Skip to content

Forward-merge release/0.6 into main#527

Merged
willkill07 merged 11 commits into
NVIDIA:mainfrom
willkill07:main-merge-release/0.6
Jul 22, 2026
Merged

Forward-merge release/0.6 into main#527
willkill07 merged 11 commits into
NVIDIA:mainfrom
willkill07:main-merge-release/0.6

Conversation

@willkill07

@willkill07 willkill07 commented Jul 22, 2026

Copy link
Copy Markdown
Member

Overview

Manual non-squash forward merge of release/0.6 into main.

  • 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

  • Preserves the release/0.6 history in a merge commit, as required by the forward-merger process.
  • Updates every explicit 0.6.0 package-install or package-dependency pin introduced by this forward merge to 0.7.0.
  • Leaves historical 0.6 migration guidance unchanged.

Where should the reviewer start?

Review merge commit 89786bd1, especially the Node install and dynamic-plugin dependency examples that now use 0.7.0.

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

Summary by CodeRabbit

  • New Features

    • Added lossless request editing for Anthropic Messages, OpenAI Chat Completions, and OpenAI Responses, including streaming routes.
    • Added support for instructions, provider-specific fields, multimodal content, native messages, and expanded tool formats.
    • Added trajectory-preserving PII redaction with configurable custom-mark handling.
    • Added safer Node.js and Python callback handling for invalid or circular results.
  • Bug Fixes

    • Prevented request intercepts from changing streaming mode.
    • Improved skill-load detection across supported shells and resource readers.
    • Preserved provider metadata, nulls, ordering, and cache controls during request edits.
  • Documentation

    • Expanded migration, codec, observability, plugin compatibility, and getting-started guidance.

bbednarski9 and others added 11 commits July 21, 2026 03:59
…DIA#513)

> [!WARNING]
> **BREAKING CHANGE — Rust built-in PII configuration API and serialized configuration:** `BuiltinBackendConfig` now includes the public `preset` and `custom_mark_payload_policy` fields, so downstream exhaustive struct literals must initialize them or use `..Default::default()`. The default `action = "remove"` value is now omitted during serialization, so consumers that depend on the previous exact serialized shape must update. Existing TOML and JSON configurations remain accepted, and existing runtime behavior is unchanged when `preset` is omitted; structure-preserving trajectory redaction is opt-in.

#### Overview

Adds a structure-preserving `trajectory_context` policy to the composable PII-redaction contract. Exported trajectories can retain conversation topology, tool-call relationships, agent hierarchy, routing, usage, cost, and optimization telemetry while removing request/response content.

This draft is intentionally stacked on [NVIDIA#512](NVIDIA#512). Review this PR relative to `bbednarski/pii-profile-composition`; its base can move to `release/0.6` after NVIDIA#512 merges.

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

#### Details

- Adds the built-in `trajectory_context` preset for OpenAI Chat Completions, OpenAI Responses, and Anthropic Messages event shapes, including buffered and streaming flows.
- Redacts chat text, reasoning, multimodal references, tool inputs/outputs, nested-agent content, and stringified tool arguments while preserving structural identifiers and analytical fields.
- Sanitizes typed Relay marks semantically so lifecycle, model-routing, token, usage, cost, and optimization data remain useful.
- Adds `custom_mark_payload_policy`:
  - `preserve` (default) leaves opaque third-party mark payloads unchanged.
  - `redact_all_leaves` recursively replaces scalar payload leaves while retaining keys, arrays, objects, and typed category identity.
- Keeps email redaction composable as a later profile so addresses are also removed from retained metadata and custom marks.
- Sanitizes canonical event fields before subscriber fan-out. Exporter-owned resource attributes remain outside this plugin boundary.
- Updates the CLI editor, schema coverage, and crate documentation.

The policy changes only observability data; it does not rewrite the provider request or client-visible provider response.

#### Where should the reviewer start?

Start in `crates/pii-redaction/src/trajectory.rs` for the semantic redaction boundary, then review preset validation and wiring in `crates/pii-redaction/src/component.rs`. Provider-shape, streaming, mark-policy, and exporter-facing regression coverage is in `crates/pii-redaction/tests/unit/component_tests.rs`.

Validation performed on the complete stack:

```text
cargo fmt --all -- --check
cargo test -p nemo-relay-pii-redaction --features schema
cargo clippy -p nemo-relay-pii-redaction --all-targets --features schema -- -D warnings
cargo test -p nemo-relay-cli pii_redaction
```

The PII crate suite passes 83 tests, and the focused CLI suite passes 7 tests.

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

- Depends on NVIDIA#512.



## Summary by CodeRabbit

* **New Features**
  * Added multiple ordered PII redaction profiles with profile-scoped backend registration and rollback-aware setup.
  * Added `trajectory_context` built-in preset for structure-preserving conversational sanitization.
  * Added `custom_mark_payload_policy` handling for unknown custom marks (preserve vs redact-all-leaves), including preset-specific constraints.
* **Documentation**
  * Updated plugin scope and configuration docs for profile-array mode, ordering/compatibility rules, and trajectory sanitization workflows.
* **Tests**
  * Expanded coverage for profile validation/registration, `trajectory_context` request/response/event sanitization, custom mark policies, and streaming finalization/export redaction.

Authors:
  - Bryan Bednarski (https://github.com/bbednarski9)

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

URL: NVIDIA#513
#### 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.

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

#### Details

* 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)

* Closes NVIDIA#501

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

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

Approvers:
  - Bryan Bednarski (https://github.com/bbednarski9)

URL: NVIDIA#509
#### Overview

Update CODEOWNERS to use the NeMo Relay developer, dependency approver, documentation reviewer, and administrator teams.

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

#### Details

- Replace NAT ownership teams with NeMo Relay ownership teams.
- Assign `/.github/CODEOWNERS` to `@nvidia/nemo-relay-admins`.
- Assign documentation paths to the NeMo Relay documentation reviewers and developers.

#### Where should the reviewer start?

Review `.github/CODEOWNERS`.

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

- Relates to: none



## Summary by CodeRabbit

* **Chores**
  * Updated repository ownership and review assignments.
  * Added dedicated administrative review for ownership configuration.
  * Updated documentation and attribution review assignments to the appropriate teams.

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

Approvers:
  - Bryan Bednarski (https://github.com/bbednarski9)

URL: NVIDIA#516
#### Overview

Clarify when NeMo Relay subscribers and observability exporters finish processing events, including the behavior during graceful and abrupt shutdown.

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

#### Details

- Define emitted, delivered, and exported events in the subscriber concept documentation.
- Document the shared subscriber flush barrier and the downstream barriers for ATOF, ATIF, OpenTelemetry, and OpenInference.
- Explain the file and stream differences for ATOF, including the limits of process-writer flushing and abrupt termination.
- Clarify ATIF export timing and remove the redundant subscriber flush from the Rust example.
- Update the Node.js custom subscriber example to allow an event-loop turn after native dispatch.
- Update public ATOF method comments in the Rust, Python, and Node.js bindings without changing behavior or signatures.
- Preserve the existing fail-open telemetry behavior. This change has no runtime, configuration, compatibility, or breaking change.

Validation:

- `uv run pre-commit run --all-files`
- `just docs-linkcheck`
- `just docs`
- `git diff --check`
- Runtime test suites were not run because the change is limited to documentation, examples, and public doc comments.

#### Where should the reviewer start?

Start with `docs/about-nemo-relay/concepts/subscribers.mdx`, which defines the canonical delivery contract and the boundary between subscriber flush and exporter-specific completion.

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

- Relates to: RELAY-541



## Summary by CodeRabbit

- **Documentation**
  - Clarified telemetry lifecycle milestones (emitted vs delivered vs exported) and the correct barrier semantics for queued delivery, file sink flushing, and stream sink draining/closing (including stream timeouts being logged without failing).
  - Updated `force_flush()`/`shutdown()` and `flush_subscribers()` guidance across Rust, Python, native typings, and FFI, including re-entrant behavior and ordering.
  - Expanded observability plugin teardown and configuration guidance (including plugin teardown steps and warnings about telemetry loss/truncated outputs on abrupt termination).
  - Refreshed ATIF/ATOF, OpenTelemetry/OpenInference, and Node “Getting Started” (extra event-loop turn after scope creation).

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

Approvers:
  - Bryan Bednarski (https://github.com/bbednarski9)

URL: NVIDIA#518
#### Overview

Update the NeMo Relay 0.6 release notes for the PII redaction changes in PRs NVIDIA#512 and NVIDIA#513. The release notes now explain the new composable profiles and structure-preserving trajectory redaction in plain language, with migration warnings for the breaking Rust configuration and serialization changes.

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

#### Details

- Update the 0.6 release summary and highlights with the new PII redaction capabilities.
- Add migration warnings for `PiiRedactionConfig.profiles`, `BuiltinBackendConfig.preset`, `custom_mark_payload_policy`, and the changed serialized defaults.
- Document that `trajectory_context` is opt-in and changes observability data without changing provider requests or client-visible responses.
- Keep the change limited to `docs/about-nemo-relay/release-notes/`.

Validation:

- `git diff --check`
- `just docs`
- `just docs-linkcheck`
- `uv run pre-commit run --files docs/about-nemo-relay/release-notes/index.mdx docs/about-nemo-relay/release-notes/highlights.mdx docs/about-nemo-relay/release-notes/known-issues.mdx`

#### Where should the reviewer start?

Start with `docs/about-nemo-relay/release-notes/known-issues.mdx` to review the migration warnings, then review the user-facing summaries in `index.mdx` and `highlights.mdx`.

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

- Relates to NVIDIA#512
- Relates to NVIDIA#513




## Summary by CodeRabbit

* **Documentation**
  * Documented composable, priority-based PII redaction profiles.
  * Added details about the opt-in `trajectory_context` preset, which removes sensitive request and response content while preserving conversation structure and telemetry.
  * Added migration guidance for configuration changes, serialization behavior, and custom mark redaction policies.
  * Updated release scope and known-issues documentation for Relay 0.6 compatibility.

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

Approvers:
  - Bryan Bednarski (https://github.com/bbednarski9)

URL: NVIDIA#522
#### Overview

Resolve the NeMo Relay 0.6 documentation gaps identified in the VDR preparation report.

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

#### Details

- Pin published Node.js installation examples to `nemo-relay-node@0.6.0`.
- Replace the stale versioned Build Plugins README link.
- Add factual positioning for OpenTelemetry GenAI conventions and observability or evaluation products, with links from the Overview and README.

#### Where should the reviewer start?

Review `docs/about-nemo-relay/ecosystem.mdx` for the new comparison, then the Node.js installation examples and README entry points.

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

- Relates to: none




## Summary by CodeRabbit

- **Documentation**
  - Added an ecosystem guide explaining how NeMo Relay complements telemetry, observability, and evaluation tooling.
  - Linked the new ecosystem guidance from relevant introductory documentation.
  - Updated Build Plugins documentation links.
  - Standardized Node.js installation instructions to use `nemo-relay-node@0.6.0` across the README and setup guides.

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

Approvers:
  - Eric Evans II (https://github.com/ericevans-nv)

URL: NVIDIA#521
#### Overview

Extend Relay's best-effort `skill.load` detection to cover additional reviewed structured readers, path fields, and single-layer shell wrappers while preserving the existing event contract.

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

#### Details

- Recognize the structured-reader suffixes `read_resource`, `get_file_contents`, and `read_file_content`.
- Recognize `uri` and `absolute_path` fields while retaining whole-file and exact-`SKILL.md` requirements.
- Support one exact wrapper layer for `sh`, `bash`, `zsh`, `fish`, PowerShell, and `pwsh` around the corresponding complete-file readers.
- Continue rejecting partial reads, range controls, pipelines, redirections, substitutions, compound commands, nested wrappers, Windows `type`, and PowerShell aliases.
- Add unit and lifecycle integration coverage for the new positive and negative cases.
- Document the complete registry and the request-based, best-effort detection contract in the event reference and Codex guide.
- Preserve the existing `skill.load` data and metadata fields. This change has no breaking API changes.

Validation completed:

- `cargo fmt --all`
- `cargo test -p nemo-relay skill_load`
- `just test-rust`
- `cargo clippy --workspace --all-targets -- -D warnings`
- `just test-python`
- `just test-go`
- `just test-node`
- `just docs`
- `uv run pre-commit run --all-files`

The authenticated SQA characterization fixture was not updated or run because this workspace does not have access to the external SQA repository. That follow-up remains required before RELAY-540 is complete.

#### Where should the reviewer start?

Start with `crates/core/src/api/skill_load.rs`, especially the reviewed registries and the single-layer wrapper parsing. Then review `crates/core/tests/unit/skill_load_tests.rs` for the supported and deliberately unsupported cases.

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

- Closes: RELAY-540



## Summary by CodeRabbit

* **New Features**
  * Expanded automatic `skill.load` detection for additional shell tools/wrappers (zsh/fish, `pwsh`) and more StructuredRead/MCP resource/file read shapes.
* **Bug Fixes**
  * Improved shell-read detection and completion parsing, including stricter PowerShell option/flag handling and tightened `SKILL.md` path validation.
* **Documentation**
  * Updated “Automatic Skill-Load Marks” and Codex “Captured Events” to clarify best-effort criteria, timing, and supported wrapper/request forms.
* **Tests**
  * Added an integration test for minimal tool-parented `skill.load` emission; expanded unit detection acceptance/rejection coverage.

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

Approvers:
  - Bryan Bednarski (https://github.com/bbednarski9)

URL: NVIDIA#517
#### Overview

Reorganizes the getting-started docs so the runtime primer lives with the About NeMo Relay conceptual content, while Getting Started gets a short About entry point and AI-coding-assistant guidance.

This replaces draft PR NVIDIA#443 with a clean branch and a single signed-off docs commit.

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

#### Details

- Moves Agent Runtime Primer from Getting Started to About NeMo Relay and adds a redirect from the old URL.
- Adds a new Getting Started About page with starting-point guidance ordered from try-now paths to advanced development workflows.
- Adds a "Using an AI coding assistant?" card to Getting Started About and Quick Start with the future no-clone `npx skills add nvidia/skills` path for installing the full Relay user-skill set.
- Updates related docs and README links to the new primer location.

#### Where should the reviewer start?

Start with `docs/getting-started/about.mdx`, then review `docs/about-nemo-relay/agent-runtime-primer.mdx` and `docs/getting-started/quick-start/index.mdx` for the IA changes.

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

- Relates to NVIDIA agent skills publication follow-up.
- Supersedes NVIDIA#443.

#### Testing

- `just docs` passed. Fern reported one warning: missing redirects check skipped because this local environment is not authenticated with `fern login` / `FERN_TOKEN`.



## Summary by CodeRabbit

* **Documentation**
  * Added/expanded NeMo Relay “About” getting-started content, including guidance on selecting the smallest matching path, prerequisites, installation, configuration, and quick-start steps.
  * Updated Quick Start with a new “Using an AI coding assistant?” card, including skill-installation commands and catalog discovery.
  * Refreshed documentation navigation ordering and updated Agent Runtime Primer links across relevant pages.
  * Improved “starting point” routing guidance and adjusted internal doc links.
* **Chores**
  * Added a redirect to keep existing Agent Runtime Primer links working.

Authors:
  - Allan (https://github.com/exactlyallan)

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

URL: NVIDIA#479
#### Overview

Make Node tool and LLM callback failures reject their returned promises instead of terminating the Node process.

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

#### Details

- Wrap synchronous tool and LLM execution callbacks on the JavaScript thread so thrown exceptions cross N-API as error envelopes.
- Normalize top-level undefined to null and copy callback results through recursive JSON validation before NAPI-RS conversion.
- Reject BigInt, sparse arrays, circular values, non-finite numbers, and other unsupported JSON values without aborting Node.
- Apply the same validation to promise-aware tool and LLM callbacks while preserving original rejection messages.
- Add regressions for sync throws, sync and async BigInt results, stateful getters, custom array iterators, process survival, and supported undefined behavior.
- Keep the public Node callback declarations and sync-only execution semantics unchanged.
- Breaking changes: none.

Validation:

- Focused Node callback, tool, and LLM tests: 94 passed.
- Full Node test suite: 283 passed.
- `just build-node`
- `just test-node`
- `cargo fmt --all`
- `just test-rust`
- `cargo clippy --workspace --all-targets -- -D warnings`
- `uv run pre-commit run --all-files`
- Targeted pre-commit checks for the final staged files.

#### Where should the reviewer start?

Start with `safe_execution_callback` in `crates/node/src/callable.rs`, then compare the promise-aware validation in `crates/node/src/promise_call.rs` and the process-survival regressions in `crates/node/tests/tools_tests.mjs`.

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

- Closes RELAY-544

## Summary by CodeRabbit

* **New Features**
  * Tool and LLM execution now accept regular JavaScript callback functions directly, with safer cross-boundary execution.

* **Bug Fixes**
  * More consistent rejection for invalid or unsupported callback results (e.g., circular references, non-finite numbers, BigInt/sparse arrays), avoiding runtime instability.
  * Completion argument validation is stricter: invalid inputs now fail explicitly instead of defaulting.

* **Tests**
  * Added/expanded tool and LLM execution cases covering thrown callbacks, invalid JSON-like outputs, getter/iterator edge cases, and continued operation after failures.

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

Prevent cyclic Python tool callback results from overflowing native JSON conversion and terminating the process. Cyclic results now produce a catchable exception while shared non-cyclic values remain supported.

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

#### Details

- Validate Python dictionaries, lists, and tuples for active-path cycles before converting callback results to JSON.
- Preserve ordinary shared references by removing container identities after each recursive branch completes.
- Add Python regressions for cycle rejection, process recovery, and shared non-cyclic values.
- Add Node regression coverage confirming synchronous and asynchronous circular results reject without terminating the process.
- Breaking changes: none.

Validation:

- Focused Python cyclic/shared-reference tests: 2 passed.
- Focused Node circular-result test: 1 passed.
- Python and Node native binding builds passed.
- Repository-wide pre-commit validation passed.

#### Where should the reviewer start?

Start with `validate_acyclic` in `crates/python/src/convert.rs`, then review the Python behavioral tests in `python/tests/test_tools.py`.

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

- Closes RELAY-543



## Summary by CodeRabbit

- **Bug Fixes**
  - Tool executions now detect and reject circular result data with a clear “circular reference detected” error, instead of risking a process crash.
  - After a circular-result rejection, the tool system remains usable for subsequent executions.
  - Shared references in non-cyclic result graphs are preserved correctly.

- **Tests**
  - Added regression coverage for rejecting cyclic tool results across sync/async and multiple data shapes, plus verification of continued operation.
  - Updated several codec/sanitizer tests to use synchronous callbacks consistently.

Authors:
  - Eric Evans II (https://github.com/ericevans-nv)

Approvers:
  - Bryan Bednarski (https://github.com/bbednarski9)

URL: NVIDIA#524
Signed-off-by: Will Killian <wkillian@nvidia.com>
@willkill07
willkill07 requested review from a team and lvojtku as code owners July 22, 2026 03:17
@github-actions github-actions Bot added size:XXL PR is very large Maintenance CI or Build or general repository maintenance lang:go PR changes/introduces Go code lang:js PR changes/introduces Javascript/Typescript code lang:python PR changes/introduces Python code lang:rust PR changes/introduces Rust code labels Jul 22, 2026

Copy link
Copy Markdown
Member Author

/merge nosquash

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

This PR expands Relay’s typed LLM request model and lossless provider codecs, wires request interception into gateway generation routes, adds trajectory-context redaction and callback safety, enforces versioned plugin contracts, broadens skill-load detection, and updates bindings, tests, documentation, and ownership rules.

Changes

Relay request and codec pipeline

Layer / File(s) Summary
Typed request model and adaptive processing
crates/types/..., crates/adaptive/...
Adds instructions, API-specific fields, developer/native/tool message variants, provider-native content, portable tool definitions, and expanded adaptive fingerprints and IR handling.
Lossless provider codecs
crates/core/src/codec/*, crates/core/tests/unit/codec/*
Reworks Anthropic, OpenAI Chat, and OpenAI Responses decoding and encoding around strict validation and baseline-aware JSON patching that preserves unchanged provider fields.
Gateway and plugin contracts
crates/cli/..., crates/core/src/plugin/..., crates/worker/..., python/plugin/...
Enables request codecs on generation routes, rejects stream-mode changes, validates annotation schemas, and rejects intercept plugins whose compatibility ranges admit Relay 0.5.
Trajectory redaction and callback safety
crates/pii-redaction/..., crates/node/..., crates/python/...
Adds structure-preserving trajectory sanitization, JSON-cycle detection, safe Node callback wrappers, Python request fields, and related tests.
Skill-load and observability behavior
crates/core/src/api/skill_load.rs, crates/core/src/observability/...
Expands structured and shell reader parsing and documents subscriber/exporter delivery barriers and re-entrant behavior.
Documentation and repository support
docs/..., README.md, fern/docs.yml, .github/CODEOWNERS, examples/..., skills/...
Updates navigation, codec and migration contracts, redaction guidance, package versions, redirects, examples, skills, and NeMo Relay ownership teams.

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

Possibly related PRs


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 error, 1 warning)

Check name Status Explanation Resolution
Title check ❌ Error The title is relevant, but it does not use the required Conventional Commits format or type prefix. Change it to a conventional-commit title like chore: forward-merge release/0.6 into main.
Docstring Coverage ⚠️ Warning Docstring coverage is 66.79% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The description matches the template with Overview, Details, reviewer start point, and related issue information filled in.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@willkill07 willkill07 changed the title chore: forward-merge release/0.6 into main Forward-merge release/0.6 into main Jul 22, 2026
@github-actions github-actions Bot removed the Maintenance CI or Build or general repository maintenance label Jul 22, 2026
@github-actions

Copy link
Copy Markdown

@willkill07 willkill07 assigned willkill07 and unassigned willkill07 Jul 22, 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.

Actionable comments posted: 10

🤖 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/adaptive/tests/integration/runtime_integration_tests.rs`:
- Around line 527-533: Update the learning_key construction to derive the system
component dynamically using the same short_hash and sha256_hex flow as the seed
component, hashing the exact system prompt text rather than retaining the
hardcoded sha256 prefix. Preserve the existing key format and agent/model/tools
components.

In `@crates/cli/src/gateway/mod.rs`:
- Around line 162-182: Update GatewayRequestCodec::encode to avoid calling
self.inner.decode(original) solely to obtain stream mode. Read the original
stream boolean directly from the raw LlmRequest JSON, defaulting it consistently
with the current unwrap_or(false) behavior, then compare it with
annotated.stream and preserve the existing validation and encoding flow.

In `@crates/core/src/codec/openai_responses.rs`:
- Around line 1288-1292: Update the patching logic around max_tokens and
max_output_tokens so the wire field max_output_tokens is written from one
canonical source only. Prevent the later top-level or parameter-level update
from overwriting a change made by the other mirror, either by selecting a single
source or synchronizing both values before calling set_or_remove_json.

In `@crates/core/src/plugin/dynamic.rs`:
- Around line 96-109: Update validate_annotated_request_consumer_compatibility
to reject requirements matching either Version::new(0, 5, 0) or the existing
Version::new(0, 5, u64::MAX), while preserving the current InvalidConfig error.
Add a regression test in plugin_dynamic_tests covering an exact or narrow 0.5.x
requirement, and retain coverage for the accepted 0.6+ range.

In `@crates/node/src/callback_factory.rs`:
- Around line 8-9: Replace the globalThis-based callback-factory cache
identified by CALLBACK_FACTORIES_PROPERTY and its related logic around the
callback factory access path with napi Env instance data. Use
Env::set_instance_data and Env::get_instance_data with the exact Ref and
ownership signatures supported by the pinned napi version, preserving per-Env
factory reuse while removing all reads and writes of the global property.

In `@crates/python/src/convert.rs`:
- Around line 67-77: Update the dataclass branch in validate_acyclic to access
each declared field through the value’s getattr/getattr_opt using the field
name, instead of retrieving and reading __dict__. Preserve recursive validation
for present field values and ensure both slotted and non-slotted dataclasses are
handled.

In `@crates/types/src/codec/response.rs`:
- Around line 354-362: Update the response_text() match over
MessageContent::Parts to handle ContentPart::Refusal alongside
ContentPart::Text, returning the refusal text as the response text. Preserve the
existing ProviderNative and other-part handling.

In `@docs/about-nemo-relay/release-notes/known-issues.mdx`:
- Around line 120-123: Update the email-redaction guidance in the known-issues
section to make execution ordering explicit: instruct readers to assign the
email-redaction profile an appropriate priority so it runs after the earlier
redaction profiles, using array order only when priorities tie. Replace the
current “later in the profile list” wording without changing the surrounding
custom-mark behavior.

In `@docs/getting-started/about.mdx`:
- Around line 22-25: Update the NVIDIA agent skills installation guidance in
docs/getting-started/about.mdx lines 22-25 and
docs/getting-started/quick-start/index.mdx lines 28-31 to use direct
present-tense wording, removing the outdated “After the NeMo Relay skills are
published” condition while preserving the instruction to install the full Relay
skill set without cloning the catalog.

In `@README.md`:
- Around line 24-25: Run the docs link checker after updating the README
Markdown links, using the repository’s just docs-linkcheck command, and include
any required fixes or verification from that check in this change.
🪄 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: 3f9e8ca2-9628-4c6c-84a9-c6e273897358

📥 Commits

Reviewing files that changed from the base of the PR and between ea898a7 and 89786bd.

📒 Files selected for processing (128)
  • .github/CODEOWNERS
  • README.md
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/tests/integration/acg_module_surface_tests.rs
  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
  • crates/adaptive/tests/unit/acg_component_tests.rs
  • crates/adaptive/tests/unit/acg_learner_tests.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/adaptive_hints_intercept_tests.rs
  • crates/adaptive/tests/unit/cache_diagnostics_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/plugins_tests.rs
  • crates/cli/tests/coverage/shared/server_tests.rs
  • crates/core/src/api/llm.rs
  • crates/core/src/api/skill_load.rs
  • crates/core/src/api/subscriber.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/atof.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/api_surface_tests.rs
  • crates/core/tests/integration/codec_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/tests/integration/pipeline_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/codec/request_tests.rs
  • crates/core/tests/unit/codec/response_tests.rs
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/tests/unit/observability/atof_tests.rs
  • crates/core/tests/unit/observability/openinference_tests.rs
  • crates/core/tests/unit/plugin_dynamic_tests.rs
  • crates/core/tests/unit/shared_tests.rs
  • crates/core/tests/unit/skill_load_tests.rs
  • crates/core/tests/unit/types_tests.rs
  • crates/ffi/nemo_relay.h
  • crates/ffi/src/api/llm_registry.rs
  • crates/ffi/src/api/observability.rs
  • crates/ffi/tests/integration/callable_extra_tests.rs
  • crates/ffi/tests/unit/callable_tests.rs
  • crates/ffi/tests/unit/types_tests.rs
  • crates/node/README.md
  • crates/node/src/api/mod.rs
  • crates/node/src/callable.rs
  • crates/node/src/callback_factory.rs
  • crates/node/src/lib.rs
  • crates/node/src/promise_call.rs
  • crates/node/tests/codec_tests.mjs
  • crates/node/tests/event_sanitizers_tests.mjs
  • crates/node/tests/llm_tests.mjs
  • crates/node/tests/tools_tests.mjs
  • crates/node/tests/typed_tests.mjs
  • crates/pii-redaction/README.md
  • crates/pii-redaction/src/builtin.rs
  • crates/pii-redaction/src/component.rs
  • crates/pii-redaction/src/lib.rs
  • crates/pii-redaction/src/overlay.rs
  • crates/pii-redaction/src/trajectory.rs
  • crates/pii-redaction/tests/coverage/overlay_tests.rs
  • crates/pii-redaction/tests/unit/component_tests.rs
  • crates/python/src/convert.rs
  • crates/python/src/py_api/mod.rs
  • crates/python/src/py_types/codecs.rs
  • crates/python/src/py_types/mod.rs
  • crates/python/src/py_types/observability.rs
  • crates/python/tests/coverage/py_types_coverage_tests.rs
  • crates/types/src/api/llm.rs
  • crates/types/src/codec/request.rs
  • crates/types/src/codec/response.rs
  • crates/types/tests/serialization_tests.rs
  • crates/worker/src/lib.rs
  • crates/worker/tests/worker_sdk_tests.rs
  • docs/about-nemo-relay/agent-runtime-primer.mdx
  • docs/about-nemo-relay/architecture.mdx
  • docs/about-nemo-relay/concepts/codecs.mdx
  • docs/about-nemo-relay/concepts/events.mdx
  • docs/about-nemo-relay/concepts/index.mdx
  • docs/about-nemo-relay/concepts/subscribers.mdx
  • docs/about-nemo-relay/ecosystem.mdx
  • docs/about-nemo-relay/overview.mdx
  • docs/about-nemo-relay/release-notes/highlights.mdx
  • docs/about-nemo-relay/release-notes/index.mdx
  • 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/configure-plugins/observability/about.mdx
  • docs/configure-plugins/observability/atif.mdx
  • docs/configure-plugins/observability/atof.mdx
  • docs/configure-plugins/observability/configuration.mdx
  • docs/configure-plugins/observability/openinference.mdx
  • docs/configure-plugins/observability/opentelemetry.mdx
  • docs/contribute/runtime-contract-docs.mdx
  • docs/getting-started/about.mdx
  • docs/getting-started/installation.mdx
  • docs/getting-started/quick-start/index.mdx
  • docs/getting-started/quick-start/nodejs.mdx
  • docs/integrate-into-frameworks/provider-codecs.mdx
  • docs/nemo-relay-cli/codex.mdx
  • docs/reference/api/index.mdx
  • docs/reference/llm-request-intercept-outcomes.mdx
  • docs/resources/troubleshooting/trace-incident-runbook.mdx
  • examples/rust-native-plugin/relay-plugin.toml
  • fern/docs.yml
  • go/nemo_relay/nemo_relay.go
  • go/nemo_relay/subscribers/subscribers.go
  • python/nemo_relay/_native.pyi
  • python/nemo_relay/subscribers.py
  • python/plugin/src/nemo_relay_plugin/_api.py
  • python/tests/plugin/test_worker_sdk.py
  • python/tests/test_builtin_codecs.py
  • python/tests/test_codecs.py
  • python/tests/test_tools.py
  • skills/nemo-relay-instrument-typed-wrappers/SKILL.md

Comment thread crates/adaptive/tests/integration/runtime_integration_tests.rs
Comment thread crates/cli/src/gateway/mod.rs
Comment thread crates/core/src/codec/openai_responses.rs
Comment thread crates/core/src/plugin/dynamic.rs
Comment thread crates/node/src/callback_factory.rs
Comment thread crates/python/src/convert.rs
Comment thread crates/types/src/codec/response.rs
Comment thread docs/about-nemo-relay/release-notes/known-issues.mdx
Comment thread docs/getting-started/about.mdx
Comment thread README.md
@rapids-bot

rapids-bot Bot commented Jul 22, 2026

Copy link
Copy Markdown

Could not determine original ForwardMerger PR from branch name. The branch name should follow the pattern <target_branch>-merge-<source_branch> (e.g., branch-25.06-merge-branch-25.04 or main-merge-release/25.06). Please contact @rapidsdevops on Slack for assistance.

@willkill07

Copy link
Copy Markdown
Member Author

/merge nosquash

@rapids-bot

rapids-bot Bot commented Jul 22, 2026

Copy link
Copy Markdown

Could not determine original ForwardMerger PR from branch name. The branch name should follow the pattern <target_branch>-merge-<source_branch> (e.g., branch-25.06-merge-branch-25.04 or main-merge-release/25.06). Please contact @rapidsdevops on Slack for assistance.

@willkill07
willkill07 merged commit f68ae38 into NVIDIA:main Jul 22, 2026
61 checks passed
@willkill07
willkill07 deleted the main-merge-release/0.6 branch July 22, 2026 03:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lang:go PR changes/introduces Go code lang:js PR changes/introduces Javascript/Typescript code lang:python PR changes/introduces Python code lang:rust PR changes/introduces Rust code size:XXL PR is very large

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants