Skip to content

fix(annotated)!: integrate lossless request codecs#509

Merged
rapids-bot[bot] merged 9 commits into
NVIDIA:release/0.6from
willkill07:wkk_fix-request-codecs
Jul 21, 2026
Merged

fix(annotated)!: integrate lossless request codecs#509
rapids-bot[bot] merged 9 commits into
NVIDIA:release/0.6from
willkill07:wkk_fix-request-codecs

Conversation

@willkill07

@willkill07 willkill07 commented Jul 20, 2026

Copy link
Copy Markdown
Member

Overview

Warning

BREAKING CHANGE: [annotated request schema and plugin compatibility] AnnotatedLlmRequest adds public fields and message, content, tool, and tool-choice variants. Rust exhaustive matches and direct struct literals must be updated. Request annotations and request-intercept outcomes now use the @2 schema tags. Rust native plugins and Rust grpc-v1 workers that consume annotations must rebuild against NeMo Relay 0.6; Python workers must update to the 0.6 worker SDK. Dynamic plugins that register LLM request intercepts must declare compat.relay = ">=0.6,<1.0"; the host rejects ranges that still admit Relay 0.5. Node.js, Go, and raw C FFI callback boundaries remain JSON-based and do not require new binding DTOs.

Fix Issue 501 by making request-codec annotations lossless across Anthropic Messages, OpenAI Responses, and OpenAI Chat Completions, and by enabling those request codecs in the nemo-relay gateway.

  • 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

  • Extend AnnotatedLlmRequest with shared provider instructions, a tagged mutable api_specific surface, portable message/content/tool unions, component extras, and explicit provider-native fallbacks.
  • Complete request modeling against the pinned Anthropic and OpenAI SDK schemas, including provider-only input items, built-in tools, tool choices, legacy Chat fields, and provider-specific top-level controls.
  • Guarantee JSON-value identity for no-op encode(decode(original), original) calls by comparing edits with a decoded baseline and patching only changed fields. Unknown fields, nulls, alternate representations, item order, and untouched native values remain unchanged.
  • Patch edited nested messages, content blocks, tools, and tool choices against their original provider values so sibling unknown fields and explicit nulls survive portable edits.
  • Reject malformed recognized structures, provider-mismatched native edits, unencodable normalized edits, and raw-body mutation before the provider callback. Remove the Responses private sentinel and Chat's implicit stream_options.include_usage injection.
  • Enable request codecs for buffered and streaming /v1/messages, /v1/chat/completions, and /v1/responses gateway calls. Count-token, model, probe, and non-LLM passthrough routes remain unannotated.
  • Add Python constructor properties and serialization coverage. Version request annotations and request-intercept outcomes as @2, require the 0.6 SDK for Python workers, and enforce a Relay 0.6 compatibility floor for dynamic plugins that register request intercepts. Node, FFI, and Go callback boundaries continue carrying annotations as JSON.
  • Add provider schema fixtures, exact round-trip and surgical-edit tests, an Issue 501 managed-runtime reproduction, a six-way gateway route/streaming matrix, migration documentation, and updated typed-wrapper guidance.
  • Migration note: gateway interceptors for the three generation routes must mutate annotated_request; changing raw request.content while a request codec is active remains an explicit runtime error.

Validation:

  • just test-rust
  • just test-python (536 passed)
  • just test-node (277 passed)
  • just test-go
  • just test-python-plugin
  • just test-claude-plugin-e2e
  • just test-codex-plugin-e2e
  • just docs
  • uv run pre-commit run --all-files

Where should the reviewer start?

Start with crates/types/src/codec/request.rs for the public annotation contract, then review the baseline-diff helper and provider codecs under crates/core/src/codec/. The gateway wiring and buffered/streaming matrix are in crates/cli/src/gateway/mod.rs and crates/cli/tests/coverage/shared/server_tests.rs.

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

Summary by CodeRabbit

  • New Features
    • Added lossless request annotations for Anthropic Messages, OpenAI Chat Completions, and OpenAI Responses routes, including streaming.
    • Added support for shared instructions, developer messages, tool calls/results, multimodal content, and provider-native fields.
    • Exposed instructions and api_specific through Python request objects.
  • Bug Fixes
    • Preserves unchanged fields, ordering, explicit nulls, metadata, and unknown provider data during edits.
    • Rejects unsupported raw-body mutations when request codecs are active.
  • Documentation
    • Expanded codec behavior, routing, migration, and interception guidance.

Summary by CodeRabbit

  • New Features

    • Added lossless, baseline-aware request codecs for Anthropic Messages, OpenAI Chat Completions, and OpenAI Responses to enable safe annotation edits while preserving unchanged JSON.
    • Expanded annotated requests to support instructions, api_specific, developer/function/tool/provider-native variants, and richer tool schemas.
    • Added Python accessors for instructions and api_specific; enhanced OpenInference message-role projection.
  • Bug Fixes

    • Stricter validation/encoding behavior, improved refusal/text extraction, and enforced rejection of unsupported raw-body and stream-mode edits when codecs are active.
    • Enforced annotated-request consumer compatibility.
  • Documentation

    • Updated codec and migration guidance for the new annotation surfaces.
  • Tests

    • Updated and expanded codec, gateway, plugin, and observability test coverage.

Signed-off-by: Will Killian <wkillian@nvidia.com>
@coderabbitai

coderabbitai Bot commented Jul 20, 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

The request annotation model now supports instructions, provider-specific fields, extended message/content variants, and provider-native tools. Provider codecs decode structured requests and apply baseline-aware patches, while gateway routing, compatibility validation, bindings, adaptive processing, tests, and documentation are updated.

Changes

Provider-aware request annotation flow

Layer / File(s) Summary
Request model and provider codecs
crates/types/..., crates/core/src/codec/...
Request annotations gain instructions, API-specific fields, provider-native variants, and richer tools/content. Anthropic, OpenAI Chat, and OpenAI Responses codecs strictly decode and patch only changed portions of the original JSON.
Gateway and protocol compatibility
crates/cli/src/gateway/mod.rs, crates/core/src/plugin/..., crates/worker/src/lib.rs
Generation routes receive request codecs, stream-mode changes are rejected, interceptor envelopes use schema version 2, and incompatible dynamic consumers are rejected.
Adaptive processing, bindings, and observability
crates/adaptive/src/..., crates/python/src/..., crates/core/src/observability/..., crates/pii-redaction/...
Fingerprinting, IR construction, Python accessors, OpenInference roles, response extraction, and redacted text extraction cover expanded request variants.
Validation and regression coverage
crates/*/tests/..., python/tests/...
Codec branch matrices, baseline patching, gateway interception, schema validation, plugin compatibility, binding accessors, and Anthropic round-trip behavior are tested.
Documentation and migration guidance
docs/..., skills/..., examples/...
Lossless codec behavior, annotation authority, provider-native constraints, schema versions, and Relay compatibility requirements are documented.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant Gateway
  participant RequestCodec
  participant Interceptor
  participant Provider
  Client->>Gateway: generation request
  Gateway->>RequestCodec: decode provider JSON
  RequestCodec->>Interceptor: normalized AnnotatedLlmRequest
  Interceptor->>RequestCodec: edited instructions/messages/tools
  RequestCodec->>Provider: baseline-patched provider JSON
  Provider-->>Gateway: response
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 74.39% 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 lossless request codec work.
Description check ✅ Passed The description matches the repository template and includes overview, details, reviewer start point, issue link, and checkboxes.
Linked Issues check ✅ Passed The PR implements the Anthropic no-op round-trip preservation and explicit-error goals from issue #501.
Out of Scope Changes check ✅ Passed The changes stay within the stated codec, gateway, compatibility, docs, and test migration scope.
✨ 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 size:XXL PR is very large Bug issue describes bug; PR fixes bug lang:js PR changes/introduces Javascript/Typescript code lang:python PR changes/introduces Python code lang:rust PR changes/introduces Rust code labels Jul 21, 2026
@github-actions

Copy link
Copy Markdown

@willkill07

Copy link
Copy Markdown
Member Author

Verified end-to-end successfully.

Client Version Route Result
Claude Code 2.1.160 /v1/messages 10 cold + 2 concurrent runs passed
Codex 0.144.4 /v1/responses 10 cold + 2 concurrent runs passed

Commands:

  • just test-claude-plugin-e2e
  • just test-codex-plugin-e2e

Both used the real installed clients, temporary Relay plugin installations, codec-enabled gateways, and an isolated deterministic provider. Requests returned pong, lifecycle/LLM scopes paired correctly, provider responses were preserved in ATOF, and cleanup succeeded.

This verifies client/gateway/codec compatibility, not live Anthropic/OpenAI service availability. The PR branch remains clean and unchanged.

Comment thread crates/core/src/codec/anthropic.rs
@afourniernv

Copy link
Copy Markdown
Contributor

One compatibility question before this lands: the PR adds new Message/ContentPart/ToolDefinition variants and AnnotatedLlmRequest fields, but worker invocations still label the payload nemo.relay.AnnotatedLlmRequest@1. Since plugin guidance recommends compat.relay = ">=0.5,<1.0", a Rust worker built against 0.5 can be admitted by a 0.6 host and then fail to deserialize a new variant. Is @1 intended to remain backward-readable here? If so, we need a catch-all/compatible representation; otherwise I think this needs a schema-version/compatibility change and an explicit 0.6 migration note for the Rust source breaks.

@willkill07 willkill07 added this to the 0.6 milestone Jul 21, 2026
@willkill07 willkill07 self-assigned this Jul 21, 2026
Signed-off-by: Will Killian <wkillian@nvidia.com>
@willkill07 willkill07 changed the title fix: integrate lossless request codecs fix!(annotated): integrate lossless request codecs Jul 21, 2026
@github-actions github-actions Bot removed the Bug issue describes bug; PR fixes bug label Jul 21, 2026
Signed-off-by: Will Killian <wkillian@nvidia.com>
@willkill07 willkill07 changed the title fix!(annotated): integrate lossless request codecs fix(annotated)!: integrate lossless request codecs Jul 21, 2026
@willkill07 willkill07 changed the title fix(annotated)!: integrate lossless request codecs fix!(annotated): integrate lossless request codecs Jul 21, 2026
@github-actions github-actions Bot added Bug issue describes bug; PR fixes bug breaking PR introduces a breaking change labels Jul 21, 2026
@github-actions github-actions Bot removed the Bug issue describes bug; PR fixes bug label Jul 21, 2026
@willkill07
willkill07 marked this pull request as ready for review July 21, 2026 02:03
@willkill07
willkill07 requested review from a team and lvojtku as code owners July 21, 2026 02:03
Comment thread crates/core/src/codec/openai_chat.rs Outdated

Copy link
Copy Markdown
Contributor

P2 verification: malformed modeled scalars are silently accepted

I reproduced this issue against the current PR head, commit 61cd11ceaf94a04781a0d23e7bb84c8208840f94.

Cases tested

Codec Recognized modeled field Malformed value
OpenAI Chat Completions frequency_penalty "high" instead of a number
Anthropic Messages top_k "many" instead of an integer
OpenAI Responses background "yes" instead of a boolean

For each case, the focused diagnostic test performed the same checks:

  1. Constructed an otherwise-valid provider request containing the malformed modeled scalar.
  2. Called the codec's decode method and confirmed that it returned Ok rather than FlowError::InvalidArgument.
  3. Confirmed that the recognized field was absent from annotated.extra, so middleware cannot inspect or correct it as an unmodeled provider value.
  4. Called encode(&annotated, &original) and confirmed that the result exactly equaled the original request, including the malformed scalar value.

The focused command was:

env CARGO_TARGET_DIR=/Users/bbednarski/Projects/code-review/NeMo-Relay/target cargo test -p nemo-relay review_probe_malformed_modeled -- --nocapture

Result:

running 3 tests
test codec::anthropic::tests::review_probe_malformed_modeled_anthropic_scalar_is_forwarded ... ok
test codec::openai_responses::tests::review_probe_malformed_modeled_responses_scalar_is_forwarded ... ok
test codec::openai_chat::tests::review_probe_malformed_modeled_chat_scalar_is_forwarded ... ok

test result: ok. 3 passed; 0 failed

These were diagnostic assertions of the current behavior, so the passing result confirms the bug rather than the desired contract.

Impact

A present value of the wrong JSON type is treated the same as an absent value by the typed annotation. Because the baseline-aware encoder preserves untouched raw fields, the malformed value is still forwarded to the provider. Middleware therefore sees the control as absent while the provider receives invalid JSON. This conflicts with the PR's stated behavior of rejecting malformed recognized structures before invoking the provider callback and may defer errors to provider-specific validation.

Expected behavior

For recognized modeled fields, decoding should distinguish:

  • missing or accepted null, where appropriate; from
  • a present value with the wrong JSON type.

The latter should return FlowError::InvalidArgument. Regression coverage should include modeled scalar controls across all three codec paths, not only malformed nested components.

Inline discussion: #509 (comment)

Comment thread crates/cli/src/gateway/mod.rs
Comment thread crates/core/src/codec/anthropic.rs Outdated
Signed-off-by: Will Killian <wkillian@nvidia.com>
@coderabbitai coderabbitai Bot added the DO NOT MERGE PR should not be merged; see PR for details label Jul 21, 2026
@willkill07 willkill07 removed the DO NOT MERGE PR should not be merged; see PR for details label Jul 21, 2026

@bbednarski9 bbednarski9 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Follow-up testing found one residual P2 in the new array-alignment fix.

Comment thread crates/core/src/codec/mod.rs
Signed-off-by: Will Killian <wkillian@nvidia.com>

@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/core/src/codec/mod.rs`:
- Around line 162-211: Remove the unconditional single-pair fallback in
align_changed_items that pairs one unmatched edited item with one unmatched
baseline item, since it can transfer provider fields between unrelated items.
Let ambiguous unmatched items remain unaligned so
patch_changed_json/patch_changed_array use their normal encode or edited-value
behavior; add a regression test in parity_tests.rs covering the reordered
deletion plus unrelated insertion case.

In `@crates/core/src/plugin/dynamic.rs`:
- Around line 96-109: Update validate_annotated_request_consumer_compatibility
to reject any VersionReq that admits a Relay 0.5.x version, including narrow
bounds and exact pins such as =0.5.3; do not rely on a single max-patch probe.
Inspect the parsed requirement’s comparators or otherwise perform comprehensive
0.5.x matching, while preserving the existing InvalidConfig error and allowing
ranges that exclude the entire 0.5 series.
🪄 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: bc8d8ce7-ff3c-48e0-ad02-3303a0afeff3

📥 Commits

Reviewing files that changed from the base of the PR and between 61cd11c and e17c140.

📒 Files selected for processing (46)
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/cli/src/gateway/mod.rs
  • crates/cli/tests/coverage/shared/gateway_tests.rs
  • crates/cli/tests/coverage/shared/server_tests.rs
  • crates/core/src/api/llm.rs
  • crates/core/src/codec/anthropic.rs
  • crates/core/src/codec/mod.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/core/src/observability/openinference.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/tests/integration/worker_plugin_tests.rs
  • crates/core/tests/unit/codec/anthropic_tests.rs
  • crates/core/tests/unit/codec/openai_chat_tests.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/tests/unit/codec/parity_tests.rs
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/tests/unit/observability/openinference_tests.rs
  • crates/core/tests/unit/plugin_dynamic_tests.rs
  • crates/pii-redaction/src/overlay.rs
  • crates/pii-redaction/tests/coverage/overlay_tests.rs
  • crates/python/tests/coverage/py_types_coverage_tests.rs
  • crates/types/src/api/llm.rs
  • crates/types/src/codec/request.rs
  • crates/worker/src/lib.rs
  • crates/worker/tests/worker_sdk_tests.rs
  • docs/about-nemo-relay/release-notes/known-issues.mdx
  • docs/build-plugins/dynamic-plugins/about.mdx
  • docs/build-plugins/dynamic-plugins/grpc-worker/about.mdx
  • docs/build-plugins/dynamic-plugins/native-dynamic/about.mdx
  • docs/build-plugins/dynamic-plugins/native-dynamic/rust-native-plugin-example.mdx
  • docs/integrate-into-frameworks/provider-codecs.mdx
  • docs/reference/llm-request-intercept-outcomes.mdx
  • examples/rust-native-plugin/relay-plugin.toml
  • python/nemo_relay/_native.pyi
  • python/plugin/src/nemo_relay_plugin/_api.py
  • python/tests/plugin/test_worker_sdk.py
  • python/tests/test_codecs.py
📜 Review details
⏰ Context from checks skipped due to timeout. (2)
  • GitHub Check: Check / Run
  • GitHub Check: Preview docs
🧰 Additional context used
📓 Path-based instructions (47)
**/*.toml

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Add the SPDX license header to all TOML files using the # comment form.

Files:

  • examples/rust-native-plugin/relay-plugin.toml
{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:

  • examples/rust-native-plugin/relay-plugin.toml
  • docs/build-plugins/dynamic-plugins/native-dynamic/about.mdx
  • docs/build-plugins/dynamic-plugins/about.mdx
  • crates/types/src/api/llm.rs
  • docs/build-plugins/dynamic-plugins/grpc-worker/about.mdx
  • python/plugin/src/nemo_relay_plugin/_api.py
  • docs/build-plugins/dynamic-plugins/native-dynamic/rust-native-plugin-example.mdx
  • crates/core/src/plugin/dynamic/native.rs
  • crates/worker/src/lib.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/worker/tests/worker_sdk_tests.rs
  • crates/types/src/codec/request.rs
**/relay-plugin.toml

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

**/relay-plugin.toml: Keep relay-plugin.toml dynamic records separate from generic runtime components; enabled dynamic records may synthesize internal component specs, and disabled records should remain inspectable but unloaded.
Treat plugin Relay compatibility as normal SemVer; use >=0.5,<1.0 in examples unless a plugin intentionally declares a narrower range.

Files:

  • examples/rust-native-plugin/relay-plugin.toml
{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:

  • examples/rust-native-plugin/relay-plugin.toml
  • docs/build-plugins/dynamic-plugins/native-dynamic/about.mdx
  • docs/build-plugins/dynamic-plugins/about.mdx
  • docs/build-plugins/dynamic-plugins/grpc-worker/about.mdx
  • docs/build-plugins/dynamic-plugins/native-dynamic/rust-native-plugin-example.mdx
  • crates/core/src/plugin/dynamic/native.rs
  • crates/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-v1 protocol details on separate pages.

Files:

  • examples/rust-native-plugin/relay-plugin.toml
  • docs/build-plugins/dynamic-plugins/native-dynamic/about.mdx
  • docs/build-plugins/dynamic-plugins/about.mdx
  • docs/build-plugins/dynamic-plugins/grpc-worker/about.mdx
  • docs/build-plugins/dynamic-plugins/native-dynamic/rust-native-plugin-example.mdx
{docs,examples}/**/*

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

Update docs and examples.

Files:

  • examples/rust-native-plugin/relay-plugin.toml
  • docs/build-plugins/dynamic-plugins/native-dynamic/about.mdx
  • docs/build-plugins/dynamic-plugins/about.mdx
  • docs/build-plugins/dynamic-plugins/grpc-worker/about.mdx
  • docs/build-plugins/dynamic-plugins/native-dynamic/rust-native-plugin-example.mdx
  • docs/reference/llm-request-intercept-outcomes.mdx
  • docs/about-nemo-relay/release-notes/known-issues.mdx
  • docs/integrate-into-frameworks/provider-codecs.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, use maintain-dynamic-plugins and 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, prefer uv run pre-commit run --files <changed files...>.
Before review or handoff, run uv run pre-commit run --all-files.

Files:

  • examples/rust-native-plugin/relay-plugin.toml
  • docs/build-plugins/dynamic-plugins/native-dynamic/about.mdx
  • docs/build-plugins/dynamic-plugins/about.mdx
  • crates/types/src/api/llm.rs
  • crates/pii-redaction/tests/coverage/overlay_tests.rs
  • docs/build-plugins/dynamic-plugins/grpc-worker/about.mdx
  • crates/core/src/api/llm.rs
  • python/plugin/src/nemo_relay_plugin/_api.py
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/core/tests/unit/plugin_dynamic_tests.rs
  • crates/pii-redaction/src/overlay.rs
  • crates/core/tests/unit/codec/parity_tests.rs
  • crates/core/tests/integration/worker_plugin_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • docs/build-plugins/dynamic-plugins/native-dynamic/rust-native-plugin-example.mdx
  • python/tests/test_codecs.py
  • python/tests/plugin/test_worker_sdk.py
  • crates/core/src/codec/mod.rs
  • docs/reference/llm-request-intercept-outcomes.mdx
  • crates/core/src/plugin/dynamic/native.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/cli/tests/coverage/shared/gateway_tests.rs
  • python/nemo_relay/_native.pyi
  • docs/about-nemo-relay/release-notes/known-issues.mdx
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/worker/src/lib.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
  • crates/cli/src/gateway/mod.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/src/observability/openinference.rs
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/python/tests/coverage/py_types_coverage_tests.rs
  • crates/core/tests/unit/observability/openinference_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/worker/tests/worker_sdk_tests.rs
  • crates/core/src/codec/anthropic.rs
  • crates/cli/tests/coverage/shared/server_tests.rs
  • crates/core/src/codec/openai_chat.rs
  • docs/integrate-into-frameworks/provider-codecs.mdx
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/tests/unit/codec/openai_chat_tests.rs
  • crates/types/src/codec/request.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/core/tests/unit/codec/anthropic_tests.rs
**/*.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/build-plugins/dynamic-plugins/native-dynamic/about.mdx
  • docs/build-plugins/dynamic-plugins/about.mdx
  • docs/build-plugins/dynamic-plugins/grpc-worker/about.mdx
  • docs/build-plugins/dynamic-plugins/native-dynamic/rust-native-plugin-example.mdx
  • docs/reference/llm-request-intercept-outcomes.mdx
  • docs/about-nemo-relay/release-notes/known-issues.mdx
  • docs/integrate-into-frameworks/provider-codecs.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 as RELEASING.md, not as user-facing docs pages or CHANGELOG.md
Keep stable user-facing wrappers at scripts/ 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, and grpc-v1 protocol details on separate pages

If links in documentation change, run just docs-linkcheck.

Files:

  • docs/build-plugins/dynamic-plugins/native-dynamic/about.mdx
  • docs/build-plugins/dynamic-plugins/about.mdx
  • docs/build-plugins/dynamic-plugins/grpc-worker/about.mdx
  • docs/build-plugins/dynamic-plugins/native-dynamic/rust-native-plugin-example.mdx
  • docs/reference/llm-request-intercept-outcomes.mdx
  • docs/about-nemo-relay/release-notes/known-issues.mdx
  • docs/integrate-into-frameworks/provider-codecs.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/build-plugins/dynamic-plugins/native-dynamic/about.mdx
  • docs/build-plugins/dynamic-plugins/about.mdx
  • docs/build-plugins/dynamic-plugins/grpc-worker/about.mdx
  • docs/build-plugins/dynamic-plugins/native-dynamic/rust-native-plugin-example.mdx
  • docs/reference/llm-request-intercept-outcomes.mdx
  • docs/about-nemo-relay/release-notes/known-issues.mdx
  • docs/integrate-into-frameworks/provider-codecs.mdx
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/build-plugins/dynamic-plugins/native-dynamic/about.mdx
  • docs/build-plugins/dynamic-plugins/about.mdx
  • docs/build-plugins/dynamic-plugins/grpc-worker/about.mdx
  • docs/build-plugins/dynamic-plugins/native-dynamic/rust-native-plugin-example.mdx
  • docs/reference/llm-request-intercept-outcomes.mdx
  • docs/about-nemo-relay/release-notes/known-issues.mdx
  • docs/integrate-into-frameworks/provider-codecs.mdx
{docs/**,README.md,CONTRIBUTING.md,RELEASING.md,SECURITY.md}

⚙️ CodeRabbit configuration file

{docs/**,README.md,CONTRIBUTING.md,RELEASING.md,SECURITY.md}: Review documentation for technical accuracy against the current API, command correctness, and consistency across language bindings.
Flag stale examples, missing SPDX headers where required, and instructions that no longer match CI or pre-commit behavior.

Files:

  • docs/build-plugins/dynamic-plugins/native-dynamic/about.mdx
  • docs/build-plugins/dynamic-plugins/about.mdx
  • docs/build-plugins/dynamic-plugins/grpc-worker/about.mdx
  • docs/build-plugins/dynamic-plugins/native-dynamic/rust-native-plugin-example.mdx
  • docs/reference/llm-request-intercept-outcomes.mdx
  • docs/about-nemo-relay/release-notes/known-issues.mdx
  • docs/integrate-into-frameworks/provider-codecs.mdx
**/*.rs

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

**/*.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

When changing the core Rust runtime or Rust-facing API surface, format Rust code with cargo fmt (rustfmt defaults), keep cargo clippy -- -D warnings clean, and satisfy cargo deny check per deny.toml.

**/*.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.
For Rust changes headed for review, run cargo fmt --all and cargo clippy --workspace --all-targets -- -D warnings even if relying on pre-commit.

Files:

  • crates/types/src/api/llm.rs
  • crates/pii-redaction/tests/coverage/overlay_tests.rs
  • crates/core/src/api/llm.rs
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/core/tests/unit/plugin_dynamic_tests.rs
  • crates/pii-redaction/src/overlay.rs
  • crates/core/tests/unit/codec/parity_tests.rs
  • crates/core/tests/integration/worker_plugin_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/codec/mod.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/cli/tests/coverage/shared/gateway_tests.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/worker/src/lib.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
  • crates/cli/src/gateway/mod.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/src/observability/openinference.rs
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/python/tests/coverage/py_types_coverage_tests.rs
  • crates/core/tests/unit/observability/openinference_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/worker/tests/worker_sdk_tests.rs
  • crates/core/src/codec/anthropic.rs
  • crates/cli/tests/coverage/shared/server_tests.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/tests/unit/codec/openai_chat_tests.rs
  • crates/types/src/codec/request.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/core/tests/unit/codec/anthropic_tests.rs
**/*.{rs,py}

📄 CodeRabbit inference engine (AGENTS.md)

Follow binding naming conventions in Rust and Python: use snake_case.

Files:

  • crates/types/src/api/llm.rs
  • crates/pii-redaction/tests/coverage/overlay_tests.rs
  • crates/core/src/api/llm.rs
  • python/plugin/src/nemo_relay_plugin/_api.py
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/core/tests/unit/plugin_dynamic_tests.rs
  • crates/pii-redaction/src/overlay.rs
  • crates/core/tests/unit/codec/parity_tests.rs
  • crates/core/tests/integration/worker_plugin_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • python/tests/test_codecs.py
  • python/tests/plugin/test_worker_sdk.py
  • crates/core/src/codec/mod.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/cli/tests/coverage/shared/gateway_tests.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/worker/src/lib.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
  • crates/cli/src/gateway/mod.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/src/observability/openinference.rs
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/python/tests/coverage/py_types_coverage_tests.rs
  • crates/core/tests/unit/observability/openinference_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/worker/tests/worker_sdk_tests.rs
  • crates/core/src/codec/anthropic.rs
  • crates/cli/tests/coverage/shared/server_tests.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/tests/unit/codec/openai_chat_tests.rs
  • crates/types/src/codec/request.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/core/tests/unit/codec/anthropic_tests.rs
**/*.{rs,py,js,mjs,cjs,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{rs,py,js,mjs,cjs,ts,tsx}: 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, 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/types/src/api/llm.rs
  • crates/pii-redaction/tests/coverage/overlay_tests.rs
  • crates/core/src/api/llm.rs
  • python/plugin/src/nemo_relay_plugin/_api.py
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/core/tests/unit/plugin_dynamic_tests.rs
  • crates/pii-redaction/src/overlay.rs
  • crates/core/tests/unit/codec/parity_tests.rs
  • crates/core/tests/integration/worker_plugin_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • python/tests/test_codecs.py
  • python/tests/plugin/test_worker_sdk.py
  • crates/core/src/codec/mod.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/cli/tests/coverage/shared/gateway_tests.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/worker/src/lib.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
  • crates/cli/src/gateway/mod.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/src/observability/openinference.rs
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/python/tests/coverage/py_types_coverage_tests.rs
  • crates/core/tests/unit/observability/openinference_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/worker/tests/worker_sdk_tests.rs
  • crates/core/src/codec/anthropic.rs
  • crates/cli/tests/coverage/shared/server_tests.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/tests/unit/codec/openai_chat_tests.rs
  • crates/types/src/codec/request.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/core/tests/unit/codec/anthropic_tests.rs
**/*.{rs,py,go,js,ts,c,h}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Use language-appropriate naming conventions: Rust snake_case, C FFI exports prefixed nemo_relay_, Go PascalCase, Node.js camelCase, and Python snake_case.

Files:

  • crates/types/src/api/llm.rs
  • crates/pii-redaction/tests/coverage/overlay_tests.rs
  • crates/core/src/api/llm.rs
  • python/plugin/src/nemo_relay_plugin/_api.py
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/core/tests/unit/plugin_dynamic_tests.rs
  • crates/pii-redaction/src/overlay.rs
  • crates/core/tests/unit/codec/parity_tests.rs
  • crates/core/tests/integration/worker_plugin_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • python/tests/test_codecs.py
  • python/tests/plugin/test_worker_sdk.py
  • crates/core/src/codec/mod.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/cli/tests/coverage/shared/gateway_tests.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/worker/src/lib.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
  • crates/cli/src/gateway/mod.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/src/observability/openinference.rs
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/python/tests/coverage/py_types_coverage_tests.rs
  • crates/core/tests/unit/observability/openinference_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/worker/tests/worker_sdk_tests.rs
  • crates/core/src/codec/anthropic.rs
  • crates/cli/tests/coverage/shared/server_tests.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/tests/unit/codec/openai_chat_tests.rs
  • crates/types/src/codec/request.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/core/tests/unit/codec/anthropic_tests.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/types/src/api/llm.rs
  • crates/pii-redaction/tests/coverage/overlay_tests.rs
  • crates/core/src/api/llm.rs
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/core/tests/unit/plugin_dynamic_tests.rs
  • crates/pii-redaction/src/overlay.rs
  • crates/core/tests/unit/codec/parity_tests.rs
  • crates/core/tests/integration/worker_plugin_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/codec/mod.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/cli/tests/coverage/shared/gateway_tests.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/worker/src/lib.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
  • crates/cli/src/gateway/mod.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/src/observability/openinference.rs
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/python/tests/coverage/py_types_coverage_tests.rs
  • crates/core/tests/unit/observability/openinference_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/worker/tests/worker_sdk_tests.rs
  • crates/core/src/codec/anthropic.rs
  • crates/cli/tests/coverage/shared/server_tests.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/tests/unit/codec/openai_chat_tests.rs
  • crates/types/src/codec/request.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/core/tests/unit/codec/anthropic_tests.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 crate tests/ trees, and Python SDK tests belong under python/tests.

Files:

  • crates/types/src/api/llm.rs
  • crates/core/src/api/llm.rs
  • python/plugin/src/nemo_relay_plugin/_api.py
  • crates/core/src/plugin/dynamic.rs
  • crates/pii-redaction/src/overlay.rs
  • python/tests/test_codecs.py
  • python/tests/plugin/test_worker_sdk.py
  • crates/core/src/codec/mod.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/worker/src/lib.rs
  • crates/cli/src/gateway/mod.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/src/observability/openinference.rs
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/core/src/codec/anthropic.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/types/src/codec/request.rs
  • crates/core/src/codec/openai_responses.rs
crates/types/**/*.rs

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

Runtime helpers must cover marks, scopes, continuations, and isolated scope stacks.

Files:

  • crates/types/src/api/llm.rs
  • crates/types/src/codec/request.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/types/src/api/llm.rs
  • crates/pii-redaction/tests/coverage/overlay_tests.rs
  • crates/core/src/api/llm.rs
  • python/plugin/src/nemo_relay_plugin/_api.py
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/core/tests/unit/plugin_dynamic_tests.rs
  • crates/pii-redaction/src/overlay.rs
  • crates/core/tests/unit/codec/parity_tests.rs
  • crates/core/tests/integration/worker_plugin_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • python/tests/test_codecs.py
  • python/tests/plugin/test_worker_sdk.py
  • crates/core/src/codec/mod.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/cli/tests/coverage/shared/gateway_tests.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/worker/src/lib.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
  • crates/cli/src/gateway/mod.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/src/observability/openinference.rs
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/python/tests/coverage/py_types_coverage_tests.rs
  • crates/core/tests/unit/observability/openinference_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/worker/tests/worker_sdk_tests.rs
  • crates/core/src/codec/anthropic.rs
  • crates/cli/tests/coverage/shared/server_tests.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/tests/unit/codec/openai_chat_tests.rs
  • crates/types/src/codec/request.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/core/tests/unit/codec/anthropic_tests.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/types/src/api/llm.rs
  • crates/pii-redaction/tests/coverage/overlay_tests.rs
  • crates/core/src/api/llm.rs
  • python/plugin/src/nemo_relay_plugin/_api.py
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/core/tests/unit/plugin_dynamic_tests.rs
  • crates/pii-redaction/src/overlay.rs
  • crates/core/tests/unit/codec/parity_tests.rs
  • crates/core/tests/integration/worker_plugin_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • python/tests/test_codecs.py
  • python/tests/plugin/test_worker_sdk.py
  • crates/core/src/codec/mod.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/cli/tests/coverage/shared/gateway_tests.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/worker/src/lib.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
  • crates/cli/src/gateway/mod.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/src/observability/openinference.rs
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/python/tests/coverage/py_types_coverage_tests.rs
  • crates/core/tests/unit/observability/openinference_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/worker/tests/worker_sdk_tests.rs
  • crates/core/src/codec/anthropic.rs
  • crates/cli/tests/coverage/shared/server_tests.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/tests/unit/codec/openai_chat_tests.rs
  • crates/types/src/codec/request.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/core/tests/unit/codec/anthropic_tests.rs
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}

⚙️ CodeRabbit configuration file

{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}: Tests should cover the behavior promised by the changed API surface, including error paths and cross-request isolation where relevant.
Prefer assertions on lifecycle events, scope stacks, middleware ordering, and binding parity over shallow smoke tests.

Files:

  • crates/pii-redaction/tests/coverage/overlay_tests.rs
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/tests/unit/plugin_dynamic_tests.rs
  • crates/core/tests/unit/codec/parity_tests.rs
  • crates/core/tests/integration/worker_plugin_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • python/tests/test_codecs.py
  • python/tests/plugin/test_worker_sdk.py
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/cli/tests/coverage/shared/gateway_tests.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
  • crates/python/tests/coverage/py_types_coverage_tests.rs
  • crates/core/tests/unit/observability/openinference_tests.rs
  • crates/worker/tests/worker_sdk_tests.rs
  • crates/cli/tests/coverage/shared/server_tests.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/tests/unit/codec/openai_chat_tests.rs
  • crates/core/tests/unit/codec/anthropic_tests.rs
{crates/core,crates/adaptive}/**/*

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

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

Files:

  • crates/core/src/api/llm.rs
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/core/tests/unit/plugin_dynamic_tests.rs
  • crates/core/tests/unit/codec/parity_tests.rs
  • crates/core/tests/integration/worker_plugin_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/codec/mod.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/src/observability/openinference.rs
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/core/tests/unit/observability/openinference_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/core/src/codec/anthropic.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/tests/unit/codec/openai_chat_tests.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/core/tests/unit/codec/anthropic_tests.rs
crates/core/**/*.rs

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

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

Files:

  • crates/core/src/api/llm.rs
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/core/tests/unit/plugin_dynamic_tests.rs
  • crates/core/tests/unit/codec/parity_tests.rs
  • crates/core/tests/integration/worker_plugin_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/codec/mod.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/src/observability/openinference.rs
  • crates/core/tests/unit/observability/openinference_tests.rs
  • crates/core/src/codec/anthropic.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/tests/unit/codec/openai_chat_tests.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/core/tests/unit/codec/anthropic_tests.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 as crates/core/src/api/runtime/, crates/core/src/codec/, and crates/core/src/json.rs.

Files:

  • crates/core/src/api/llm.rs
  • crates/core/src/codec/mod.rs
  • crates/core/src/codec/anthropic.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/src/codec/openai_responses.rs
crates/{core,adaptive}/**/*

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

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

Files:

  • crates/core/src/api/llm.rs
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/core/tests/unit/plugin_dynamic_tests.rs
  • crates/core/tests/unit/codec/parity_tests.rs
  • crates/core/tests/integration/worker_plugin_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/codec/mod.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/src/observability/openinference.rs
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/core/tests/unit/observability/openinference_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/core/src/codec/anthropic.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/tests/unit/codec/openai_chat_tests.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/core/tests/unit/codec/anthropic_tests.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.rs or llm.rs; shared mark and scope event sanitization uses shared.rs and is called from scope.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/tests/unit/dynamic_worker_tests.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/core/tests/unit/plugin_dynamic_tests.rs
  • crates/core/tests/unit/codec/parity_tests.rs
  • crates/core/tests/integration/worker_plugin_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/codec/mod.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/src/observability/openinference.rs
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/core/tests/unit/observability/openinference_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/core/src/codec/anthropic.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/tests/unit/codec/openai_chat_tests.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/core/tests/unit/codec/anthropic_tests.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 pass ty type checking.
Add the SPDX license header to all Python source files using the # comment form.

Files:

  • python/plugin/src/nemo_relay_plugin/_api.py
  • python/tests/test_codecs.py
  • python/tests/plugin/test_worker_sdk.py
{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/_api.py
  • crates/core/src/plugin/dynamic/native.rs
  • crates/worker/src/lib.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/worker/tests/worker_sdk_tests.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
**/*.{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/plugin/src/nemo_relay_plugin/_api.py
  • python/tests/test_codecs.py
  • python/tests/plugin/test_worker_sdk.py
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.asyncio to any test; async tests are automatically detected and run by the async runner.
Do not add a -> None return type annotation to test functions.
When mocking a class, do not define a new class; use unittest.mock.MagicMock or unittest.mock.AsyncMock, with the spec constructor argument when necessary.
Name mocked classes with the mock prefix, not fake.
Prefer pytest fixtures over helper methods.
Do not repeat fixtures; if a fixture is needed in multiple test files, place it in a conftest.py file.
When creating a fixture, use @pytest.fixture(name="<fixture_name>"[, scope="<scope>"]) and define the fixture function as def <fixture_name>_fixture() -> <return_type>:; only specify scope when it is not function.
Prefer pytest.mark.parametrize over creating individual tests for different input types.

Files:

  • python/tests/test_codecs.py
  • python/tests/plugin/test_worker_sdk.py
{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.rs
  • crates/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.rs
  • crates/core/src/plugin/dynamic/worker.rs
crates/adaptive/**

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

Keep crates/adaptive aligned with the canonical adaptive config schema, built-in section helpers, plugin lifecycle, and validation/report behavior.

Files:

  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/adaptive/src/acg_profile.rs
{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/_native.pyi
{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/_native.pyi
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/_native.pyi
docs/about-nemo-relay/release-notes/{index,highlights,known-issues}.mdx

📄 CodeRabbit inference engine (.agents/skills/draft-release-notes/SKILL.md)

docs/about-nemo-relay/release-notes/{index,highlights,known-issues}.mdx: Update only docs/about-nemo-relay/release-notes/index.mdx, docs/about-nemo-relay/release-notes/highlights.mdx, and docs/about-nemo-relay/release-notes/known-issues.mdx unless the release changes their route or entry points.
Preserve the existing MDX front matter and the JSX SPDX comment in the release-notes pages.

Files:

  • docs/about-nemo-relay/release-notes/known-issues.mdx
docs/about-nemo-relay/release-notes/known-issues.mdx

📄 CodeRabbit inference engine (.agents/skills/draft-release-notes/SKILL.md)

docs/about-nemo-relay/release-notes/known-issues.mdx: In known-issues.mdx, preserve every prior fixed-item bullet under release-labeled subsections; do not summarize, deduplicate, or omit it.
In known-issues.mdx, keep the complete fixed-item history recorded in earlier release-note pages.

Files:

  • docs/about-nemo-relay/release-notes/known-issues.mdx
{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/worker/tests/worker_sdk_tests.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/src/lib.rs
  • crates/worker/tests/worker_sdk_tests.rs
crates/core/src/observability/{atif,otel,openinference}.rs

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

When changing the core event model, emitted fields, exporter behavior, subscriber config, or lifecycle, keep the ATIF, OpenTelemetry, and OpenInference implementations in sync.

Files:

  • crates/core/src/observability/openinference.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/tests/coverage/py_types_coverage_tests.rs
docs/integrate-into-frameworks/**/*.mdx

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

Update docs if activation or usage changes.

Files:

  • docs/integrate-into-frameworks/provider-codecs.mdx
🧠 Learnings (1)
📚 Learning: 2026-07-02T18:33:06.638Z
Learnt from: yczhang-nv
Repo: NVIDIA/NeMo-Relay PR: 355
File: crates/core/tests/unit/codec/parity_tests.rs:500-548
Timestamp: 2026-07-02T18:33:06.638Z
Learning: In Rust codec parity unit tests, when comparing a computed float/cost against a hand-derived literal (typically documented in a nearby comment), use a tolerance-based assertion rather than `assert_eq!` (e.g., `assert!((total - expected).abs() < 1e-9)`) to avoid harmless floating-point/rounding differences. Keep cross-codec parity assertions (e.g., `assert_eq!(chat_cost, anthropic_cost)`) exact with `assert_eq!` when the intention is a strict parity contract across codecs, since they are expected to share the same estimation path and produce bit-identical output across codecs.

Applied to files:

  • crates/core/tests/unit/codec/parity_tests.rs
🔇 Additional comments (49)
crates/adaptive/src/acg/ir_builder.rs (1)

79-87: LGTM!

crates/adaptive/tests/unit/acg_profile_tests.rs (1)

135-189: LGTM!

Also applies to: 339-455, 457-498

crates/core/tests/unit/observability/openinference_tests.rs (1)

18-19: LGTM!

Also applies to: 101-102, 372-373, 391-402, 4235-4321

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

1841-1852: LGTM!

crates/pii-redaction/src/overlay.rs (1)

295-319: LGTM!

crates/pii-redaction/tests/coverage/overlay_tests.rs (1)

60-85: LGTM!

docs/build-plugins/dynamic-plugins/native-dynamic/rust-native-plugin-example.mdx (1)

32-32: LGTM!

Also applies to: 73-73

docs/integrate-into-frameworks/provider-codecs.mdx (1)

55-59: LGTM!

Also applies to: 62-86, 451-469

docs/reference/llm-request-intercept-outcomes.mdx (1)

46-62: LGTM!

Also applies to: 101-101, 131-145

examples/rust-native-plugin/relay-plugin.toml (1)

11-11: LGTM!

python/nemo_relay/_native.pyi (1)

33-33: LGTM!

Also applies to: 467-485, 504-511, 544-557

python/tests/test_codecs.py (1)

171-195: LGTM!

crates/adaptive/src/acg_profile.rs (1)

90-121: LGTM!

Also applies to: 167-223, 270-272

crates/cli/src/gateway/mod.rs (1)

31-31: LGTM!

Also applies to: 153-199

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

39-41: LGTM!

crates/core/src/codec/openai_chat.rs (2)

561-609: LGTM!

Also applies to: 713-796, 802-948, 949-1254


864-900: 🗄️ Data Integrity & Integration

No issue: MODELED_REQUEST_KEYS already includes the newly modeled request fields, so extra only captures unmodeled keys here.

			> Likely an incorrect or invalid review comment.
crates/core/src/plugin/dynamic/worker.rs (1)

56-56: LGTM!

Also applies to: 66-66, 76-76, 451-456, 615-620, 1641-1641

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

847-879: LGTM!

Also applies to: 1965-2015

crates/worker/src/lib.rs (1)

47-47: LGTM!

Also applies to: 1518-1534, 1774-1787, 1817-1830

crates/worker/tests/worker_sdk_tests.rs (1)

22-25: LGTM!

Also applies to: 1266-1275, 2339-2376

python/plugin/src/nemo_relay_plugin/_api.py (1)

109-110: LGTM!

python/tests/plugin/test_worker_sdk.py (1)

1299-1299: LGTM!

crates/adaptive/tests/integration/runtime_integration_tests.rs (1)

81-82: LGTM!

Also applies to: 117-193, 528-532

crates/adaptive/tests/unit/acg/ir_builder_tests.rs (1)

15-28: LGTM!

Also applies to: 46-61, 121-122, 168-169, 200-300

crates/adaptive/tests/unit/runtime_tests.rs (1)

40-41: LGTM!

Also applies to: 75-76, 417-435, 513-514

crates/cli/tests/coverage/shared/gateway_tests.rs (1)

330-370: LGTM!

Also applies to: 372-412

crates/core/src/codec/anthropic.rs (2)

132-139: LGTM!

Also applies to: 169-179, 520-562, 706-821


823-1041: Both previously-flagged surgical-edit gaps look resolved. The (None, _) tool_choice arm now synthesizes an Auto choice carrying parallel_tool_calls instead of silently dropping the edit, and the tools/tool_choice/messages paths now patch against the original JSON (super::patch_changed_json/super::encode_changed_items) instead of fully reconstructing, preserving unknown nested fields and explicit nulls. Note: the shared array-alignment helper these paths delegate to (crates/core/src/codec/mod.rs) has a residual misattribution edge case for insert+delete pairs — see the corresponding comment on that file; it applies here too since messages (829-838) and tools (883-898) both use super::encode_changed_items.

crates/core/src/codec/mod.rs (2)

28-100: LGTM!

Also applies to: 102-121, 230-266


213-228: 🎯 Functional Correctness

No issue with this let-chain syntax. The workspace is on Rust 2024 and pinned to toolchain 1.96.1, so this code is valid here.

			> Likely an incorrect or invalid review comment.
crates/core/tests/unit/codec/parity_tests.rs (1)

683-695: LGTM!

Also applies to: 729-784

crates/types/src/api/llm.rs (1)

14-18: LGTM!

docs/about-nemo-relay/release-notes/known-issues.mdx (1)

84-113: LGTM!

Also applies to: 310-313

docs/build-plugins/dynamic-plugins/about.mdx (1)

67-73: LGTM!

docs/build-plugins/dynamic-plugins/grpc-worker/about.mdx (1)

67-72: LGTM!

docs/build-plugins/dynamic-plugins/native-dynamic/about.mdx (1)

58-62: LGTM!

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

2650-2704: LGTM!

crates/core/src/codec/openai_responses.rs (2)

671-796: LGTM! Wrapped-function-tool name edits now correctly patch the nested function object (via patch_responses_tool) instead of flattening into a conflicting top-level name, resolving the previously flagged issue on this segment.


1130-1201: 🗄️ Data Integrity & Integration

No issue: MODELED_REQUEST_KEYS already covers every field read in decode(), so extra won’t duplicate the typed fields.

			> Likely an incorrect or invalid review comment.
crates/core/src/observability/openinference.rs (1)

1096-1131: LGTM! Function and ProviderNative message content are now correctly projected into span attributes, resolving the previously flagged content-loss issue.

Also applies to: 1173-1183

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

260-266: LGTM!

Also applies to: 290-400, 1347-1382

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

938-959: LGTM!

Also applies to: 1141-1165

crates/core/tests/unit/codec/anthropic_tests.rs (1)

776-834: LGTM!

Also applies to: 894-910

crates/core/tests/unit/codec/openai_chat_tests.rs (1)

1365-1409: LGTM!

Also applies to: 1432-1481

crates/core/tests/unit/codec/openai_responses_tests.rs (1)

815-844: LGTM!

Also applies to: 871-910

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

402-402: LGTM!

Also applies to: 418-418

crates/python/tests/coverage/py_types_coverage_tests.rs (1)

1075-1099: LGTM! Fully addresses the previously flagged coverage gap for instructions/api_specific (round-trip, mutation, clearing, invalid input, and forced-serialization hooks all present).

Also applies to: 1143-1152, 1190-1197, 1229-1239, 1248-1278, 1537-1566, 1647-1671

crates/types/src/codec/request.rs (1)

15-19: LGTM! Moving instructions out of the messages array (and prioritizing it in system_prompt) is the correct structural fix for the issue #501 corruption bug, and the schema bump to @2 correctly reflects the new tagged variants.

Also applies to: 591-601, 608-620, 626-644

Comment thread crates/core/src/codec/mod.rs Outdated
Comment thread crates/core/src/plugin/dynamic.rs
Signed-off-by: Will Killian <wkillian@nvidia.com>

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

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/codec/mod.rs (1)

166-222: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Single-pair fallback still cross-wires unrelated insert/delete items.

The >1 && >1 guard (lines 204-209) only blocks ambiguity when both sides have multiple unmatched items. It does not stop the exact scenario flagged previously: baseline=[A,B,C], edited=[A,C,X] (B deleted, C reordered, X inserted) → unmatched_edited=[X], unmatched_baseline=[B] → the else if let ([edited_index], [baseline_index]) = ... branch at lines 215-219 unconditionally pairs X with B. patch_changed_json/patch_changed_array then grafts B's original-only provider fields (id, cache_control, etc.) onto the unrelated new item X — silent cross-item field leakage, not an error, contradicting the PR's stated guarantee that unsupported/ambiguous edits must "remain intact... or produce an explicit error."

This affects every provider codec that reuses encode_changed_items/encode_changed_items_with_patch (Anthropic messages/tools, OpenAI Chat messages/tools, OpenAI Responses input/tools), so the fix belongs here once.

🐛 Proposed fix: drop the ambiguous 1:1 fallback
-    if !structurally_changed && edited.len() == baseline.len() {
-        for index in unmatched_edited {
-            alignment[index] = Some(index);
-        }
-    } else if let ([edited_index], [baseline_index]) =
-        (unmatched_edited.as_slice(), unmatched_baseline.as_slice())
-    {
-        alignment[*edited_index] = Some(*baseline_index);
-    }
+    if !structurally_changed && edited.len() == baseline.len() {
+        for index in unmatched_edited {
+            alignment[index] = Some(index);
+        }
+    }
+    // Do not positionally pair a single unmatched edited item with a single
+    // unmatched baseline item: without a stable identity/discriminator this
+    // cannot distinguish "same item edited" from "unrelated insert+delete",
+    // and mispairing leaks baseline-only provider fields onto the wrong item.
+    // Leaving it unaligned falls through to `encode(item)` (safe: no reuse,
+    // no corruption).

A regression test mirroring the coderabbitai example (baseline=[A,B,C], edited=[A,C,X]) belongs in crates/core/tests/unit/codec/parity_tests.rs.

🤖 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/codec/mod.rs` around lines 166 - 222, Remove the single-pair
fallback in align_changed_items that unconditionally maps one unmatched edited
item to one unmatched baseline item. For cases such as a deletion, reorder, and
insertion, leave the unmatched entries unaligned so provider-only fields cannot
be copied between unrelated items; preserve direct matches and existing safe
ambiguity handling. Add a regression test in parity_tests.rs covering baseline
[A,B,C] and edited [A,C,X].
🤖 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/codec/mod.rs`:
- Around line 166-222: Remove the single-pair fallback in align_changed_items
that unconditionally maps one unmatched edited item to one unmatched baseline
item. For cases such as a deletion, reorder, and insertion, leave the unmatched
entries unaligned so provider-only fields cannot be copied between unrelated
items; preserve direct matches and existing safe ambiguity handling. Add a
regression test in parity_tests.rs covering baseline [A,B,C] and edited [A,C,X].

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 3bb79caf-659c-41b4-bfc6-656cbe14a8e4

📥 Commits

Reviewing files that changed from the base of the PR and between e17c140 and 73de11f.

📒 Files selected for processing (6)
  • crates/core/src/codec/anthropic.rs
  • crates/core/src/codec/mod.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/core/tests/unit/codec/openai_chat_tests.rs
  • crates/core/tests/unit/codec/parity_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 (15)
**/*.rs

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

**/*.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

When changing the core Rust runtime or Rust-facing API surface, format Rust code with cargo fmt (rustfmt defaults), keep cargo clippy -- -D warnings clean, and satisfy cargo deny check per deny.toml.

**/*.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.
For Rust changes headed for review, run cargo fmt --all and cargo clippy --workspace --all-targets -- -D warnings even if relying on pre-commit.

Files:

  • crates/core/tests/unit/codec/parity_tests.rs
  • crates/core/src/codec/mod.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/src/codec/anthropic.rs
  • crates/core/tests/unit/codec/openai_chat_tests.rs
  • crates/core/src/codec/openai_responses.rs
{crates/core,crates/adaptive}/**/*

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

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

Files:

  • crates/core/tests/unit/codec/parity_tests.rs
  • crates/core/src/codec/mod.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/src/codec/anthropic.rs
  • crates/core/tests/unit/codec/openai_chat_tests.rs
  • crates/core/src/codec/openai_responses.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

Files:

  • crates/core/tests/unit/codec/parity_tests.rs
  • crates/core/src/codec/mod.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/src/codec/anthropic.rs
  • crates/core/tests/unit/codec/openai_chat_tests.rs
  • crates/core/src/codec/openai_responses.rs
**/*.{rs,py}

📄 CodeRabbit inference engine (AGENTS.md)

Follow binding naming conventions in Rust and Python: use snake_case.

Files:

  • crates/core/tests/unit/codec/parity_tests.rs
  • crates/core/src/codec/mod.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/src/codec/anthropic.rs
  • crates/core/tests/unit/codec/openai_chat_tests.rs
  • crates/core/src/codec/openai_responses.rs
**/*.{rs,py,js,mjs,cjs,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{rs,py,js,mjs,cjs,ts,tsx}: 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, 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/core/tests/unit/codec/parity_tests.rs
  • crates/core/src/codec/mod.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/src/codec/anthropic.rs
  • crates/core/tests/unit/codec/openai_chat_tests.rs
  • crates/core/src/codec/openai_responses.rs
**/*.{rs,py,go,js,ts,c,h}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Use language-appropriate naming conventions: Rust snake_case, C FFI exports prefixed nemo_relay_, Go PascalCase, Node.js camelCase, and Python snake_case.

Files:

  • crates/core/tests/unit/codec/parity_tests.rs
  • crates/core/src/codec/mod.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/src/codec/anthropic.rs
  • crates/core/tests/unit/codec/openai_chat_tests.rs
  • crates/core/src/codec/openai_responses.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/core/tests/unit/codec/parity_tests.rs
  • crates/core/src/codec/mod.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/src/codec/anthropic.rs
  • crates/core/tests/unit/codec/openai_chat_tests.rs
  • crates/core/src/codec/openai_responses.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, use maintain-dynamic-plugins and 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, prefer uv run pre-commit run --files <changed files...>.
Before review or handoff, run uv run pre-commit run --all-files.

Files:

  • crates/core/tests/unit/codec/parity_tests.rs
  • crates/core/src/codec/mod.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/src/codec/anthropic.rs
  • crates/core/tests/unit/codec/openai_chat_tests.rs
  • crates/core/src/codec/openai_responses.rs
crates/{core,adaptive}/**/*

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

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

Files:

  • crates/core/tests/unit/codec/parity_tests.rs
  • crates/core/src/codec/mod.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/src/codec/anthropic.rs
  • crates/core/tests/unit/codec/openai_chat_tests.rs
  • crates/core/src/codec/openai_responses.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/core/tests/unit/codec/parity_tests.rs
  • crates/core/src/codec/mod.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/src/codec/anthropic.rs
  • crates/core/tests/unit/codec/openai_chat_tests.rs
  • crates/core/src/codec/openai_responses.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/core/tests/unit/codec/parity_tests.rs
  • crates/core/src/codec/mod.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/src/codec/anthropic.rs
  • crates/core/tests/unit/codec/openai_chat_tests.rs
  • crates/core/src/codec/openai_responses.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/codec/parity_tests.rs
  • crates/core/src/codec/mod.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/src/codec/anthropic.rs
  • crates/core/tests/unit/codec/openai_chat_tests.rs
  • crates/core/src/codec/openai_responses.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/unit/codec/parity_tests.rs
  • crates/core/tests/unit/codec/openai_chat_tests.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 as crates/core/src/api/runtime/, crates/core/src/codec/, and crates/core/src/json.rs.

Files:

  • crates/core/src/codec/mod.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/src/codec/anthropic.rs
  • crates/core/src/codec/openai_responses.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 crate tests/ trees, and Python SDK tests belong under python/tests.

Files:

  • crates/core/src/codec/mod.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/src/codec/anthropic.rs
  • crates/core/src/codec/openai_responses.rs
🧠 Learnings (1)
📚 Learning: 2026-07-02T18:33:06.638Z
Learnt from: yczhang-nv
Repo: NVIDIA/NeMo-Relay PR: 355
File: crates/core/tests/unit/codec/parity_tests.rs:500-548
Timestamp: 2026-07-02T18:33:06.638Z
Learning: In Rust codec parity unit tests, when comparing a computed float/cost against a hand-derived literal (typically documented in a nearby comment), use a tolerance-based assertion rather than `assert_eq!` (e.g., `assert!((total - expected).abs() < 1e-9)`) to avoid harmless floating-point/rounding differences. Keep cross-codec parity assertions (e.g., `assert_eq!(chat_cost, anthropic_cost)`) exact with `assert_eq!` when the intention is a strict parity contract across codecs, since they are expected to share the same estimation path and produce bit-identical output across codecs.

Applied to files:

  • crates/core/tests/unit/codec/parity_tests.rs
🔇 Additional comments (6)
crates/core/src/codec/mod.rs (1)

28-100: LGTM!

Also applies to: 102-121, 123-164, 224-239, 241-277

crates/core/src/codec/anthropic.rs (1)

706-1041: LGTM!

crates/core/src/codec/openai_chat.rs (1)

802-1254: LGTM!

crates/core/src/codec/openai_responses.rs (1)

757-791: LGTM!

Also applies to: 1077-1383

crates/core/tests/unit/codec/openai_chat_tests.rs (1)

1410-1452: LGTM!

crates/core/tests/unit/codec/parity_tests.rs (1)

729-756: LGTM!

Also applies to: 758-784, 785-807

@coderabbitai coderabbitai Bot added the invalid PR seems invalid label Jul 21, 2026
@bbednarski9

Copy link
Copy Markdown
Contributor

P2: malformed modeled structured controls are still forwarded

I reproduced this against the current PR head, commit 8756844d52f34a9ee7b8787054bd4b3300351830.

The scalar validation added in the recent commits works, including Chat seed, but recognized fields stored as raw Json still do not validate their outer JSON shape.

Cases tested

Codec Recognized field Malformed value Expected shape
OpenAI Chat Completions response_format "json_object" object
OpenAI Responses include "reasoning.encrypted_content" array
Anthropic Messages metadata "user-123" object

For all three cases, the diagnostic test confirmed that:

  1. decode() returned Ok.
  2. The recognized field was excluded from annotated.extra.
  3. encode(&annotated, &original) reproduced the malformed value unchanged.

I also exercised the Chat case through the real gateway request-interceptor path. A request containing response_format: "json_object" received HTTP 200 from the relay test gateway, and the mock upstream captured that malformed value unchanged. This shows the value reaches the provider callback rather than being rejected at the codec boundary.

The focused results were:

running 3 tests
test codec::anthropic::tests::review_probe_malformed_modeled_structure_is_accepted_anthropic ... ok
test codec::openai_responses::tests::review_probe_malformed_modeled_structure_is_accepted_responses ... ok
test codec::openai_chat::tests::review_probe_chat_seed_mutation_and_malformed_structure ... ok

test result: ok. 3 passed; 0 failed

running 1 test
test server::tests::review_probe_gateway_seed_and_malformed_structure ... ok

test result: ok. 1 passed; 0 failed

These passing tests assert the current behavior, so they confirm the gap rather than the desired contract. This conflicts with the PR description's guarantee that malformed recognized structures are rejected before the provider callback.

Suggested fix and cost

The decode paths currently use direct .cloned() reads for these fields (and several adjacent object/array-valued controls). I suggest adding shallow optional_object and optional_array helpers alongside the existing scalar helpers, then using them for fields whose provider schema has an unambiguous outer type. Unknown members inside valid objects should remain untouched.

This should have negligible compute overhead. serde_json::Value has already been parsed, so validation only checks its enum variant—constant-time, with no schema traversal or reserialization. The existing .cloned() call already performs the potentially meaningful copy; inspecting the value's outer type first does not add another allocation.

Relevant decode sites:

  • crates/core/src/codec/openai_chat.rs around metadata, response_format, and the other raw-JSON API controls.
  • crates/core/src/codec/openai_responses.rs around truncation, reasoning, include, metadata, and raw-JSON API controls.
  • crates/core/src/codec/anthropic.rs around metadata, cache_control, output_config, and thinking.

Signed-off-by: Will Killian <wkillian@nvidia.com>
@coderabbitai coderabbitai Bot removed the invalid PR seems invalid label Jul 21, 2026

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

Caution

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

⚠️ Outside diff range comments (2)
crates/core/src/codec/openai_chat.rs (1)

896-953: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

function_call bypasses the new structured-field validation.

Every other newly-added field here uses super::optional_object(...), but function_call: obj.get("function_call").cloned() (Line 935) reads the raw value with no type check at all. Since the deprecated OpenAI function_call control accepts "none"/"auto" (string) or {"name": ...} (object), optional_object can't be reused directly — but that's not a reason to skip validation entirely. A malformed function_call (e.g. a number or array) will decode successfully, get embedded in api_specific, and be forwarded to the provider unchanged on encode — exactly the "malformed recognized structures forwarded unchanged" bug this PR's fix commit targets. The malformed-field test matrix at openai_chat_tests.rs L1497-1511 confirms this gap: every other structured field is covered except function_call.

🛡️ Proposed fix to validate function_call's union type
+        let function_call = match obj.get("function_call") {
+            Some(Json::Null) | None => None,
+            Some(value @ (Json::String(_) | Json::Object(_))) => Some(value.clone()),
+            Some(_) => {
+                return Err(FlowError::InvalidArgument(
+                    "OpenAI Chat function_call must be a string, object, or null".into(),
+                ));
+            }
+        };
         let metadata = super::optional_object(obj, "metadata", "OpenAI Chat")?;
             api_specific: Some(ApiSpecificRequest::OpenAIChat {
                 audio,
                 frequency_penalty,
-                function_call: obj.get("function_call").cloned(),
+                function_call,
                 functions,
🤖 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/codec/openai_chat.rs` around lines 896 - 953, Validate the
`function_call` field in the request-decoding path before constructing
`ApiSpecificRequest::OpenAIChat`: allow only the supported string values
(`"none"` or `"auto"`) or the expected object form, while rejecting numbers,
arrays, and other malformed values. Replace the raw
`obj.get("function_call").cloned()` handling with this union-type validation and
preserve the validated value for encoding.
crates/core/src/codec/openai_responses.rs (1)

1157-1205: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

conversation has the same unvalidated union-type gap as function_call.

conversation: obj.get("conversation").cloned() (Line 1196) is newly touched in this hunk but skips validation entirely, unlike the surrounding reasoning/include/metadata/etc. fields that now use optional_object/optional_array. OpenAI Responses conversation accepts either a string ID or an object; a malformed value (number, array, bool) will decode without error and be forwarded to the provider unchanged on encode, which is the exact bug class this PR's fix commit is meant to close. The malformed-field matrix at openai_responses_tests.rs L887-900 confirms conversation isn't covered.

🛡️ Proposed fix to validate conversation's union type
+        let conversation = match obj.get("conversation") {
+            Some(Json::Null) | None => None,
+            Some(value @ (Json::String(_) | Json::Object(_))) => Some(value.clone()),
+            Some(_) => {
+                return Err(FlowError::InvalidArgument(
+                    "OpenAI Responses conversation must be a string, object, or null".into(),
+                ));
+            }
+        };
         let text = super::optional_object(obj, "text", "OpenAI Responses")?;
             api_specific: Some(ApiSpecificRequest::OpenAIResponses {
                 background,
                 context_management,
-                conversation: obj.get("conversation").cloned(),
+                conversation,
                 moderation,
🤖 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/codec/openai_responses.rs` around lines 1157 - 1205, Validate
the OpenAI Responses `conversation` field before constructing
`ApiSpecificRequest::OpenAIResponses`, accepting only its supported string-ID or
object forms and rejecting numbers, arrays, booleans, and other invalid values.
Replace the direct `obj.get("conversation").cloned()` assignment in the request
decoder with the appropriate validated parsing flow, and add `conversation` to
the malformed-field coverage in `openai_responses_tests.rs`.
🤖 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/codec/openai_chat.rs`:
- Around line 896-953: Validate the `function_call` field in the
request-decoding path before constructing `ApiSpecificRequest::OpenAIChat`:
allow only the supported string values (`"none"` or `"auto"`) or the expected
object form, while rejecting numbers, arrays, and other malformed values.
Replace the raw `obj.get("function_call").cloned()` handling with this
union-type validation and preserve the validated value for encoding.

In `@crates/core/src/codec/openai_responses.rs`:
- Around line 1157-1205: Validate the OpenAI Responses `conversation` field
before constructing `ApiSpecificRequest::OpenAIResponses`, accepting only its
supported string-ID or object forms and rejecting numbers, arrays, booleans, and
other invalid values. Replace the direct `obj.get("conversation").cloned()`
assignment in the request decoder with the appropriate validated parsing flow,
and add `conversation` to the malformed-field coverage in
`openai_responses_tests.rs`.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 63505c70-55c0-4ef5-b52b-83324153e67b

📥 Commits

Reviewing files that changed from the base of the PR and between 8756844 and 056b78f.

📒 Files selected for processing (8)
  • crates/cli/tests/coverage/shared/server_tests.rs
  • crates/core/src/codec/anthropic.rs
  • crates/core/src/codec/mod.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/core/tests/unit/codec/anthropic_tests.rs
  • crates/core/tests/unit/codec/openai_chat_tests.rs
  • crates/core/tests/unit/codec/openai_responses_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 (15)
**/*.rs

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

**/*.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

When changing the core Rust runtime or Rust-facing API surface, format Rust code with cargo fmt (rustfmt defaults), keep cargo clippy -- -D warnings clean, and satisfy cargo deny check per deny.toml.

**/*.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.
For Rust changes headed for review, run cargo fmt --all and cargo clippy --workspace --all-targets -- -D warnings even if relying on pre-commit.

Files:

  • crates/core/src/codec/mod.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/src/codec/anthropic.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/cli/tests/coverage/shared/server_tests.rs
  • crates/core/tests/unit/codec/anthropic_tests.rs
  • crates/core/tests/unit/codec/openai_chat_tests.rs
{crates/core,crates/adaptive}/**/*

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

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

Files:

  • crates/core/src/codec/mod.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/src/codec/anthropic.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/core/tests/unit/codec/anthropic_tests.rs
  • crates/core/tests/unit/codec/openai_chat_tests.rs
crates/core/**/*.rs

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

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

Files:

  • crates/core/src/codec/mod.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/src/codec/anthropic.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/core/tests/unit/codec/anthropic_tests.rs
  • crates/core/tests/unit/codec/openai_chat_tests.rs
**/*.{rs,py}

📄 CodeRabbit inference engine (AGENTS.md)

Follow binding naming conventions in Rust and Python: use snake_case.

Files:

  • crates/core/src/codec/mod.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/src/codec/anthropic.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/cli/tests/coverage/shared/server_tests.rs
  • crates/core/tests/unit/codec/anthropic_tests.rs
  • crates/core/tests/unit/codec/openai_chat_tests.rs
**/*.{rs,py,js,mjs,cjs,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{rs,py,js,mjs,cjs,ts,tsx}: 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, 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/core/src/codec/mod.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/src/codec/anthropic.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/cli/tests/coverage/shared/server_tests.rs
  • crates/core/tests/unit/codec/anthropic_tests.rs
  • crates/core/tests/unit/codec/openai_chat_tests.rs
**/*.{rs,py,go,js,ts,c,h}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Use language-appropriate naming conventions: Rust snake_case, C FFI exports prefixed nemo_relay_, Go PascalCase, Node.js camelCase, and Python snake_case.

Files:

  • crates/core/src/codec/mod.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/src/codec/anthropic.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/cli/tests/coverage/shared/server_tests.rs
  • crates/core/tests/unit/codec/anthropic_tests.rs
  • crates/core/tests/unit/codec/openai_chat_tests.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/core/src/codec/mod.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/src/codec/anthropic.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/cli/tests/coverage/shared/server_tests.rs
  • crates/core/tests/unit/codec/anthropic_tests.rs
  • crates/core/tests/unit/codec/openai_chat_tests.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 as crates/core/src/api/runtime/, crates/core/src/codec/, and crates/core/src/json.rs.

Files:

  • crates/core/src/codec/mod.rs
  • crates/core/src/codec/anthropic.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/src/codec/openai_responses.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 crate tests/ trees, and Python SDK tests belong under python/tests.

Files:

  • crates/core/src/codec/mod.rs
  • crates/core/src/codec/anthropic.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/src/codec/openai_responses.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, use maintain-dynamic-plugins and 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, prefer uv run pre-commit run --files <changed files...>.
Before review or handoff, run uv run pre-commit run --all-files.

Files:

  • crates/core/src/codec/mod.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/src/codec/anthropic.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/cli/tests/coverage/shared/server_tests.rs
  • crates/core/tests/unit/codec/anthropic_tests.rs
  • crates/core/tests/unit/codec/openai_chat_tests.rs
crates/{core,adaptive}/**/*

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

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

Files:

  • crates/core/src/codec/mod.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/src/codec/anthropic.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/core/tests/unit/codec/anthropic_tests.rs
  • crates/core/tests/unit/codec/openai_chat_tests.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/core/src/codec/mod.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/src/codec/anthropic.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/cli/tests/coverage/shared/server_tests.rs
  • crates/core/tests/unit/codec/anthropic_tests.rs
  • crates/core/tests/unit/codec/openai_chat_tests.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/core/src/codec/mod.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/src/codec/anthropic.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/cli/tests/coverage/shared/server_tests.rs
  • crates/core/tests/unit/codec/anthropic_tests.rs
  • crates/core/tests/unit/codec/openai_chat_tests.rs
crates/{core,adaptive}/**/*.rs

⚙️ CodeRabbit configuration file

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

Files:

  • crates/core/src/codec/mod.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/src/codec/anthropic.rs
  • crates/core/src/codec/openai_chat.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/core/tests/unit/codec/anthropic_tests.rs
  • crates/core/tests/unit/codec/openai_chat_tests.rs
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}

⚙️ CodeRabbit configuration file

{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}: Tests should cover the behavior promised by the changed API surface, including error paths and cross-request isolation where relevant.
Prefer assertions on lifecycle events, scope stacks, middleware ordering, and binding parity over shallow smoke tests.

Files:

  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/cli/tests/coverage/shared/server_tests.rs
  • crates/core/tests/unit/codec/anthropic_tests.rs
  • crates/core/tests/unit/codec/openai_chat_tests.rs
🔇 Additional comments (6)
crates/cli/tests/coverage/shared/server_tests.rs (1)

2650-2676: LGTM!

crates/core/src/codec/mod.rs (1)

102-128: LGTM!

crates/core/tests/unit/codec/anthropic_tests.rs (1)

802-823: LGTM!

crates/core/tests/unit/codec/openai_chat_tests.rs (1)

1497-1520: LGTM!

crates/core/tests/unit/codec/openai_responses_tests.rs (1)

887-909: LGTM!

crates/core/src/codec/anthropic.rs (1)

785-822: 🗄️ Data Integrity & Integration

metadata is already modeled and excluded from extra. It’s listed in MODELED_REQUEST_KEYS, so it won’t leak into extra here.

			> Likely an incorrect or invalid review comment.

@willkill07

Copy link
Copy Markdown
Member Author

/merge

@rapids-bot
rapids-bot Bot merged commit c561b29 into NVIDIA:release/0.6 Jul 21, 2026
60 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking PR introduces a breaking change Bug issue describes bug; PR fixes bug lang:js PR changes/introduces Javascript/Typescript code lang:python PR changes/introduces Python code lang:rust PR changes/introduces Rust code size:XXL PR is very large

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants