feat(sanitizers)!: make sanitizers async and expose per-call codecs#546
feat(sanitizers)!: make sanitizers async and expose per-call codecs#546willkill07 wants to merge 12 commits into
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:
WalkthroughThis PR adds codec-aware contextual LLM sanitizers that receive per-call codec metadata and may omit observability payloads. The behavior is propagated through core runtime state, worker and native plugin protocols, Node, Python, Go, and PII-redaction integrations. ChangesContextual sanitizer runtime
Language and ABI integrations
PII redaction
Documentation and validation
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
License DiffCompared against Lockfile license changesLockfile License ChangesRustAdded
Removed
Updated/Changed
NodeAdded
Removed
Updated/Changed
PythonAdded
Removed
Updated/Changed
Status output |
relda88
left a comment
There was a problem hiding this comment.
Good improvement overall. One edge case: empty string vs null aren't treated the same downstream — might need a normalization step.
There was a problem hiding this comment.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
crates/core/src/api/llm.rs (1)
669-769: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueResponse-side omission gating (
payload_omitted) is logically consistent with the request-side handling and withcrates/core/src/stream.rs's streaming equivalent — decode/annotation/optimization-summary backfill are all correctly skipped when the payload is omitted.Minor:
data.as_ref().and(response_codec)(line 718) is redundant —resolve_llm_end_annotationalready early-returns(None, None)unless bothresponse_codecanddataareSome, so passingresponse_codecdirectly would be equivalent and simpler.🤖 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/core/src/api/llm.rs` around lines 669 - 769, In llm_call_end_with_behavior, simplify the resolve_llm_end_annotation call by passing response_codec directly instead of the redundant data.as_ref().and(response_codec) expression; preserve the existing data.as_ref() argument and payload_omitted gating.
🤖 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/pii-redaction/src/builtin.rs`:
- Around line 446-448: Remove the unnecessary clone in the sanitize response
flow by passing payload by move to sanitize_response_with_codec; payload is not
used after this call, and the subsequent sanitize_json_preorder_dfs mapping
should remain unchanged.
- Around line 393-457: Extract the duplicated omission warning from
llm_sanitize_request_callback and llm_sanitize_response_callback into a shared
helper that accepts the codec context and failure cause. Replace all four
log::warn! sites with this helper, preserving the existing target and context
fields while distinguishing incompatible legacy codec shape from codec
decode/sanitize/encode failure in the message.
In `@crates/python/src/py_callable.rs`:
- Around line 825-862: Add parity diagnostics to
wrap_py_contextual_llm_sanitize_response_fn for context/response serialization
failures, Python callable failures, and result conversion failures, while
retaining fail-closed None returns. Update the final PyLLMRequest extraction
path in wrap_py_contextual_llm_sanitize_request_fn to log extraction errors
before returning None, matching the existing sanitizer wrapper logging style.
In `@python/nemo_relay/guardrails.py`:
- Around line 336-358: Expand the docstrings for
register_contextual_llm_sanitize_request and
register_contextual_llm_sanitize_response to match the Args, Returns, Notes, and
Example structure used by register_llm_sanitize_request and
register_llm_sanitize_response. Document the callback signatures, context
behavior, None handling, and registration return contract without changing
either function’s implementation.
In `@python/tests/plugin/test_worker_sdk.py`:
- Around line 733-741: Remove the redundant explicit return statements from the
nested request_sanitizer and response_sanitizer callbacks, leaving their
existing request/response deletion and seen.append behavior unchanged.
---
Outside diff comments:
In `@crates/core/src/api/llm.rs`:
- Around line 669-769: In llm_call_end_with_behavior, simplify the
resolve_llm_end_annotation call by passing response_codec directly instead of
the redundant data.as_ref().and(response_codec) expression; preserve the
existing data.as_ref() argument and payload_omitted gating.
🪄 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: 7c53ccab-82b5-429b-9a78-7c6b2b4e4bed
📒 Files selected for processing (58)
crates/cli/src/gateway/mod.rscrates/core/src/api/llm.rscrates/core/src/api/registry.rscrates/core/src/api/runtime.rscrates/core/src/api/runtime/callbacks.rscrates/core/src/api/runtime/state.rscrates/core/src/codec/anthropic.rscrates/core/src/codec/openai_chat.rscrates/core/src/codec/openai_responses.rscrates/core/src/codec/traits.rscrates/core/src/context/registries.rscrates/core/src/plugin.rscrates/core/src/plugin/dynamic/native.rscrates/core/src/plugin/dynamic/worker.rscrates/core/src/stream.rscrates/core/tests/unit/context_tests.rscrates/core/tests/unit/dynamic_worker_tests.rscrates/ffi/nemo_relay.hcrates/ffi/src/api/llm_registry.rscrates/ffi/src/api/mod.rscrates/ffi/src/api/plugin.rscrates/ffi/src/callable.rscrates/node/plugin.d.tscrates/node/src/api/mod.rscrates/node/src/callable.rscrates/node/tests/llm_tests.mjscrates/pii-redaction/README.mdcrates/pii-redaction/src/builtin.rscrates/pii-redaction/src/component.rscrates/pii-redaction/tests/unit/component_tests.rscrates/plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rscrates/python/src/py_api/mod.rscrates/python/src/py_callable.rscrates/python/src/py_plugin.rscrates/worker-proto/proto/nemo/relay/worker/v1/plugin_worker.protocrates/worker/src/lib.rscrates/worker/tests/worker_sdk_tests.rsdocs/about-nemo-relay/concepts/middleware.mdxdocs/build-plugins/dynamic-plugins/grpc-worker/grpc-worker-protocol.mdxdocs/build-plugins/language-binding/about.mdxdocs/configure-plugins/pii-redaction/about.mdxdocs/configure-plugins/pii-redaction/configuration.mdxgo/nemo_relay/callbacks.gogo/nemo_relay/guardrails/guardrails.gogo/nemo_relay/llm_test.gogo/nemo_relay/nemo_relay.gogo/nemo_relay/plugin.gopython/nemo_relay/__init__.pypython/nemo_relay/__init__.pyipython/nemo_relay/_native.pyipython/nemo_relay/guardrails.pypython/nemo_relay/plugin.pypython/nemo_relay/plugin.pyipython/plugin/src/nemo_relay_plugin/__init__.pypython/plugin/src/nemo_relay_plugin/_api.pypython/tests/plugin/test_public_api_docstrings.pypython/tests/plugin/test_worker_sdk.py
💤 Files with no reviewable changes (1)
- crates/pii-redaction/README.md
📜 Review details
⏰ Context from checks skipped due to timeout. (2)
- GitHub Check: Check / Run
- GitHub Check: Preview docs
🧰 Additional context used
📓 Path-based instructions (55)
**/*.mdx
📄 CodeRabbit inference engine (.agents/skills/review-doc-style/SKILL.md)
MDX top-of-file SPDX comments must use {/* ... */} delimiters instead of HTML comment delimiters (Must-Fix)
In MDX files, top-of-file comments must use JSX comment delimiters (
{/*to open and*/}to close); do not use HTML comments for MDX SPDX headers
Files:
docs/configure-plugins/pii-redaction/about.mdxdocs/build-plugins/dynamic-plugins/grpc-worker/grpc-worker-protocol.mdxdocs/about-nemo-relay/concepts/middleware.mdxdocs/build-plugins/language-binding/about.mdxdocs/configure-plugins/pii-redaction/configuration.mdx
**/*.{md,mdx}
📄 CodeRabbit inference engine (AGENTS.md)
Update
README.md,fern/, package READMEs, and binding-support notes when public behavior, package names, examples, or supported bindings change.
**/*.{md,mdx}: Prefer the documented public API, not internal shortcuts
Keep package names, repo references, and build commands current
Keep release-process and release-notes guidance in repo-maintainer docs such asRELEASING.md, not as user-facing docs pages orCHANGELOG.md
Keep stable user-facing wrappers atscripts/root in docs and examples; only point at namespaced helper paths when documenting internal maintenance work
When detailed dynamic plugin guides exist, keep Rust native plugin examples, Python worker plugin examples, andgrpc-v1protocol details on separate pagesIf links in documentation change, run
just docs-linkcheck.
Files:
docs/configure-plugins/pii-redaction/about.mdxdocs/build-plugins/dynamic-plugins/grpc-worker/grpc-worker-protocol.mdxdocs/about-nemo-relay/concepts/middleware.mdxdocs/build-plugins/language-binding/about.mdxdocs/configure-plugins/pii-redaction/configuration.mdx
**/*.{md,markdown,mdx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Add the SPDX license header to all Markdown/MDX documentation files using the HTML comment block form.
Files:
docs/configure-plugins/pii-redaction/about.mdxdocs/build-plugins/dynamic-plugins/grpc-worker/grpc-worker-protocol.mdxdocs/about-nemo-relay/concepts/middleware.mdxdocs/build-plugins/language-binding/about.mdxdocs/configure-plugins/pii-redaction/configuration.mdx
{docs,examples}/**/*
📄 CodeRabbit inference engine (.agents/skills/rename-surfaces/SKILL.md)
Update docs and examples.
Files:
docs/configure-plugins/pii-redaction/about.mdxdocs/build-plugins/dynamic-plugins/grpc-worker/grpc-worker-protocol.mdxdocs/about-nemo-relay/concepts/middleware.mdxdocs/build-plugins/language-binding/about.mdxdocs/configure-plugins/pii-redaction/configuration.mdx
**/*
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
**/*: Format changed files with the language-native formatter before the final lint/test pass.
If dynamic plugin behavior changed, usemaintain-dynamic-pluginsand include the native SDK, worker protocol, Python SDK, docs, packaging, and Codecov surfaces in the validation plan.
If code changes alter APIs, bindings, commands, paths, packaging behavior, observability/adaptive semantics, or documented best practices, update any dependent maintainer or consumer skills in the same branch.
During iteration, preferuv run pre-commit run --files <changed files...>.
Before review or handoff, runuv run pre-commit run --all-files.
Files:
docs/configure-plugins/pii-redaction/about.mdxcrates/cli/src/gateway/mod.rspython/tests/plugin/test_public_api_docstrings.pycrates/core/tests/unit/context_tests.rscrates/core/src/api/runtime.rscrates/ffi/src/api/mod.rscrates/core/src/codec/traits.rsdocs/build-plugins/dynamic-plugins/grpc-worker/grpc-worker-protocol.mdxcrates/core/src/codec/anthropic.rsdocs/about-nemo-relay/concepts/middleware.mdxpython/nemo_relay/plugin.pycrates/node/plugin.d.tscrates/core/src/codec/openai_responses.rsdocs/build-plugins/language-binding/about.mdxpython/nemo_relay/plugin.pyicrates/core/src/codec/openai_chat.rspython/plugin/src/nemo_relay_plugin/__init__.pycrates/worker/tests/worker_sdk_tests.rscrates/core/src/context/registries.rspython/nemo_relay/__init__.pyicrates/node/tests/llm_tests.mjspython/nemo_relay/__init__.pycrates/python/src/py_api/mod.rsgo/nemo_relay/llm_test.gopython/nemo_relay/_native.pyicrates/worker-proto/proto/nemo/relay/worker/v1/plugin_worker.protogo/nemo_relay/guardrails/guardrails.gocrates/python/src/py_callable.rscrates/python/src/py_plugin.rscrates/core/src/api/runtime/callbacks.rscrates/ffi/src/api/llm_registry.rspython/tests/plugin/test_worker_sdk.pycrates/core/src/stream.rscrates/node/src/callable.rscrates/core/src/plugin/dynamic/native.rspython/nemo_relay/guardrails.pycrates/core/tests/unit/dynamic_worker_tests.rsdocs/configure-plugins/pii-redaction/configuration.mdxcrates/core/src/plugin.rscrates/node/src/api/mod.rscrates/core/src/api/registry.rsgo/nemo_relay/nemo_relay.gocrates/core/src/plugin/dynamic/worker.rspython/plugin/src/nemo_relay_plugin/_api.pycrates/pii-redaction/src/builtin.rscrates/ffi/nemo_relay.hgo/nemo_relay/plugin.gocrates/plugin/src/lib.rsgo/nemo_relay/callbacks.gocrates/core/src/api/runtime/state.rscrates/pii-redaction/src/component.rscrates/ffi/src/callable.rscrates/ffi/src/api/plugin.rscrates/worker/src/lib.rscrates/pii-redaction/tests/unit/component_tests.rscrates/core/src/api/llm.rscrates/plugin/tests/typed_callbacks.rs
docs/**/*
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
If documentation examples or commands under
docs/change, run the targeted docs checks appropriate to the change.
Files:
docs/configure-plugins/pii-redaction/about.mdxdocs/build-plugins/dynamic-plugins/grpc-worker/grpc-worker-protocol.mdxdocs/about-nemo-relay/concepts/middleware.mdxdocs/build-plugins/language-binding/about.mdxdocs/configure-plugins/pii-redaction/configuration.mdx
{docs/**,README.md,CONTRIBUTING.md,RELEASING.md,SECURITY.md}
⚙️ CodeRabbit configuration file
{docs/**,README.md,CONTRIBUTING.md,RELEASING.md,SECURITY.md}: Review documentation for technical accuracy against the current API, command correctness, and consistency across language bindings.
Flag stale examples, missing SPDX headers where required, and instructions that no longer match CI or pre-commit behavior.
Files:
docs/configure-plugins/pii-redaction/about.mdxdocs/build-plugins/dynamic-plugins/grpc-worker/grpc-worker-protocol.mdxdocs/about-nemo-relay/concepts/middleware.mdxdocs/build-plugins/language-binding/about.mdxdocs/configure-plugins/pii-redaction/configuration.mdx
**/*.rs
📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)
**/*.rs: Any Rust change must runjust test-rust
Any Rust change must runcargo fmt --all
Any Rust change must runcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Runcargo fmt --allfor all FFI work since it is Rust work
Runjust test-rustto validate FFI changes
Runcargo clippy --workspace --all-targets -- -D warningsto enforce strict linting on FFI workWhen Rust files changed as part of Go work, also run
cargo fmt --all,just test-rust, andcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Runcargo fmt --allwhen Rust files are changed as part of Node work
Runcargo clippy --workspace --all-targets -- -D warningswhen Rust files are changed as part of Node work
Runjust test-rustwhen Rust files are changed as part of Node workWhen changing the core Rust runtime or Rust-facing API surface, format Rust code with
cargo fmt(rustfmt defaults), keepcargo clippy -- -D warningsclean, and satisfycargo deny checkperdeny.toml.
**/*.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.
For Rust changes headed for review, runcargo fmt --allandcargo clippy --workspace --all-targets -- -D warningseven if relying on pre-commit.
Files:
crates/cli/src/gateway/mod.rscrates/core/tests/unit/context_tests.rscrates/core/src/api/runtime.rscrates/ffi/src/api/mod.rscrates/core/src/codec/traits.rscrates/core/src/codec/anthropic.rscrates/core/src/codec/openai_responses.rscrates/core/src/codec/openai_chat.rscrates/worker/tests/worker_sdk_tests.rscrates/core/src/context/registries.rscrates/python/src/py_api/mod.rscrates/python/src/py_callable.rscrates/python/src/py_plugin.rscrates/core/src/api/runtime/callbacks.rscrates/ffi/src/api/llm_registry.rscrates/core/src/stream.rscrates/node/src/callable.rscrates/core/src/plugin/dynamic/native.rscrates/core/tests/unit/dynamic_worker_tests.rscrates/core/src/plugin.rscrates/node/src/api/mod.rscrates/core/src/api/registry.rscrates/core/src/plugin/dynamic/worker.rscrates/pii-redaction/src/builtin.rscrates/plugin/src/lib.rscrates/core/src/api/runtime/state.rscrates/pii-redaction/src/component.rscrates/ffi/src/callable.rscrates/ffi/src/api/plugin.rscrates/worker/src/lib.rscrates/pii-redaction/tests/unit/component_tests.rscrates/core/src/api/llm.rscrates/plugin/tests/typed_callbacks.rs
**/*.{rs,py}
📄 CodeRabbit inference engine (AGENTS.md)
Follow binding naming conventions in Rust and Python: use
snake_case.
Files:
crates/cli/src/gateway/mod.rspython/tests/plugin/test_public_api_docstrings.pycrates/core/tests/unit/context_tests.rscrates/core/src/api/runtime.rscrates/ffi/src/api/mod.rscrates/core/src/codec/traits.rscrates/core/src/codec/anthropic.rspython/nemo_relay/plugin.pycrates/core/src/codec/openai_responses.rscrates/core/src/codec/openai_chat.rspython/plugin/src/nemo_relay_plugin/__init__.pycrates/worker/tests/worker_sdk_tests.rscrates/core/src/context/registries.rspython/nemo_relay/__init__.pycrates/python/src/py_api/mod.rscrates/python/src/py_callable.rscrates/python/src/py_plugin.rscrates/core/src/api/runtime/callbacks.rscrates/ffi/src/api/llm_registry.rspython/tests/plugin/test_worker_sdk.pycrates/core/src/stream.rscrates/node/src/callable.rscrates/core/src/plugin/dynamic/native.rspython/nemo_relay/guardrails.pycrates/core/tests/unit/dynamic_worker_tests.rscrates/core/src/plugin.rscrates/node/src/api/mod.rscrates/core/src/api/registry.rscrates/core/src/plugin/dynamic/worker.rspython/plugin/src/nemo_relay_plugin/_api.pycrates/pii-redaction/src/builtin.rscrates/plugin/src/lib.rscrates/core/src/api/runtime/state.rscrates/pii-redaction/src/component.rscrates/ffi/src/callable.rscrates/ffi/src/api/plugin.rscrates/worker/src/lib.rscrates/pii-redaction/tests/unit/component_tests.rscrates/core/src/api/llm.rscrates/plugin/tests/typed_callbacks.rs
**/*.{rs,py,js,mjs,cjs,ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{rs,py,js,mjs,cjs,ts,tsx}: UseJson = serde_json::Valuein Rust-facing runtime APIs where the existing code expects JSON payloads.
UseResult<T>withFlowErrorin core runtime paths, and keep errors explicit and binding-appropriate at the wrapper layer.
Keep async behavior on the existing tokio-based model; bindings should preserve callback and future lifetimes rather than blocking or hiding async work unexpectedly.
Files:
crates/cli/src/gateway/mod.rspython/tests/plugin/test_public_api_docstrings.pycrates/core/tests/unit/context_tests.rscrates/core/src/api/runtime.rscrates/ffi/src/api/mod.rscrates/core/src/codec/traits.rscrates/core/src/codec/anthropic.rspython/nemo_relay/plugin.pycrates/node/plugin.d.tscrates/core/src/codec/openai_responses.rscrates/core/src/codec/openai_chat.rspython/plugin/src/nemo_relay_plugin/__init__.pycrates/worker/tests/worker_sdk_tests.rscrates/core/src/context/registries.rscrates/node/tests/llm_tests.mjspython/nemo_relay/__init__.pycrates/python/src/py_api/mod.rscrates/python/src/py_callable.rscrates/python/src/py_plugin.rscrates/core/src/api/runtime/callbacks.rscrates/ffi/src/api/llm_registry.rspython/tests/plugin/test_worker_sdk.pycrates/core/src/stream.rscrates/node/src/callable.rscrates/core/src/plugin/dynamic/native.rspython/nemo_relay/guardrails.pycrates/core/tests/unit/dynamic_worker_tests.rscrates/core/src/plugin.rscrates/node/src/api/mod.rscrates/core/src/api/registry.rscrates/core/src/plugin/dynamic/worker.rspython/plugin/src/nemo_relay_plugin/_api.pycrates/pii-redaction/src/builtin.rscrates/plugin/src/lib.rscrates/core/src/api/runtime/state.rscrates/pii-redaction/src/component.rscrates/ffi/src/callable.rscrates/ffi/src/api/plugin.rscrates/worker/src/lib.rscrates/pii-redaction/tests/unit/component_tests.rscrates/core/src/api/llm.rscrates/plugin/tests/typed_callbacks.rs
**/*.{rs,py,go,js,ts,c,h}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Use language-appropriate naming conventions: Rust
snake_case, C FFI exports prefixednemo_relay_, GoPascalCase, Node.jscamelCase, and Pythonsnake_case.
Files:
crates/cli/src/gateway/mod.rspython/tests/plugin/test_public_api_docstrings.pycrates/core/tests/unit/context_tests.rscrates/core/src/api/runtime.rscrates/ffi/src/api/mod.rscrates/core/src/codec/traits.rscrates/core/src/codec/anthropic.rspython/nemo_relay/plugin.pycrates/node/plugin.d.tscrates/core/src/codec/openai_responses.rscrates/core/src/codec/openai_chat.rspython/plugin/src/nemo_relay_plugin/__init__.pycrates/worker/tests/worker_sdk_tests.rscrates/core/src/context/registries.rspython/nemo_relay/__init__.pycrates/python/src/py_api/mod.rsgo/nemo_relay/llm_test.gogo/nemo_relay/guardrails/guardrails.gocrates/python/src/py_callable.rscrates/python/src/py_plugin.rscrates/core/src/api/runtime/callbacks.rscrates/ffi/src/api/llm_registry.rspython/tests/plugin/test_worker_sdk.pycrates/core/src/stream.rscrates/node/src/callable.rscrates/core/src/plugin/dynamic/native.rspython/nemo_relay/guardrails.pycrates/core/tests/unit/dynamic_worker_tests.rscrates/core/src/plugin.rscrates/node/src/api/mod.rscrates/core/src/api/registry.rsgo/nemo_relay/nemo_relay.gocrates/core/src/plugin/dynamic/worker.rspython/plugin/src/nemo_relay_plugin/_api.pycrates/pii-redaction/src/builtin.rscrates/ffi/nemo_relay.hgo/nemo_relay/plugin.gocrates/plugin/src/lib.rsgo/nemo_relay/callbacks.gocrates/core/src/api/runtime/state.rscrates/pii-redaction/src/component.rscrates/ffi/src/callable.rscrates/ffi/src/api/plugin.rscrates/worker/src/lib.rscrates/pii-redaction/tests/unit/component_tests.rscrates/core/src/api/llm.rscrates/plugin/tests/typed_callbacks.rs
**/*.{rs,go,js,ts}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Add the SPDX license header to all Rust, Go, JavaScript, and TypeScript source files using the corresponding
//comment form.
Files:
crates/cli/src/gateway/mod.rscrates/core/tests/unit/context_tests.rscrates/core/src/api/runtime.rscrates/ffi/src/api/mod.rscrates/core/src/codec/traits.rscrates/core/src/codec/anthropic.rscrates/node/plugin.d.tscrates/core/src/codec/openai_responses.rscrates/core/src/codec/openai_chat.rscrates/worker/tests/worker_sdk_tests.rscrates/core/src/context/registries.rscrates/python/src/py_api/mod.rsgo/nemo_relay/llm_test.gogo/nemo_relay/guardrails/guardrails.gocrates/python/src/py_callable.rscrates/python/src/py_plugin.rscrates/core/src/api/runtime/callbacks.rscrates/ffi/src/api/llm_registry.rscrates/core/src/stream.rscrates/node/src/callable.rscrates/core/src/plugin/dynamic/native.rscrates/core/tests/unit/dynamic_worker_tests.rscrates/core/src/plugin.rscrates/node/src/api/mod.rscrates/core/src/api/registry.rsgo/nemo_relay/nemo_relay.gocrates/core/src/plugin/dynamic/worker.rscrates/pii-redaction/src/builtin.rsgo/nemo_relay/plugin.gocrates/plugin/src/lib.rsgo/nemo_relay/callbacks.gocrates/core/src/api/runtime/state.rscrates/pii-redaction/src/component.rscrates/ffi/src/callable.rscrates/ffi/src/api/plugin.rscrates/worker/src/lib.rscrates/pii-redaction/tests/unit/component_tests.rscrates/core/src/api/llm.rscrates/plugin/tests/typed_callbacks.rs
{crates/**/src/**/*.rs,python/**/*.py}
📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)
Do not add tests under
src; Rust tests belong in cratetests/trees, and Python SDK tests belong underpython/tests.
Files:
crates/cli/src/gateway/mod.rspython/tests/plugin/test_public_api_docstrings.pycrates/core/src/api/runtime.rscrates/ffi/src/api/mod.rscrates/core/src/codec/traits.rscrates/core/src/codec/anthropic.rspython/nemo_relay/plugin.pycrates/core/src/codec/openai_responses.rscrates/core/src/codec/openai_chat.rspython/plugin/src/nemo_relay_plugin/__init__.pycrates/core/src/context/registries.rspython/nemo_relay/__init__.pycrates/python/src/py_api/mod.rscrates/python/src/py_callable.rscrates/python/src/py_plugin.rscrates/core/src/api/runtime/callbacks.rscrates/ffi/src/api/llm_registry.rspython/tests/plugin/test_worker_sdk.pycrates/core/src/stream.rscrates/node/src/callable.rscrates/core/src/plugin/dynamic/native.rspython/nemo_relay/guardrails.pycrates/core/src/plugin.rscrates/node/src/api/mod.rscrates/core/src/api/registry.rscrates/core/src/plugin/dynamic/worker.rspython/plugin/src/nemo_relay_plugin/_api.pycrates/pii-redaction/src/builtin.rscrates/plugin/src/lib.rscrates/core/src/api/runtime/state.rscrates/pii-redaction/src/component.rscrates/ffi/src/callable.rscrates/ffi/src/api/plugin.rscrates/worker/src/lib.rscrates/core/src/api/llm.rs
**/*.{rs,py,go,js,ts}
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
If a language surface changed, always run that language's test target even when Rust core did not change.
Files:
crates/cli/src/gateway/mod.rspython/tests/plugin/test_public_api_docstrings.pycrates/core/tests/unit/context_tests.rscrates/core/src/api/runtime.rscrates/ffi/src/api/mod.rscrates/core/src/codec/traits.rscrates/core/src/codec/anthropic.rspython/nemo_relay/plugin.pycrates/node/plugin.d.tscrates/core/src/codec/openai_responses.rscrates/core/src/codec/openai_chat.rspython/plugin/src/nemo_relay_plugin/__init__.pycrates/worker/tests/worker_sdk_tests.rscrates/core/src/context/registries.rspython/nemo_relay/__init__.pycrates/python/src/py_api/mod.rsgo/nemo_relay/llm_test.gogo/nemo_relay/guardrails/guardrails.gocrates/python/src/py_callable.rscrates/python/src/py_plugin.rscrates/core/src/api/runtime/callbacks.rscrates/ffi/src/api/llm_registry.rspython/tests/plugin/test_worker_sdk.pycrates/core/src/stream.rscrates/node/src/callable.rscrates/core/src/plugin/dynamic/native.rspython/nemo_relay/guardrails.pycrates/core/tests/unit/dynamic_worker_tests.rscrates/core/src/plugin.rscrates/node/src/api/mod.rscrates/core/src/api/registry.rsgo/nemo_relay/nemo_relay.gocrates/core/src/plugin/dynamic/worker.rspython/plugin/src/nemo_relay_plugin/_api.pycrates/pii-redaction/src/builtin.rsgo/nemo_relay/plugin.gocrates/plugin/src/lib.rsgo/nemo_relay/callbacks.gocrates/core/src/api/runtime/state.rscrates/pii-redaction/src/component.rscrates/ffi/src/callable.rscrates/ffi/src/api/plugin.rscrates/worker/src/lib.rscrates/pii-redaction/tests/unit/component_tests.rscrates/core/src/api/llm.rscrates/plugin/tests/typed_callbacks.rs
**/*.{rs,py,js,ts,tsx,go,java,kt,swift}
📄 CodeRabbit inference engine (.agents/skills/add-middleware/SKILL.md)
Add tests covering registration and duplicate names, deregistration and missing names, priority ordering, callback failure policy, scope-local inheritance and cleanup, event payload semantics, immutable mark and scope fields, and parity across affected bindings.
Files:
crates/cli/src/gateway/mod.rspython/tests/plugin/test_public_api_docstrings.pycrates/core/tests/unit/context_tests.rscrates/core/src/api/runtime.rscrates/ffi/src/api/mod.rscrates/core/src/codec/traits.rscrates/core/src/codec/anthropic.rspython/nemo_relay/plugin.pycrates/node/plugin.d.tscrates/core/src/codec/openai_responses.rscrates/core/src/codec/openai_chat.rspython/plugin/src/nemo_relay_plugin/__init__.pycrates/worker/tests/worker_sdk_tests.rscrates/core/src/context/registries.rspython/nemo_relay/__init__.pycrates/python/src/py_api/mod.rsgo/nemo_relay/llm_test.gogo/nemo_relay/guardrails/guardrails.gocrates/python/src/py_callable.rscrates/python/src/py_plugin.rscrates/core/src/api/runtime/callbacks.rscrates/ffi/src/api/llm_registry.rspython/tests/plugin/test_worker_sdk.pycrates/core/src/stream.rscrates/node/src/callable.rscrates/core/src/plugin/dynamic/native.rspython/nemo_relay/guardrails.pycrates/core/tests/unit/dynamic_worker_tests.rscrates/core/src/plugin.rscrates/node/src/api/mod.rscrates/core/src/api/registry.rsgo/nemo_relay/nemo_relay.gocrates/core/src/plugin/dynamic/worker.rspython/plugin/src/nemo_relay_plugin/_api.pycrates/pii-redaction/src/builtin.rsgo/nemo_relay/plugin.gocrates/plugin/src/lib.rsgo/nemo_relay/callbacks.gocrates/core/src/api/runtime/state.rscrates/pii-redaction/src/component.rscrates/ffi/src/callable.rscrates/ffi/src/api/plugin.rscrates/worker/src/lib.rscrates/pii-redaction/tests/unit/component_tests.rscrates/core/src/api/llm.rscrates/plugin/tests/typed_callbacks.rs
**/*.py
📄 CodeRabbit inference engine (CONTRIBUTING.md)
**/*.py: When changing the Python wrapper package, tests, or docs tooling, lint with Ruff (E,F,W,I), format with Ruff formatter (120-character lines, double quotes), and passtytype checking.
Add the SPDX license header to all Python source files using the#comment form.
Files:
python/tests/plugin/test_public_api_docstrings.pypython/nemo_relay/plugin.pypython/plugin/src/nemo_relay_plugin/__init__.pypython/nemo_relay/__init__.pypython/tests/plugin/test_worker_sdk.pypython/nemo_relay/guardrails.pypython/plugin/src/nemo_relay_plugin/_api.py
**/*.{py,go,js,ts}
📄 CodeRabbit inference engine (.agents/skills/maintain-observability/SKILL.md)
Keep Python, Go, and Node.js config objects and subscriber/exporter methods aligned so all bindings expose the same logical knobs and semantics.
Files:
python/tests/plugin/test_public_api_docstrings.pypython/nemo_relay/plugin.pycrates/node/plugin.d.tspython/plugin/src/nemo_relay_plugin/__init__.pypython/nemo_relay/__init__.pygo/nemo_relay/llm_test.gogo/nemo_relay/guardrails/guardrails.gopython/tests/plugin/test_worker_sdk.pypython/nemo_relay/guardrails.pygo/nemo_relay/nemo_relay.gopython/plugin/src/nemo_relay_plugin/_api.pygo/nemo_relay/plugin.gogo/nemo_relay/callbacks.go
python/tests/**/*.py
📄 CodeRabbit inference engine (.agents/skills/test-python-binding/SKILL.md)
python/tests/**/*.py: Pytest is used to run tests.
Do not add@pytest.mark.asyncioto any test; async tests are automatically detected and run by the async runner.
Do not add a-> Nonereturn type annotation to test functions.
When mocking a class, do not define a new class; useunittest.mock.MagicMockorunittest.mock.AsyncMock, with thespecconstructor argument when necessary.
Name mocked classes with themockprefix, notfake.
Prefer pytest fixtures over helper methods.
Do not repeat fixtures; if a fixture is needed in multiple test files, place it in aconftest.pyfile.
When creating a fixture, use@pytest.fixture(name="<fixture_name>"[, scope="<scope>"])and define the fixture function asdef <fixture_name>_fixture() -> <return_type>:; only specifyscopewhen it is notfunction.
Preferpytest.mark.parametrizeover creating individual tests for different input types.
Files:
python/tests/plugin/test_public_api_docstrings.pypython/tests/plugin/test_worker_sdk.py
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}
⚙️ CodeRabbit configuration file
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}: Tests should cover the behavior promised by the changed API surface, including error paths and cross-request isolation where relevant.
Prefer assertions on lifecycle events, scope stacks, middleware ordering, and binding parity over shallow smoke tests.
Files:
python/tests/plugin/test_public_api_docstrings.pycrates/core/tests/unit/context_tests.rscrates/worker/tests/worker_sdk_tests.rscrates/node/tests/llm_tests.mjsgo/nemo_relay/llm_test.gopython/tests/plugin/test_worker_sdk.pycrates/core/tests/unit/dynamic_worker_tests.rscrates/pii-redaction/tests/unit/component_tests.rscrates/plugin/tests/typed_callbacks.rs
{crates/core,crates/adaptive}/**/*
📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)
Changes to
crates/coreorcrates/adaptivemust run the full language matrix
Files:
crates/core/tests/unit/context_tests.rscrates/core/src/api/runtime.rscrates/core/src/codec/traits.rscrates/core/src/codec/anthropic.rscrates/core/src/codec/openai_responses.rscrates/core/src/codec/openai_chat.rscrates/core/src/context/registries.rscrates/core/src/api/runtime/callbacks.rscrates/core/src/stream.rscrates/core/src/plugin/dynamic/native.rscrates/core/tests/unit/dynamic_worker_tests.rscrates/core/src/plugin.rscrates/core/src/api/registry.rscrates/core/src/plugin/dynamic/worker.rscrates/core/src/api/runtime/state.rscrates/core/src/api/llm.rs
crates/core/**/*.rs
📄 CodeRabbit inference engine (.agents/skills/test-go-binding/SKILL.md)
If the change touched
crates/coreor shared runtime semantics, also usevalidate-changefor broader validation
Files:
crates/core/tests/unit/context_tests.rscrates/core/src/api/runtime.rscrates/core/src/codec/traits.rscrates/core/src/codec/anthropic.rscrates/core/src/codec/openai_responses.rscrates/core/src/codec/openai_chat.rscrates/core/src/context/registries.rscrates/core/src/api/runtime/callbacks.rscrates/core/src/stream.rscrates/core/src/plugin/dynamic/native.rscrates/core/tests/unit/dynamic_worker_tests.rscrates/core/src/plugin.rscrates/core/src/api/registry.rscrates/core/src/plugin/dynamic/worker.rscrates/core/src/api/runtime/state.rscrates/core/src/api/llm.rs
crates/{core,adaptive}/**/*
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
If
crates/coreorcrates/adaptivechanged, run the full validation matrix across Rust, Python, Go, and Node.js.
Files:
crates/core/tests/unit/context_tests.rscrates/core/src/api/runtime.rscrates/core/src/codec/traits.rscrates/core/src/codec/anthropic.rscrates/core/src/codec/openai_responses.rscrates/core/src/codec/openai_chat.rscrates/core/src/context/registries.rscrates/core/src/api/runtime/callbacks.rscrates/core/src/stream.rscrates/core/src/plugin/dynamic/native.rscrates/core/tests/unit/dynamic_worker_tests.rscrates/core/src/plugin.rscrates/core/src/api/registry.rscrates/core/src/plugin/dynamic/worker.rscrates/core/src/api/runtime/state.rscrates/core/src/api/llm.rs
crates/{core,adaptive}/**/*.rs
⚙️ CodeRabbit configuration file
crates/{core,adaptive}/**/*.rs: Review the Rust runtime for async correctness, scope isolation, middleware ordering, and event lifecycle regressions.
Pay close attention to task-local/thread-local scope propagation, callback lifetimes, stream finalization, and root_uuid isolation.
Public API changes should preserve existing behavior unless tests and docs show the intended migration path.
Files:
crates/core/tests/unit/context_tests.rscrates/core/src/api/runtime.rscrates/core/src/codec/traits.rscrates/core/src/codec/anthropic.rscrates/core/src/codec/openai_responses.rscrates/core/src/codec/openai_chat.rscrates/core/src/context/registries.rscrates/core/src/api/runtime/callbacks.rscrates/core/src/stream.rscrates/core/src/plugin/dynamic/native.rscrates/core/tests/unit/dynamic_worker_tests.rscrates/core/src/plugin.rscrates/core/src/api/registry.rscrates/core/src/plugin/dynamic/worker.rscrates/core/src/api/runtime/state.rscrates/core/src/api/llm.rs
crates/core/src/{api/**/*.rs,api/runtime/**/*.rs,codec/**/*.rs,json.rs}
📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)
Implement the new or changed public runtime behavior first in the Rust core, especially under
crates/core/src/api/and related core modules such ascrates/core/src/api/runtime/,crates/core/src/codec/, andcrates/core/src/json.rs.
Files:
crates/core/src/api/runtime.rscrates/core/src/codec/traits.rscrates/core/src/codec/anthropic.rscrates/core/src/codec/openai_responses.rscrates/core/src/codec/openai_chat.rscrates/core/src/api/runtime/callbacks.rscrates/core/src/api/registry.rscrates/core/src/api/runtime/state.rscrates/core/src/api/llm.rs
crates/core/src/api/**/*.rs
📄 CodeRabbit inference engine (.agents/skills/add-middleware/SKILL.md)
Preserve the documented pipeline order: conditional guardrails, request intercepts, request sanitization, execution intercepts, and response sanitization for tool and LLM execution; specialized sanitization, event creation, and dispatch for mark and scope events.
Files:
crates/core/src/api/runtime.rscrates/core/src/api/runtime/callbacks.rscrates/core/src/api/registry.rscrates/core/src/api/runtime/state.rscrates/core/src/api/llm.rs
crates/ffi/**
📄 CodeRabbit inference engine (.agents/skills/test-ffi-surface/SKILL.md)
Rebuild the FFI crate in release mode so the shared library and header stay in sync when making changes to crates/ffi
Files:
crates/ffi/src/api/mod.rscrates/ffi/src/api/llm_registry.rscrates/ffi/nemo_relay.hcrates/ffi/src/callable.rscrates/ffi/src/api/plugin.rs
crates/ffi/**/*.rs
📄 CodeRabbit inference engine (.agents/skills/test-go-binding/SKILL.md)
If the change touched
crates/ffi, also usetest-ffi-surfacefor validationUse C FFI export names prefixed with
nemo_relay_in the raw C FFI layer.
Files:
crates/ffi/src/api/mod.rscrates/ffi/src/api/llm_registry.rscrates/ffi/src/callable.rscrates/ffi/src/api/plugin.rs
{crates/ffi/src/api/*.rs,crates/ffi/nemo_relay.h}
📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)
Add or update the shared C/FFI surface in the relevant
crates/ffi/src/api/*.rsmodule, re-export it throughcrates/ffi/src/api/mod.rs, and keep the generatedcrates/ffi/nemo_relay.hheader correct.
Files:
crates/ffi/src/api/mod.rscrates/ffi/src/api/llm_registry.rscrates/ffi/nemo_relay.hcrates/ffi/src/api/plugin.rs
crates/{python,ffi,node}/**/*
⚙️ CodeRabbit configuration file
crates/{python,ffi,node}/**/*: Treat binding changes as public API changes. Check for parity with the other language bindings, FFI ownership/lifetime safety,
callback error propagation, stable type conversion, and consistent async/stream semantics.
Flag changes that update one binding without corresponding tests or documentation for the same surface elsewhere.
Files:
crates/ffi/src/api/mod.rscrates/node/plugin.d.tscrates/node/tests/llm_tests.mjscrates/python/src/py_api/mod.rscrates/python/src/py_callable.rscrates/python/src/py_plugin.rscrates/ffi/src/api/llm_registry.rscrates/node/src/callable.rscrates/node/src/api/mod.rscrates/ffi/nemo_relay.hcrates/ffi/src/callable.rscrates/ffi/src/api/plugin.rs
{crates/core/src/plugin/dynamic/**,crates/plugin/**,crates/worker/**,crates/worker-proto/**,crates/types/**,python/plugin/**,examples/rust-native-plugin/**,examples/python-grpc-worker-plugin/**,docs/build-plugins/**}
📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)
Keep the stable boundary explicit: native plugins cross a C ABI, and worker plugins cross
grpc-v1.
Files:
docs/build-plugins/dynamic-plugins/grpc-worker/grpc-worker-protocol.mdxdocs/build-plugins/language-binding/about.mdxpython/plugin/src/nemo_relay_plugin/__init__.pycrates/worker/tests/worker_sdk_tests.rscrates/worker-proto/proto/nemo/relay/worker/v1/plugin_worker.protocrates/core/src/plugin/dynamic/native.rscrates/core/src/plugin/dynamic/worker.rspython/plugin/src/nemo_relay_plugin/_api.pycrates/plugin/src/lib.rscrates/worker/src/lib.rscrates/plugin/tests/typed_callbacks.rs
{crates/core/src/plugin/dynamic/**,examples/rust-native-plugin/**,examples/python-grpc-worker-plugin/**,docs/build-plugins/**}
📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)
Native and worker plugins are trusted extensions; document that native plugins are in-process and unsandboxed, and worker plugins provide process isolation but not a security sandbox.
Files:
docs/build-plugins/dynamic-plugins/grpc-worker/grpc-worker-protocol.mdxdocs/build-plugins/language-binding/about.mdxcrates/core/src/plugin/dynamic/native.rscrates/core/src/plugin/dynamic/worker.rs
{docs/build-plugins/**,examples/rust-native-plugin/**,examples/python-grpc-worker-plugin/**}
📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)
When detailed dynamic plugin guides exist, keep Rust native, Python worker, and
grpc-v1protocol details on separate pages.
Files:
docs/build-plugins/dynamic-plugins/grpc-worker/grpc-worker-protocol.mdxdocs/build-plugins/language-binding/about.mdx
python/nemo_relay/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Python wrapper modules live under
python/nemo_relay/, and the native extension is built fromcrates/pythonwithmaturin.
Files:
python/nemo_relay/plugin.pypython/nemo_relay/__init__.pypython/nemo_relay/guardrails.py
{crates/python/src/py_api/mod.rs,python/nemo_relay/**/*.py,python/nemo_relay/**/*.pyi,go/nemo_relay/**/*.go,crates/node/src/api/**/*.rs}
📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)
Update the language-native bindings for every exposed surface in Python, Go, and Node.js.
Files:
python/nemo_relay/plugin.pypython/nemo_relay/plugin.pyipython/nemo_relay/__init__.pyipython/nemo_relay/__init__.pycrates/python/src/py_api/mod.rsgo/nemo_relay/llm_test.gopython/nemo_relay/_native.pyigo/nemo_relay/guardrails/guardrails.gopython/nemo_relay/guardrails.pycrates/node/src/api/mod.rsgo/nemo_relay/nemo_relay.gogo/nemo_relay/plugin.gogo/nemo_relay/callbacks.go
{python/nemo_relay/**/*.py,python/nemo_relay/**/*.pyi,go/nemo_relay/**/*.go}
📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)
Update language wrapper helpers such as Python wrapper modules, Python type stubs, and Go shorthand packages when the new behavior belongs in those helper layers.
Files:
python/nemo_relay/plugin.pypython/nemo_relay/plugin.pyipython/nemo_relay/__init__.pyipython/nemo_relay/__init__.pygo/nemo_relay/llm_test.gopython/nemo_relay/_native.pyigo/nemo_relay/guardrails/guardrails.gopython/nemo_relay/guardrails.pygo/nemo_relay/nemo_relay.gogo/nemo_relay/plugin.gogo/nemo_relay/callbacks.go
python/nemo_relay/{adaptive.py,plugin.py}
📄 CodeRabbit inference engine (.agents/skills/maintain-optimizer/SKILL.md)
Keep Python adaptive/plugin wrappers in
python/nemo_relay/adaptive.pyandpython/nemo_relay/plugin.pysynchronized with the shared adaptive/plugin boundary and lifecycle.
Files:
python/nemo_relay/plugin.py
python/nemo_relay/**/*
⚙️ CodeRabbit configuration file
python/nemo_relay/**/*: Review Python wrapper changes for typed API consistency, contextvars-based scope isolation, async behavior, and parity with the native extension.
Stubs and runtime implementations should stay aligned.
Files:
python/nemo_relay/plugin.pypython/nemo_relay/plugin.pyipython/nemo_relay/__init__.pyipython/nemo_relay/__init__.pypython/nemo_relay/_native.pyipython/nemo_relay/guardrails.py
crates/node/**/*.{js,ts,jsx,tsx,json}
📄 CodeRabbit inference engine (.agents/skills/test-node-binding/SKILL.md)
Format changed Node files with
npm run format --workspace=nemo-relay-node
Files:
crates/node/plugin.d.ts
crates/node/**/*.{ts,tsx,d.ts}
📄 CodeRabbit inference engine (.agents/skills/test-node-binding/SKILL.md)
Use
npm run check:docstrings --workspace=nemo-relay-nodeto validate public API docstring checks when surface docs changed
Files:
crates/node/plugin.d.ts
crates/node/**/*.{js,mjs,cjs,ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use
camelCasefor Node.js public APIs.
Files:
crates/node/plugin.d.tscrates/node/tests/llm_tests.mjs
{crates/core/src/plugin/dynamic/**/*.rs,crates/plugin/**/*.rs,crates/worker/**/*.rs,crates/worker-proto/**/*.rs,python/plugin/**/*.py}
📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)
Manifest validation must cover kind, compatibility, load contract, integrity, capability mismatch, and disabled-plugin behavior.
Files:
python/plugin/src/nemo_relay_plugin/__init__.pycrates/worker/tests/worker_sdk_tests.rscrates/core/src/plugin/dynamic/native.rscrates/core/src/plugin/dynamic/worker.rspython/plugin/src/nemo_relay_plugin/_api.pycrates/plugin/src/lib.rscrates/worker/src/lib.rscrates/plugin/tests/typed_callbacks.rs
{crates/plugin/**/*.rs,python/plugin/**/*.py}
📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)
Rust and Python SDKs must expose every supported registration surface.
Files:
python/plugin/src/nemo_relay_plugin/__init__.pypython/plugin/src/nemo_relay_plugin/_api.pycrates/plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rs
{crates/worker-proto/**/*.{rs,proto},crates/worker/**/*.rs}
📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)
Keep worker protocol DTOs in
JsonEnvelope; protobuf should own control flow, not duplicated Relay data models.
Files:
crates/worker/tests/worker_sdk_tests.rscrates/worker-proto/proto/nemo/relay/worker/v1/plugin_worker.protocrates/worker/src/lib.rs
crates/worker/**/*.rs
📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)
Worker activation must cover process launch, token authentication, handshake, validation, declarative registration, proxy rollback, cancellation, and shutdown.
Files:
crates/worker/tests/worker_sdk_tests.rscrates/worker/src/lib.rs
go/nemo_relay/**/*.go
📄 CodeRabbit inference engine (.agents/skills/test-go-binding/SKILL.md)
go/nemo_relay/**/*.go: Format changed Go packages withcd go/nemo_relay && go fmt ./...
Run Go tests withjust test-goto build and test the NeMo Relay Go binding
Usejust build-gowhen you want an explicit build-only pass or need the artifact for other work
Usejust ci=true test-gowhen you need the CI-style coverage and JUnit path
On macOS, setDYLD_LIBRARY_PATHto the../../target/releasedirectory before running the rawgo testcommand directlyUse
PascalCasefor public Go APIs.
Files:
go/nemo_relay/llm_test.gogo/nemo_relay/guardrails/guardrails.gogo/nemo_relay/nemo_relay.gogo/nemo_relay/plugin.gogo/nemo_relay/callbacks.go
**/*.go
📄 CodeRabbit inference engine (CONTRIBUTING.md)
When changing the experimental Go binding, format Go code with
gofmtand keepgo vet ./...passing.
Files:
go/nemo_relay/llm_test.gogo/nemo_relay/guardrails/guardrails.gogo/nemo_relay/nemo_relay.gogo/nemo_relay/plugin.gogo/nemo_relay/callbacks.go
go/nemo_relay/**
📄 CodeRabbit inference engine (.agents/skills/maintain-optimizer/SKILL.md)
Keep shared plugin helpers in
go/nemo_relayaligned with plugin registration, composition, and lifecycle behavior.
Files:
go/nemo_relay/llm_test.gogo/nemo_relay/guardrails/guardrails.gogo/nemo_relay/nemo_relay.gogo/nemo_relay/plugin.gogo/nemo_relay/callbacks.go
go/nemo_relay/**/*
⚙️ CodeRabbit configuration file
go/nemo_relay/**/*: Review Go binding changes for cgo memory ownership, race safety, callback cleanup, idiomatic exported APIs, and parity with Rust/FFI behavior.
Any API change should include focused Go tests and consider race-test behavior.
Files:
go/nemo_relay/llm_test.gogo/nemo_relay/guardrails/guardrails.gogo/nemo_relay/nemo_relay.gogo/nemo_relay/plugin.gogo/nemo_relay/callbacks.go
crates/core/src/api/runtime/callbacks.rs
📄 CodeRabbit inference engine (.agents/skills/add-middleware/SKILL.md)
Define or reuse the middleware callback type alias in
crates/core/src/api/runtime/callbacks.rs, using the appropriate callable signature and thread-safety bounds.
Files:
crates/core/src/api/runtime/callbacks.rs
{crates/core/src/plugin/dynamic/**/*.rs,examples/rust-native-plugin/**/*.rs}
📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)
Do not pass Rust runtime types, trait objects, futures, or allocator-owned strings across the native dynamic-library boundary.
Files:
crates/core/src/plugin/dynamic/native.rscrates/core/src/plugin/dynamic/worker.rs
crates/core/src/plugin/dynamic/**/*.rs
📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)
The native loader must keep libraries alive until registered callbacks are cleared and must deregister plugin kinds before unload.
Files:
crates/core/src/plugin/dynamic/native.rscrates/core/src/plugin/dynamic/worker.rs
crates/core/src/api/registry.rs
📄 CodeRabbit inference engine (.agents/skills/add-middleware/SKILL.md)
Add global and scope-local registration and deregistration APIs using the existing
global_*_registry_api!andscope_*_registry_api!macro patterns, unless the design explicitly excludes one scope.
Files:
crates/core/src/api/registry.rs
crates/ffi/nemo_relay.h
📄 CodeRabbit inference engine (.agents/skills/test-ffi-surface/SKILL.md)
Check the generated header diff when any exported symbol or type changed in the FFI surface
Update generated or generated-from-build surfaces such as
crates/ffi/nemo_relay.hthrough the proper build step.
Files:
crates/ffi/nemo_relay.h
crates/core/src/api/runtime/state.rs
📄 CodeRabbit inference engine (.agents/skills/add-middleware/SKILL.md)
crates/core/src/api/runtime/state.rs: Add aSortedRegistry<GuardrailEntry<...>>orSortedRegistry<Intercept<...>>field toNemoRelayContextStatefor the new middleware type.
Add chain-execution helpers toNemoRelayContextState, following existing helpers such astool_sanitize_request_chainortool_request_intercepts_chain.
Files:
crates/core/src/api/runtime/state.rs
crates/core/src/api/{tool,llm,shared,scope}.rs
📄 CodeRabbit inference engine (.agents/skills/add-middleware/SKILL.md)
Wire the new middleware chain into the appropriate lifecycle owner and pipeline stage: tool and LLM execution paths use
tool.rsorllm.rs; shared mark and scope event sanitization usesshared.rsand is called fromscope.rs.
Files:
crates/core/src/api/llm.rs
🧠 Learnings (1)
📚 Learning: 2026-05-07T18:04:44.387Z
Learnt from: mnajafian-nv
Repo: NVIDIA/NeMo-Flow PR: 67
File: integrations/openclaw/src/modules.ts:1-2
Timestamp: 2026-05-07T18:04:44.387Z
Learning: In NVIDIA/NeMo-Flow, TypeScript source files should use `//` line comments for SPDX headers (e.g., `// SPDX-FileCopyrightText: ...` and `// SPDX-License-Identifier: ...`) rather than C-style block comments (`/* ... */`). The repo’s copyright checker enforces this mapping, so `//` SPDX headers in `.ts` files should not be flagged as a style violation.
Applied to files:
crates/node/plugin.d.ts
🪛 Ruff (0.15.21)
python/tests/plugin/test_worker_sdk.py
[warning] 736-736: Do not explicitly return None in function if it is the only possible return value
Remove explicit return None
(RET501)
[warning] 736-736: Useless return statement at end of function
Remove useless return statement
(PLR1711)
[warning] 741-741: Do not explicitly return None in function if it is the only possible return value
Remove explicit return None
(RET501)
[warning] 741-741: Useless return statement at end of function
Remove useless return statement
(PLR1711)
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
crates/core/src/api/llm.rs (1)
431-466: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick winTie annotations to the sanitized payload before publishing events.
Both paths can retain annotations created from the original payload after contextual sanitization changes or omits that payload.
crates/core/src/api/llm.rs#L431-L466: clearannotated_requestwhen the request changes and cannot be safely re-decoded.crates/core/src/api/llm.rs#L702-L723: clear or regenerateannotated_responseunless it is guaranteed to describe the sanitized response.🤖 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/core/src/api/llm.rs` around lines 431 - 466, Ensure published annotations always describe the sanitized payload: in crates/core/src/api/llm.rs:431-466, clear annotated_request when sanitization changes the request but codec decoding fails, rather than retaining annotations from the original request; in crates/core/src/api/llm.rs:702-723, clear or regenerate annotated_response unless it is guaranteed to correspond to the sanitized response before building the event.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@crates/core/src/api/llm.rs`:
- Around line 431-466: Ensure published annotations always describe the
sanitized payload: in crates/core/src/api/llm.rs:431-466, clear
annotated_request when sanitization changes the request but codec decoding
fails, rather than retaining annotations from the original request; in
crates/core/src/api/llm.rs:702-723, clear or regenerate annotated_response
unless it is guaranteed to correspond to the sanitized response before building
the event.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Enterprise
Run ID: 4069591c-b48f-42dc-b657-5e4158d4e367
📒 Files selected for processing (7)
crates/core/src/api/llm.rscrates/pii-redaction/src/builtin.rscrates/python/src/py_callable.rscrates/worker/src/lib.rspython/nemo_relay/guardrails.pypython/plugin/src/nemo_relay_plugin/_api.pypython/tests/plugin/test_worker_sdk.py
📜 Review details
🧰 Additional context used
📓 Path-based instructions (30)
**/*.{rs,py}
📄 CodeRabbit inference engine (AGENTS.md)
Follow binding naming conventions in Rust and Python: use
snake_case.
Files:
python/nemo_relay/guardrails.pycrates/python/src/py_callable.rspython/tests/plugin/test_worker_sdk.pycrates/core/src/api/llm.rscrates/worker/src/lib.rscrates/pii-redaction/src/builtin.rspython/plugin/src/nemo_relay_plugin/_api.py
**/*.{rs,py,js,mjs,cjs,ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{rs,py,js,mjs,cjs,ts,tsx}: UseJson = serde_json::Valuein Rust-facing runtime APIs where the existing code expects JSON payloads.
UseResult<T>withFlowErrorin core runtime paths, and keep errors explicit and binding-appropriate at the wrapper layer.
Keep async behavior on the existing tokio-based model; bindings should preserve callback and future lifetimes rather than blocking or hiding async work unexpectedly.
Files:
python/nemo_relay/guardrails.pycrates/python/src/py_callable.rspython/tests/plugin/test_worker_sdk.pycrates/core/src/api/llm.rscrates/worker/src/lib.rscrates/pii-redaction/src/builtin.rspython/plugin/src/nemo_relay_plugin/_api.py
python/nemo_relay/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Python wrapper modules live under
python/nemo_relay/, and the native extension is built fromcrates/pythonwithmaturin.
Files:
python/nemo_relay/guardrails.py
**/*.py
📄 CodeRabbit inference engine (CONTRIBUTING.md)
**/*.py: When changing the Python wrapper package, tests, or docs tooling, lint with Ruff (E,F,W,I), format with Ruff formatter (120-character lines, double quotes), and passtytype checking.
Add the SPDX license header to all Python source files using the#comment form.
Files:
python/nemo_relay/guardrails.pypython/tests/plugin/test_worker_sdk.pypython/plugin/src/nemo_relay_plugin/_api.py
**/*.{rs,py,go,js,ts,c,h}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Use language-appropriate naming conventions: Rust
snake_case, C FFI exports prefixednemo_relay_, GoPascalCase, Node.jscamelCase, and Pythonsnake_case.
Files:
python/nemo_relay/guardrails.pycrates/python/src/py_callable.rspython/tests/plugin/test_worker_sdk.pycrates/core/src/api/llm.rscrates/worker/src/lib.rscrates/pii-redaction/src/builtin.rspython/plugin/src/nemo_relay_plugin/_api.py
{crates/python/src/py_api/mod.rs,python/nemo_relay/**/*.py,python/nemo_relay/**/*.pyi,go/nemo_relay/**/*.go,crates/node/src/api/**/*.rs}
📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)
Update the language-native bindings for every exposed surface in Python, Go, and Node.js.
Files:
python/nemo_relay/guardrails.py
{python/nemo_relay/**/*.py,python/nemo_relay/**/*.pyi,go/nemo_relay/**/*.go}
📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)
Update language wrapper helpers such as Python wrapper modules, Python type stubs, and Go shorthand packages when the new behavior belongs in those helper layers.
Files:
python/nemo_relay/guardrails.py
{crates/**/src/**/*.rs,python/**/*.py}
📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)
Do not add tests under
src; Rust tests belong in cratetests/trees, and Python SDK tests belong underpython/tests.
Files:
python/nemo_relay/guardrails.pycrates/python/src/py_callable.rspython/tests/plugin/test_worker_sdk.pycrates/core/src/api/llm.rscrates/worker/src/lib.rscrates/pii-redaction/src/builtin.rspython/plugin/src/nemo_relay_plugin/_api.py
**/*.{py,go,js,ts}
📄 CodeRabbit inference engine (.agents/skills/maintain-observability/SKILL.md)
Keep Python, Go, and Node.js config objects and subscriber/exporter methods aligned so all bindings expose the same logical knobs and semantics.
Files:
python/nemo_relay/guardrails.pypython/tests/plugin/test_worker_sdk.pypython/plugin/src/nemo_relay_plugin/_api.py
**/*
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
**/*: Format changed files with the language-native formatter before the final lint/test pass.
If dynamic plugin behavior changed, usemaintain-dynamic-pluginsand include the native SDK, worker protocol, Python SDK, docs, packaging, and Codecov surfaces in the validation plan.
If code changes alter APIs, bindings, commands, paths, packaging behavior, observability/adaptive semantics, or documented best practices, update any dependent maintainer or consumer skills in the same branch.
During iteration, preferuv run pre-commit run --files <changed files...>.
Before review or handoff, runuv run pre-commit run --all-files.
Files:
python/nemo_relay/guardrails.pycrates/python/src/py_callable.rspython/tests/plugin/test_worker_sdk.pycrates/core/src/api/llm.rscrates/worker/src/lib.rscrates/pii-redaction/src/builtin.rspython/plugin/src/nemo_relay_plugin/_api.py
**/*.{rs,py,go,js,ts}
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
If a language surface changed, always run that language's test target even when Rust core did not change.
Files:
python/nemo_relay/guardrails.pycrates/python/src/py_callable.rspython/tests/plugin/test_worker_sdk.pycrates/core/src/api/llm.rscrates/worker/src/lib.rscrates/pii-redaction/src/builtin.rspython/plugin/src/nemo_relay_plugin/_api.py
**/*.{rs,py,js,ts,tsx,go,java,kt,swift}
📄 CodeRabbit inference engine (.agents/skills/add-middleware/SKILL.md)
Add tests covering registration and duplicate names, deregistration and missing names, priority ordering, callback failure policy, scope-local inheritance and cleanup, event payload semantics, immutable mark and scope fields, and parity across affected bindings.
Files:
python/nemo_relay/guardrails.pycrates/python/src/py_callable.rspython/tests/plugin/test_worker_sdk.pycrates/core/src/api/llm.rscrates/worker/src/lib.rscrates/pii-redaction/src/builtin.rspython/plugin/src/nemo_relay_plugin/_api.py
python/nemo_relay/**/*
⚙️ CodeRabbit configuration file
python/nemo_relay/**/*: Review Python wrapper changes for typed API consistency, contextvars-based scope isolation, async behavior, and parity with the native extension.
Stubs and runtime implementations should stay aligned.
Files:
python/nemo_relay/guardrails.py
**/*.rs
📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)
**/*.rs: Any Rust change must runjust test-rust
Any Rust change must runcargo fmt --all
Any Rust change must runcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Runcargo fmt --allfor all FFI work since it is Rust work
Runjust test-rustto validate FFI changes
Runcargo clippy --workspace --all-targets -- -D warningsto enforce strict linting on FFI workWhen Rust files changed as part of Go work, also run
cargo fmt --all,just test-rust, andcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Runcargo fmt --allwhen Rust files are changed as part of Node work
Runcargo clippy --workspace --all-targets -- -D warningswhen Rust files are changed as part of Node work
Runjust test-rustwhen Rust files are changed as part of Node workWhen changing the core Rust runtime or Rust-facing API surface, format Rust code with
cargo fmt(rustfmt defaults), keepcargo clippy -- -D warningsclean, and satisfycargo deny checkperdeny.toml.
**/*.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.
For Rust changes headed for review, runcargo fmt --allandcargo clippy --workspace --all-targets -- -D warningseven if relying on pre-commit.
Files:
crates/python/src/py_callable.rscrates/core/src/api/llm.rscrates/worker/src/lib.rscrates/pii-redaction/src/builtin.rs
**/*.{rs,go,js,ts}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Add the SPDX license header to all Rust, Go, JavaScript, and TypeScript source files using the corresponding
//comment form.
Files:
crates/python/src/py_callable.rscrates/core/src/api/llm.rscrates/worker/src/lib.rscrates/pii-redaction/src/builtin.rs
crates/{python,ffi,node}/**/*
⚙️ CodeRabbit configuration file
crates/{python,ffi,node}/**/*: Treat binding changes as public API changes. Check for parity with the other language bindings, FFI ownership/lifetime safety,
callback error propagation, stable type conversion, and consistent async/stream semantics.
Flag changes that update one binding without corresponding tests or documentation for the same surface elsewhere.
Files:
crates/python/src/py_callable.rs
python/tests/**/*.py
📄 CodeRabbit inference engine (.agents/skills/test-python-binding/SKILL.md)
python/tests/**/*.py: Pytest is used to run tests.
Do not add@pytest.mark.asyncioto any test; async tests are automatically detected and run by the async runner.
Do not add a-> Nonereturn type annotation to test functions.
When mocking a class, do not define a new class; useunittest.mock.MagicMockorunittest.mock.AsyncMock, with thespecconstructor argument when necessary.
Name mocked classes with themockprefix, notfake.
Prefer pytest fixtures over helper methods.
Do not repeat fixtures; if a fixture is needed in multiple test files, place it in aconftest.pyfile.
When creating a fixture, use@pytest.fixture(name="<fixture_name>"[, scope="<scope>"])and define the fixture function asdef <fixture_name>_fixture() -> <return_type>:; only specifyscopewhen it is notfunction.
Preferpytest.mark.parametrizeover creating individual tests for different input types.
Files:
python/tests/plugin/test_worker_sdk.py
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}
⚙️ CodeRabbit configuration file
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}: Tests should cover the behavior promised by the changed API surface, including error paths and cross-request isolation where relevant.
Prefer assertions on lifecycle events, scope stacks, middleware ordering, and binding parity over shallow smoke tests.
Files:
python/tests/plugin/test_worker_sdk.py
{crates/core,crates/adaptive}/**/*
📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)
Changes to
crates/coreorcrates/adaptivemust run the full language matrix
Files:
crates/core/src/api/llm.rs
crates/core/**/*.rs
📄 CodeRabbit inference engine (.agents/skills/test-go-binding/SKILL.md)
If the change touched
crates/coreor shared runtime semantics, also usevalidate-changefor broader validation
Files:
crates/core/src/api/llm.rs
crates/core/src/{api/**/*.rs,api/runtime/**/*.rs,codec/**/*.rs,json.rs}
📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)
Implement the new or changed public runtime behavior first in the Rust core, especially under
crates/core/src/api/and related core modules such ascrates/core/src/api/runtime/,crates/core/src/codec/, andcrates/core/src/json.rs.
Files:
crates/core/src/api/llm.rs
crates/{core,adaptive}/**/*
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
If
crates/coreorcrates/adaptivechanged, run the full validation matrix across Rust, Python, Go, and Node.js.
Files:
crates/core/src/api/llm.rs
crates/core/src/api/{tool,llm,shared,scope}.rs
📄 CodeRabbit inference engine (.agents/skills/add-middleware/SKILL.md)
Wire the new middleware chain into the appropriate lifecycle owner and pipeline stage: tool and LLM execution paths use
tool.rsorllm.rs; shared mark and scope event sanitization usesshared.rsand is called fromscope.rs.
Files:
crates/core/src/api/llm.rs
crates/core/src/api/**/*.rs
📄 CodeRabbit inference engine (.agents/skills/add-middleware/SKILL.md)
Preserve the documented pipeline order: conditional guardrails, request intercepts, request sanitization, execution intercepts, and response sanitization for tool and LLM execution; specialized sanitization, event creation, and dispatch for mark and scope events.
Files:
crates/core/src/api/llm.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/llm.rs
{crates/core/src/plugin/dynamic/**,crates/plugin/**,crates/worker/**,crates/worker-proto/**,crates/types/**,python/plugin/**,examples/rust-native-plugin/**,examples/python-grpc-worker-plugin/**,docs/build-plugins/**}
📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)
Keep the stable boundary explicit: native plugins cross a C ABI, and worker plugins cross
grpc-v1.
Files:
crates/worker/src/lib.rspython/plugin/src/nemo_relay_plugin/_api.py
{crates/worker-proto/**/*.{rs,proto},crates/worker/**/*.rs}
📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)
Keep worker protocol DTOs in
JsonEnvelope; protobuf should own control flow, not duplicated Relay data models.
Files:
crates/worker/src/lib.rs
{crates/core/src/plugin/dynamic/**/*.rs,crates/plugin/**/*.rs,crates/worker/**/*.rs,crates/worker-proto/**/*.rs,python/plugin/**/*.py}
📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)
Manifest validation must cover kind, compatibility, load contract, integrity, capability mismatch, and disabled-plugin behavior.
Files:
crates/worker/src/lib.rspython/plugin/src/nemo_relay_plugin/_api.py
crates/worker/**/*.rs
📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)
Worker activation must cover process launch, token authentication, handshake, validation, declarative registration, proxy rollback, cancellation, and shutdown.
Files:
crates/worker/src/lib.rs
{crates/plugin/**/*.rs,python/plugin/**/*.py}
📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)
Rust and Python SDKs must expose every supported registration surface.
Files:
python/plugin/src/nemo_relay_plugin/_api.py
🔇 Additional comments (8)
crates/python/src/py_callable.rs (1)
855-863: 📐 Maintainability & Code QualityRun the required Rust validation before handoff.
Confirm this source retains its SPDX header, then run
cargo fmt --all,cargo clippy --workspace --all-targets -- -D warnings, andjust test-rust.As per coding guidelines, “Any Rust change must run
just test-rust”,cargo fmt --all, andcargo clippy --workspace --all-targets -- -D warnings; Rust source files require an SPDX header.Also applies to: 1074-1110
Source: Coding guidelines
crates/core/src/api/llm.rs (1)
22-22: LGTM!Also applies to: 733-734, 771-790
crates/worker/src/lib.rs (2)
442-480: 🗄️ Data Integrity & IntegrationVerify duplicate registration names cannot overwrite contextual callbacks.
The contextual handler maps use
insert(name.into(), ...), whilepush_contextual_registrationrecords a registration entry separately. Confirm that duplicate names are rejected before insertion; otherwise multiple priority entries can resolve to the last callback stored for that name, breaking duplicate-name and rollback semantics.
138-150: LGTM!Also applies to: 175-176, 579-585, 1504-1607, 1776-1827, 1879-1885, 1925-1926
python/nemo_relay/guardrails.py (1)
336-408: LGTM! The docstrings forregister_contextual_llm_sanitize_request/register_contextual_llm_sanitize_responsenow include Args/Returns/Notes/Example sections matching their sibling functions, addressing the earlier feedback.python/plugin/src/nemo_relay_plugin/_api.py (1)
113-121: LGTM!_llm_sanitize_contextcorrectly normalizes empty-string codec names toNone, and the contextual dispatch in_invoke_resultcleanly separates contextual vs. legacy LLM sanitizer handling, consistent with the cross-languageLlmSanitizeContextcontract.Also applies to: 1971-2002, 2084-2089
python/tests/plugin/test_worker_sdk.py (1)
724-777: LGTM! Redundantreturn Nonefrom the prior review is removed, and the added(True, "")case plus its expected entries correctly validate empty-string-to-Nonecodec-name normalization.crates/pii-redaction/src/builtin.rs (1)
393-458: LGTM! Both previously flagged issues are resolved: the duplicated omission-warning logic is now centralized inlog_llm_payload_omitted, and the needless responsepayload.clone()is gone. The contextual sanitize/omission gating correctly restricts legacy-codec fallback to the no-active-codec case, matching the PR's privacy-safe-omission objective.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@crates/pii-redaction/src/builtin.rs`:
- Around line 501-551: Update replace_sanitized_json_pointer_value so the
Json::Object branch always returns Some(()) after inserting the replacement,
rather than using Map::insert’s Option result as the success signal. Preserve
the existing array and traversal behavior.
🪄 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: 387afd46-3d88-4f00-8f6f-70ad5353e247
📒 Files selected for processing (1)
crates/pii-redaction/src/builtin.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 (9)
**/*.rs
📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)
**/*.rs: Any Rust change must runjust test-rust
Any Rust change must runcargo fmt --all
Any Rust change must runcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Runcargo fmt --allfor all FFI work since it is Rust work
Runjust test-rustto validate FFI changes
Runcargo clippy --workspace --all-targets -- -D warningsto enforce strict linting on FFI workWhen Rust files changed as part of Go work, also run
cargo fmt --all,just test-rust, andcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Runcargo fmt --allwhen Rust files are changed as part of Node work
Runcargo clippy --workspace --all-targets -- -D warningswhen Rust files are changed as part of Node work
Runjust test-rustwhen Rust files are changed as part of Node workWhen changing the core Rust runtime or Rust-facing API surface, format Rust code with
cargo fmt(rustfmt defaults), keepcargo clippy -- -D warningsclean, and satisfycargo deny checkperdeny.toml.
**/*.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.
For Rust changes headed for review, runcargo fmt --allandcargo clippy --workspace --all-targets -- -D warningseven if relying on pre-commit.
Files:
crates/pii-redaction/src/builtin.rs
**/*.{rs,py}
📄 CodeRabbit inference engine (AGENTS.md)
Follow binding naming conventions in Rust and Python: use
snake_case.
Files:
crates/pii-redaction/src/builtin.rs
**/*.{rs,py,js,mjs,cjs,ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{rs,py,js,mjs,cjs,ts,tsx}: UseJson = serde_json::Valuein Rust-facing runtime APIs where the existing code expects JSON payloads.
UseResult<T>withFlowErrorin core runtime paths, and keep errors explicit and binding-appropriate at the wrapper layer.
Keep async behavior on the existing tokio-based model; bindings should preserve callback and future lifetimes rather than blocking or hiding async work unexpectedly.
Files:
crates/pii-redaction/src/builtin.rs
**/*.{rs,py,go,js,ts,c,h}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Use language-appropriate naming conventions: Rust
snake_case, C FFI exports prefixednemo_relay_, GoPascalCase, Node.jscamelCase, and Pythonsnake_case.
Files:
crates/pii-redaction/src/builtin.rs
**/*.{rs,go,js,ts}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Add the SPDX license header to all Rust, Go, JavaScript, and TypeScript source files using the corresponding
//comment form.
Files:
crates/pii-redaction/src/builtin.rs
{crates/**/src/**/*.rs,python/**/*.py}
📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)
Do not add tests under
src; Rust tests belong in cratetests/trees, and Python SDK tests belong underpython/tests.
Files:
crates/pii-redaction/src/builtin.rs
**/*
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
**/*: Format changed files with the language-native formatter before the final lint/test pass.
If dynamic plugin behavior changed, usemaintain-dynamic-pluginsand include the native SDK, worker protocol, Python SDK, docs, packaging, and Codecov surfaces in the validation plan.
If code changes alter APIs, bindings, commands, paths, packaging behavior, observability/adaptive semantics, or documented best practices, update any dependent maintainer or consumer skills in the same branch.
During iteration, preferuv run pre-commit run --files <changed files...>.
Before review or handoff, runuv run pre-commit run --all-files.
Files:
crates/pii-redaction/src/builtin.rs
**/*.{rs,py,go,js,ts}
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
If a language surface changed, always run that language's test target even when Rust core did not change.
Files:
crates/pii-redaction/src/builtin.rs
**/*.{rs,py,js,ts,tsx,go,java,kt,swift}
📄 CodeRabbit inference engine (.agents/skills/add-middleware/SKILL.md)
Add tests covering registration and duplicate names, deregistration and missing names, priority ordering, callback failure policy, scope-local inheritance and cleanup, event payload semantics, immutable mark and scope fields, and parity across affected bindings.
Files:
crates/pii-redaction/src/builtin.rs
🔇 Additional comments (5)
crates/pii-redaction/src/builtin.rs (5)
15-23: LGTM!Also applies to: 35-35, 172-172
288-306: Codec selection correctly prioritizes per-call context over the configured fallback.
selected_surfaceuses the active codec's surface whencontext.has_active_codecis true, only falling back tolegacy_surfaceotherwise — matches the mixed-provider + compatibility-fallback requirement from the linked issue.
357-368: LGTM!Confirms the previously flagged
payload.clone()was removed —payloadis now moved directly intosanitize_response_with_codec's caller usage without an extra clone.
15-551: 📐 Maintainability & Code QualityConfirm the Rust validation pipeline was run for this change.
As per coding guidelines, any Rust change to this file must have
cargo fmt --all,cargo clippy --workspace --all-targets -- -D warnings, andjust test-rustrun against it before review/handoff.Source: Coding guidelines
307-355: 🗄️ Data Integrity & IntegrationNo issue:
target_pathsare defined against the normalized LLM payload, so resolving them fromAnnotatedLlmRequestis expected.> Likely an incorrect or invalid review comment.
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
crates/pii-redaction/src/builtin.rs (2)
318-324: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick winMake the target-path fallback all-or-nothing
sanitize_request_target_paths_incrementallyclones the original request and skips missing paths, so the encode-failure fallback can still returnSome(request.clone())or a partially sanitized request. If any configured target path can’t be replaced and re-encoded, bail out withNone.🤖 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/pii-redaction/src/builtin.rs` around lines 318 - 324, Update sanitize_request_target_paths_incrementally so it returns None whenever any configured target path is missing, cannot be replaced, or fails re-encoding; do not return the cloned original request or a partially sanitized request. Preserve the existing successful path by returning Some only after every configured target path has been replaced and the resulting request has been encoded successfully.
73-175: 📐 Maintainability & Code Quality | 🔵 TrivialRun the Rust validation suite before handoff.
cargo fmt --all,just test-rust,cargo clippy --workspace --all-targets -- -D warnings, anduv run pre-commit run --all-files.🤖 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/pii-redaction/src/builtin.rs` around lines 73 - 175, Before handoff, run the Rust validation commands cargo fmt --all, just test-rust, cargo clippy --workspace --all-targets -- -D warnings, and uv run pre-commit run --all-files, resolving any failures they report.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@crates/pii-redaction/src/builtin.rs`:
- Around line 318-324: Update sanitize_request_target_paths_incrementally so it
returns None whenever any configured target path is missing, cannot be replaced,
or fails re-encoding; do not return the cloned original request or a partially
sanitized request. Preserve the existing successful path by returning Some only
after every configured target path has been replaced and the resulting request
has been encoded successfully.
- Around line 73-175: Before handoff, run the Rust validation commands cargo fmt
--all, just test-rust, cargo clippy --workspace --all-targets -- -D warnings,
and uv run pre-commit run --all-files, resolving any failures they report.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Enterprise
Run ID: a4a0272e-3960-4254-bb3e-cb8f46365076
📒 Files selected for processing (1)
crates/pii-redaction/src/builtin.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 (9)
**/*.rs
📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)
**/*.rs: Any Rust change must runjust test-rust
Any Rust change must runcargo fmt --all
Any Rust change must runcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Runcargo fmt --allfor all FFI work since it is Rust work
Runjust test-rustto validate FFI changes
Runcargo clippy --workspace --all-targets -- -D warningsto enforce strict linting on FFI workWhen Rust files changed as part of Go work, also run
cargo fmt --all,just test-rust, andcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Runcargo fmt --allwhen Rust files are changed as part of Node work
Runcargo clippy --workspace --all-targets -- -D warningswhen Rust files are changed as part of Node work
Runjust test-rustwhen Rust files are changed as part of Node workWhen changing the core Rust runtime or Rust-facing API surface, format Rust code with
cargo fmt(rustfmt defaults), keepcargo clippy -- -D warningsclean, and satisfycargo deny checkperdeny.toml.
**/*.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.
For Rust changes headed for review, runcargo fmt --allandcargo clippy --workspace --all-targets -- -D warningseven if relying on pre-commit.
Files:
crates/pii-redaction/src/builtin.rs
**/*.{rs,py}
📄 CodeRabbit inference engine (AGENTS.md)
Follow binding naming conventions in Rust and Python: use
snake_case.
Files:
crates/pii-redaction/src/builtin.rs
**/*.{rs,py,js,mjs,cjs,ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{rs,py,js,mjs,cjs,ts,tsx}: UseJson = serde_json::Valuein Rust-facing runtime APIs where the existing code expects JSON payloads.
UseResult<T>withFlowErrorin core runtime paths, and keep errors explicit and binding-appropriate at the wrapper layer.
Keep async behavior on the existing tokio-based model; bindings should preserve callback and future lifetimes rather than blocking or hiding async work unexpectedly.
Files:
crates/pii-redaction/src/builtin.rs
**/*.{rs,py,go,js,ts,c,h}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Use language-appropriate naming conventions: Rust
snake_case, C FFI exports prefixednemo_relay_, GoPascalCase, Node.jscamelCase, and Pythonsnake_case.
Files:
crates/pii-redaction/src/builtin.rs
**/*.{rs,go,js,ts}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Add the SPDX license header to all Rust, Go, JavaScript, and TypeScript source files using the corresponding
//comment form.
Files:
crates/pii-redaction/src/builtin.rs
{crates/**/src/**/*.rs,python/**/*.py}
📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)
Do not add tests under
src; Rust tests belong in cratetests/trees, and Python SDK tests belong underpython/tests.
Files:
crates/pii-redaction/src/builtin.rs
**/*
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
**/*: Format changed files with the language-native formatter before the final lint/test pass.
If dynamic plugin behavior changed, usemaintain-dynamic-pluginsand include the native SDK, worker protocol, Python SDK, docs, packaging, and Codecov surfaces in the validation plan.
If code changes alter APIs, bindings, commands, paths, packaging behavior, observability/adaptive semantics, or documented best practices, update any dependent maintainer or consumer skills in the same branch.
During iteration, preferuv run pre-commit run --files <changed files...>.
Before review or handoff, runuv run pre-commit run --all-files.
Files:
crates/pii-redaction/src/builtin.rs
**/*.{rs,py,go,js,ts}
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
If a language surface changed, always run that language's test target even when Rust core did not change.
Files:
crates/pii-redaction/src/builtin.rs
**/*.{rs,py,js,ts,tsx,go,java,kt,swift}
📄 CodeRabbit inference engine (.agents/skills/add-middleware/SKILL.md)
Add tests covering registration and duplicate names, deregistration and missing names, priority ordering, callback failure policy, scope-local inheritance and cleanup, event payload semantics, immutable mark and scope fields, and parity across affected bindings.
Files:
crates/pii-redaction/src/builtin.rs
🔇 Additional comments (3)
crates/pii-redaction/src/builtin.rs (3)
15-23: LGTM!Also applies to: 35-35, 162-167, 172-172
541-544: LGTM!
357-367: 🔒 Security & PrivacyNo action needed: the codec-specific overlay helpers remove omitted fields from the returned JSON, and decode/sanitize failures still short-circuit to
None.> Likely an incorrect or invalid review comment.
f4b3ac7 to
83a16fa
Compare
Signed-off-by: Will Killian <wkillian@nvidia.com>
Signed-off-by: Will Killian <wkillian@nvidia.com>
Signed-off-by: Will Killian <wkillian@nvidia.com>
Signed-off-by: Will Killian <wkillian@nvidia.com>
Signed-off-by: Will Killian <wkillian@nvidia.com>
Signed-off-by: Will Killian <wkillian@nvidia.com>
Signed-off-by: Will Killian <wkillian@nvidia.com>
Signed-off-by: Will Killian <wkillian@nvidia.com>
83a16fa to
d830458
Compare
Signed-off-by: Will Killian <wkillian@nvidia.com>
Signed-off-by: Will Killian <wkillian@nvidia.com>
Signed-off-by: Will Killian <wkillian@nvidia.com>
Signed-off-by: Will Killian <wkillian@nvidia.com>
2737e6a to
28b2120
Compare
Overview
Exposes the active per-call LLM codec to observability sanitizers across in-process and plugin boundaries, then uses that resolved capability to make PII redaction provider-correct for mixed managed LLM traffic.
Warning
BREAKING CHANGE: LLM request and response sanitizers now use the required two-argument contract
(payload, directional_context) -> optional payload. No registration-time compatibility shim remains. Rust, Python, Node.js, native plugins, raw C FFI consumers, worker plugins, and downstream bindings must update their callbacks. All Rust worker sanitizer callbacks—mark, scope, tool, and LLM—are now async. Native dynamic plugins remain ABI v2 and workers remaingrpc-v1, but the v2 context/host tables and grpc-v1 invocation/service definitions change in place.Details
LlmSanitizeRequestContextandLlmSanitizeResponseContextvalues with structured codec identities: none, built-in, runtime, and opaque. Every active codec, including opaque codecs, can be resolved for the lifetime of the callback.decode(request)andencode(annotated, original); gives response sanitizersdecode(response).grpc-v1with directional contexts and authenticated, invocation-scoped codec capabilities. Host RPCs reject forged, expired, unauthorized, and wrong-direction capability IDs, and SDK authors see async codec proxies rather than raw IDs.None/nullresults omit the payload and annotation without changing the client-visible request or response.codeconly when no active codec exists, support provider-agnostic policies without a configured codec, and omit codec-dependent observability data when normalization is unavailable.Validation:
Where should the reviewer start?
Start with
crates/core/src/api/runtime/callbacks.rsandcrates/core/src/api/llm.rsfor the canonical callback contract and codec propagation. Then reviewcrates/plugin/src/lib.rs,crates/core/src/plugin/dynamic/native.rs,crates/core/src/plugin/dynamic/worker.rs, andcrates/worker-proto/proto/nemo/relay/worker/v1/plugin_worker.protofor cross-boundary capability lifetime and authorization. Finish withcrates/pii-redaction/src/builtin.rsfor per-call codec selection and fail-closed policy, then reviewdocs/reference/migration-guides.mdxfor the public upgrade contract.Related Issues: (use one of the action keywords Closes / Fixes / Resolves / Relates to)