Skip to content

refactor: hoist provider schema detection and normalization#291

Merged
rapids-bot[bot] merged 10 commits into
NVIDIA:mainfrom
zhongxuanwang-nv:refactor/hoist-provider-schema-handling
Jun 24, 2026
Merged

refactor: hoist provider schema detection and normalization#291
rapids-bot[bot] merged 10 commits into
NVIDIA:mainfrom
zhongxuanwang-nv:refactor/hoist-provider-schema-handling

Conversation

@zhongxuanwang-nv

@zhongxuanwang-nv zhongxuanwang-nv commented Jun 23, 2026

Copy link
Copy Markdown
Member

Overview

Consolidate provider schema handling for OpenAI Chat Completions, OpenAI Responses, and Anthropic Messages behind a single codec-layer path, so exporters and plugins consume normalized provider data instead of re-implementing provider parsing from raw JSON. This adds new public Rust core API (codec::resolve, Event::normalized_llm_request / normalized_llm_response); the change is additive and Rust-only, with no breaking changes.

Local validation: cargo test -p nemo-relay (638 passing), cargo clippy -p nemo-relay --all-features --all-targets clean, single-feature (otel / openinference) builds warning-free, and adaptive request-surface tests pass. The full cross-language matrix is left to CI.

  • 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

  • codec::resolve (new) — the canonical detect-then-decode entry point: ProviderSurface + detect_request_surface (priority order hoisted from adaptive) / detect_response_surface (strict; ambiguous or empty payloads classify to None) + fail-open normalize_request / normalize_response.
  • Event::normalized_llm_request / normalized_llm_response — annotation-first Cow helpers over the detector; annotated_*() left unchanged. Rustdoc documents the {headers, content} LlmRequest precondition for the request fallback.
  • OpenAIResponsesCodec — response-only extension to decode top-level output_text and item-level output[].type == "output_text" (structured output keeps precedence).
  • observability::manual (new) — the OpenTelemetry/OpenInference non-provider usage/cost fallback de-duplicated into one module, with the USD-only vs emit-any-currency policy parameterized.
  • OpenInference — un-annotated provider payloads are decoded through the normalized helpers to emit structured request/response messages; usage merges codec-normalized fields (e.g. Anthropic's computed total) with the manual scraper per field so neither source's coverage is lost.
  • ATIF — reads normalized message text from annotations when present (multimodal falls back to the raw extractor); text-less responses (tool-call-only, or reasoning/thinking-only) render an empty message instead of a raw-JSON dump, with tool calls and metrics still recovered from the raw path.
  • adaptiveresolve_request_surface_from_request delegates to codec::resolve::detect_request_surface.
  • Docs and docstrings: documented the annotation → normalized-helper → raw fallback rule and per-exporter behavior in provider-response-codecs.mdx; fixed the misleading "global codec registry" / "request codecs' priority order" docstrings and noted the detection limitation for system-less Anthropic requests.

Where should the reviewer start?

crates/core/src/codec/resolve.rs (the single detect-then-decode path), then crates/core/src/observability/atif.rs and openinference.rs — the annotation-first / raw-fallback consumers are the trickiest equivalence surface, where the raw parser is intentionally retained because the normalized form would be lossy (tool-call extras, multimodal content, metrics).

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

  • Relates to RELAY-325

Summary by CodeRabbit

Release Notes

  • New Features

    • Automatic detection and normalization of LLM provider requests and responses when provider-specific annotations are unavailable, with intelligent fallback handling.
    • Enhanced token usage and cost extraction from various LLM output formats, supporting multiple field aliases and currency handling.
    • Improved text extraction from OpenAI Responses payloads with better support for output_text fields.
  • Improvements

    • Better preference ordering for request/response data: prioritizes annotated values, then normalized codec results, then raw payloads.
    • More robust message construction with multiple fallback strategies for different payload structures.

… Chat Completions

Consolidate provider schema handling for OpenAI Chat Completions, OpenAI
Responses, and Anthropic Messages behind a single codec-layer path so exporters
and plugins consume normalized data instead of re-parsing raw provider JSON.

- Add codec::resolve: ProviderSurface detection + fail-open
  normalize_request/normalize_response as the canonical detect-then-decode entry.
- Add Event::normalized_llm_request/response annotation-first helpers and consume
  them in the OpenInference exporter (annotation -> OpenClaw replay -> codec
  detection), so un-annotated provider events emit structured attributes.
- Extend OpenAIResponsesCodec to decode top-level and item-level output_text.
- Dedupe the otel/openinference non-provider usage/cost fallback into
  observability::manual (currency policy parameterized).
- ATIF reads normalized message text from annotations (raw fallback for
  multimodal); tool calls and metrics stay on the raw path to preserve provider
  extras.
- adaptive delegates request-surface detection to codec::resolve.
- Fix the misleading "global codec registry" docstring and document the
  annotation-vs-raw-fallback rule.

Relates to RELAY-325.

Signed-off-by: Zhongxuan Wang <[email protected]>
@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

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

Use the following commands to manage reviews:

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

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds a codec::resolve module with heuristic ProviderSurface detection and fail-open normalization functions. Extracts shared manual LLM output parsing (usage, cost, model name) into observability::manual. Wires Event::normalized_llm_request / normalized_llm_response methods using annotation-first fallback to resolve. Updates ATIF, OpenInference, OTel, and ACG consumers accordingly, and extends OpenAIResponsesCodec to handle output_text items.

Changes

Codec resolve pipeline and observability integration

Layer / File(s) Summary
ProviderSurface detection and codec resolve module
crates/core/src/codec/resolve.rs, crates/core/src/codec/mod.rs, crates/core/src/codec/traits.rs, crates/core/src/codec/openai_responses.rs, crates/core/tests/unit/codec/resolve_tests.rs, crates/core/tests/unit/codec/openai_responses_tests.rs
Defines ProviderSurface enum; implements detect_request_surface and detect_response_surface with priority-ordered key heuristics; implements normalize_request / normalize_response as fail-open dispatchers; exports from codec::mod; adds output_text item handling and top-level output_text fallback to OpenAIResponsesCodec; tests cover detection priority, ambiguity, normalization, and output_text precedence.
Event::normalized_llm_request / normalized_llm_response
crates/core/src/api/event.rs, crates/core/tests/unit/types_tests.rs
Adds two pub methods on Event that prefer codec annotations (Cow::Borrowed) and fall back to resolve normalization of raw start/end payloads (Cow::Owned), returning None on failure; tests assert annotation preference, raw-codec fallback, and None for non-provider payloads.
Shared manual LLM output extraction
crates/core/src/observability/manual.rs, crates/core/src/observability/mod.rs, crates/core/tests/unit/observability/manual_tests.rs
Feature-gated observability::manual module consolidates usage_from_manual_llm_output, cost_from_manual_llm_output (with usd_only flag), model_name_from_manual_llm_output, and normalize_total_tokens with multi-alias key probing; unit tests validate cost policy, alias handling, normalization, and model-name extraction.
OTel and OpenInference exporter integration
crates/core/src/observability/otel.rs, crates/core/src/observability/openinference.rs, crates/core/tests/unit/observability/openinference_tests.rs
Both exporters delegate manual cost/usage/model-name parsing to manual; otel.rs removes its local helpers; openinference.rs adds merge_usage for field-by-field codec+manual merge, rewires push_llm_request_attributes and push_llm_response_attributes to route replay payloads first, and derives codec usage from event.normalized_llm_response(); tests cover unannotated codec decoding, Anthropic total inference, empty-usage fallback, and partial-usage merge.
ATIF annotated request/response integration
crates/core/src/observability/atif.rs, crates/core/tests/unit/atif_tests.rs
Adds annotation adapters mapping AnnotatedLlmRequest/AnnotatedLlmResponse to ATIF JSON (multimodal → None to trigger fallback; absent assistant text → explicit empty message); LLM-start/end step message derivation prefers annotated values; TestEventBuilder gains optional annotated fields; tests cover annotation preference with preserved tool calls, empty-message variants, annotated-request priority, and multimodal fallback.
ACG request-surface resolution
crates/adaptive/src/acg/request_surfaces/mod.rs
Replaces manual key inspection in resolve_request_surface_from_request with detect_request_surface; adds RequestSurface::from_provider_surface mapping ProviderSurface variants to internal enum variants.
Docs: when no annotation is present
docs/integrate-into-frameworks/provider-response-codecs.mdx
Adds guidance section covering annotation attachment conditions, normalized helper usage, exporter/subscriber precedence, and when to fall back to manual raw-payload parsing.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed Title follows Conventional Commits format with correct type (refactor), lowercase scope, and imperative summary within 72 character limit.
Description check ✅ Passed Description includes all required template sections: Overview with checkboxes, Details explaining changes, Where to start guidance, and Related Issues linking to RELAY-325.
Docstring Coverage ✅ Passed Docstring coverage is 80.82% which is sufficient. The required threshold is 80.00%.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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:XL PR is extra large Improvement improvement to existing functionality lang:rust PR changes/introduces Rust code labels Jun 23, 2026
@zhongxuanwang-nv zhongxuanwang-nv self-assigned this Jun 23, 2026
@zhongxuanwang-nv zhongxuanwang-nv added the DO NOT MERGE PR should not be merged; see PR for details label Jun 23, 2026
@zhongxuanwang-nv zhongxuanwang-nv added this to the 0.5 milestone Jun 23, 2026
@github-actions

Copy link
Copy Markdown

@zhongxuanwang-nv

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@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/adaptive/src/acg/request_surfaces/mod.rs`:
- Around line 83-89: The detect_request_surface function classifies
messages-only requests (containing only {"messages": ...}) as OpenAiChat, which
causes failures when the provider is "anthropic" at the supports_provider check
around lines 97-103. Add provider-aware tie-breaking logic before the
supports_provider validation to handle provider-specific variations where
certain providers like Anthropic can accept messages without a top-level system
field, ensuring that messages-only requests are properly disambiguated based on
the actual provider capability rather than just the detected surface
classification.

In `@crates/core/tests/unit/types_tests.rs`:
- Around line 673-676: The test for normalized_llm_request() currently only
asserts that the messages list is not empty, but does not verify the actual
decoded content or which source won in the fallback/preference logic. Replace
the assertion checking is_empty() with stronger assertions that validate the
specific content of the decoded request from normalized.messages, ensuring the
test proves which source (annotation vs raw payload) was actually used rather
than just confirming that some content was returned.
🪄 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: f2c4301e-8dc2-446c-b1bd-201859045b54

📥 Commits

Reviewing files that changed from the base of the PR and between 67606b5 and e64c06b.

📒 Files selected for processing (18)
  • crates/adaptive/src/acg/request_surfaces/mod.rs
  • crates/core/src/api/event.rs
  • crates/core/src/codec/mod.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/core/src/codec/resolve.rs
  • crates/core/src/codec/traits.rs
  • crates/core/src/observability/atif.rs
  • crates/core/src/observability/manual.rs
  • crates/core/src/observability/mod.rs
  • crates/core/src/observability/openinference.rs
  • crates/core/src/observability/otel.rs
  • crates/core/tests/unit/atif_tests.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/tests/unit/codec/resolve_tests.rs
  • crates/core/tests/unit/observability/manual_tests.rs
  • crates/core/tests/unit/observability/openinference_tests.rs
  • crates/core/tests/unit/types_tests.rs
  • docs/integrate-into-frameworks/provider-response-codecs.mdx
📜 Review details
⏰ Context from checks skipped due to timeout. (25)
  • GitHub Check: WebAssembly / Test (windows-arm64)
  • GitHub Check: Rust / Test (linux-arm64)
  • GitHub Check: Rust / Test (linux-amd64)
  • GitHub Check: Rust / Test (windows-arm64)
  • GitHub Check: WebAssembly / Test (windows-amd64)
  • GitHub Check: Go / Test (windows-arm64)
  • GitHub Check: Rust / Test (macos-arm64)
  • GitHub Check: WebAssembly / Test (linux-arm64)
  • GitHub Check: WebAssembly / Test (macos-arm64)
  • GitHub Check: Rust / Test (windows-amd64)
  • GitHub Check: WebAssembly / Test (linux-amd64)
  • GitHub Check: Go / Test (linux-arm64)
  • GitHub Check: Node.js / Test (windows-amd64)
  • GitHub Check: Python / Test (linux-arm64)
  • GitHub Check: Go / Test (linux-amd64)
  • GitHub Check: Go / Test (macos-arm64)
  • GitHub Check: Python / Test (linux-amd64)
  • GitHub Check: Go / Test (windows-amd64)
  • GitHub Check: Python / Test (windows-amd64)
  • GitHub Check: Node.js / Test (macos-arm64)
  • GitHub Check: Node.js / Test (windows-arm64)
  • GitHub Check: Python / Test (macos-arm64)
  • GitHub Check: Python / Test (windows-arm64)
  • GitHub Check: Node.js / Test (linux-amd64)
  • GitHub Check: Node.js / Test (linux-arm64)
🧰 Additional context used
📓 Path-based instructions (29)
**/*.rs

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

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

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

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

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

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

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

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

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

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

Files:

  • crates/core/tests/unit/codec/resolve_tests.rs
  • crates/core/src/codec/mod.rs
  • crates/core/src/codec/traits.rs
  • crates/adaptive/src/acg/request_surfaces/mod.rs
  • crates/core/src/observability/mod.rs
  • crates/core/src/observability/manual.rs
  • crates/core/src/api/event.rs
  • crates/core/tests/unit/types_tests.rs
  • crates/core/src/observability/atif.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/core/src/codec/resolve.rs
  • crates/core/tests/unit/observability/manual_tests.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/tests/unit/observability/openinference_tests.rs
  • crates/core/tests/unit/atif_tests.rs
  • crates/core/src/observability/otel.rs
  • crates/core/src/observability/openinference.rs
{crates/adaptive/**/*.rs,**/*test*.{rs,py,go,ts,js},**/*adaptive*test*.{rs,py,go,ts,js},docs/plugins/adaptive/**}

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

Maintain documented and tested validation and report behavior for adaptive surfaces

Files:

  • crates/core/tests/unit/codec/resolve_tests.rs
  • crates/adaptive/src/acg/request_surfaces/mod.rs
  • crates/core/tests/unit/types_tests.rs
  • crates/core/tests/unit/observability/manual_tests.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/tests/unit/observability/openinference_tests.rs
  • crates/core/tests/unit/atif_tests.rs
**/{Cargo.toml,**/*.rs}

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

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

Files:

  • crates/core/tests/unit/codec/resolve_tests.rs
  • crates/core/src/codec/mod.rs
  • crates/core/src/codec/traits.rs
  • crates/adaptive/src/acg/request_surfaces/mod.rs
  • crates/core/src/observability/mod.rs
  • crates/core/src/observability/manual.rs
  • crates/core/src/api/event.rs
  • crates/core/tests/unit/types_tests.rs
  • crates/core/src/observability/atif.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/core/src/codec/resolve.rs
  • crates/core/tests/unit/observability/manual_tests.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/tests/unit/observability/openinference_tests.rs
  • crates/core/tests/unit/atif_tests.rs
  • crates/core/src/observability/otel.rs
  • crates/core/src/observability/openinference.rs
**/*.{h,hpp,c,cpp,rs}

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

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

Files:

  • crates/core/tests/unit/codec/resolve_tests.rs
  • crates/core/src/codec/mod.rs
  • crates/core/src/codec/traits.rs
  • crates/adaptive/src/acg/request_surfaces/mod.rs
  • crates/core/src/observability/mod.rs
  • crates/core/src/observability/manual.rs
  • crates/core/src/api/event.rs
  • crates/core/tests/unit/types_tests.rs
  • crates/core/src/observability/atif.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/core/src/codec/resolve.rs
  • crates/core/tests/unit/observability/manual_tests.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/tests/unit/observability/openinference_tests.rs
  • crates/core/tests/unit/atif_tests.rs
  • crates/core/src/observability/otel.rs
  • crates/core/src/observability/openinference.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/resolve_tests.rs
  • crates/core/src/codec/mod.rs
  • crates/core/src/codec/traits.rs
  • crates/adaptive/src/acg/request_surfaces/mod.rs
  • crates/core/src/observability/mod.rs
  • crates/core/src/observability/manual.rs
  • crates/core/src/api/event.rs
  • crates/core/tests/unit/types_tests.rs
  • crates/core/src/observability/atif.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/core/src/codec/resolve.rs
  • crates/core/tests/unit/observability/manual_tests.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/tests/unit/observability/openinference_tests.rs
  • crates/core/tests/unit/atif_tests.rs
  • crates/core/src/observability/otel.rs
  • crates/core/src/observability/openinference.rs
**/*.{rs,toml}

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

Update Rust crate names and module prefixes during coordinated rename operations

Files:

  • crates/core/tests/unit/codec/resolve_tests.rs
  • crates/core/src/codec/mod.rs
  • crates/core/src/codec/traits.rs
  • crates/adaptive/src/acg/request_surfaces/mod.rs
  • crates/core/src/observability/mod.rs
  • crates/core/src/observability/manual.rs
  • crates/core/src/api/event.rs
  • crates/core/tests/unit/types_tests.rs
  • crates/core/src/observability/atif.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/core/src/codec/resolve.rs
  • crates/core/tests/unit/observability/manual_tests.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/tests/unit/observability/openinference_tests.rs
  • crates/core/tests/unit/atif_tests.rs
  • crates/core/src/observability/otel.rs
  • crates/core/src/observability/openinference.rs
crates/core/**/*.rs

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

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

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

Files:

  • crates/core/tests/unit/codec/resolve_tests.rs
  • crates/core/src/codec/mod.rs
  • crates/core/src/codec/traits.rs
  • crates/core/src/observability/mod.rs
  • crates/core/src/observability/manual.rs
  • crates/core/src/api/event.rs
  • crates/core/tests/unit/types_tests.rs
  • crates/core/src/observability/atif.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/core/src/codec/resolve.rs
  • crates/core/tests/unit/observability/manual_tests.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/tests/unit/observability/openinference_tests.rs
  • crates/core/tests/unit/atif_tests.rs
  • crates/core/src/observability/otel.rs
  • crates/core/src/observability/openinference.rs
crates/{core,adaptive}/**

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

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

Files:

  • crates/core/tests/unit/codec/resolve_tests.rs
  • crates/core/src/codec/mod.rs
  • crates/core/src/codec/traits.rs
  • crates/adaptive/src/acg/request_surfaces/mod.rs
  • crates/core/src/observability/mod.rs
  • crates/core/src/observability/manual.rs
  • crates/core/src/api/event.rs
  • crates/core/tests/unit/types_tests.rs
  • crates/core/src/observability/atif.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/core/src/codec/resolve.rs
  • crates/core/tests/unit/observability/manual_tests.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/tests/unit/observability/openinference_tests.rs
  • crates/core/tests/unit/atif_tests.rs
  • crates/core/src/observability/otel.rs
  • crates/core/src/observability/openinference.rs
**/*.{rs,py,js,ts,tsx,jsx,go,sh,toml,yaml,yml,md}

📄 CodeRabbit inference engine (AGENTS.md)

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

Files:

  • crates/core/tests/unit/codec/resolve_tests.rs
  • crates/core/src/codec/mod.rs
  • crates/core/src/codec/traits.rs
  • crates/adaptive/src/acg/request_surfaces/mod.rs
  • crates/core/src/observability/mod.rs
  • crates/core/src/observability/manual.rs
  • crates/core/src/api/event.rs
  • crates/core/tests/unit/types_tests.rs
  • crates/core/src/observability/atif.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/core/src/codec/resolve.rs
  • crates/core/tests/unit/observability/manual_tests.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/tests/unit/observability/openinference_tests.rs
  • crates/core/tests/unit/atif_tests.rs
  • crates/core/src/observability/otel.rs
  • crates/core/src/observability/openinference.rs
**/*.{rs,py,go,js,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

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

Files:

  • crates/core/tests/unit/codec/resolve_tests.rs
  • crates/core/src/codec/mod.rs
  • crates/core/src/codec/traits.rs
  • crates/adaptive/src/acg/request_surfaces/mod.rs
  • crates/core/src/observability/mod.rs
  • crates/core/src/observability/manual.rs
  • crates/core/src/api/event.rs
  • crates/core/tests/unit/types_tests.rs
  • crates/core/src/observability/atif.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/core/src/codec/resolve.rs
  • crates/core/tests/unit/observability/manual_tests.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/tests/unit/observability/openinference_tests.rs
  • crates/core/tests/unit/atif_tests.rs
  • crates/core/src/observability/otel.rs
  • crates/core/src/observability/openinference.rs
crates/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

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

Files:

  • crates/core/tests/unit/codec/resolve_tests.rs
  • crates/core/src/codec/mod.rs
  • crates/core/src/codec/traits.rs
  • crates/adaptive/src/acg/request_surfaces/mod.rs
  • crates/core/src/observability/mod.rs
  • crates/core/src/observability/manual.rs
  • crates/core/src/api/event.rs
  • crates/core/tests/unit/types_tests.rs
  • crates/core/src/observability/atif.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/core/src/codec/resolve.rs
  • crates/core/tests/unit/observability/manual_tests.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/tests/unit/observability/openinference_tests.rs
  • crates/core/tests/unit/atif_tests.rs
  • crates/core/src/observability/otel.rs
  • crates/core/src/observability/openinference.rs
**

⚙️ CodeRabbit configuration file

**:

AGENTS.md

This file provides guidance to agents, including Claude Code and OpenAI Codex, when working in this repository.

Project Overview

NeMo Relay is a multi-language agent runtime framework for execution scopes, lifecycle events, middleware, plugins, and observability around tool and LLM calls. The core runtime is Rust. Primary supported bindings are Rust, Python, and Node.js. Go, WebAssembly, and the raw C FFI are experimental and source-first.

The shared runtime model is:

  1. Scope stacks decide where work belongs and which scope-local behavior is visible.
  2. Middleware registries decide what guardrails and intercepts run around managed calls.
  3. Plugins install reusable runtime behavior from configuration.
  4. Events record runtime behavior in ATOF form.
  5. Subscribers and exporters consume events in-process or export them to ATIF, OpenTelemetry, OpenInference, or other backends.

Repository Structure

The repository layout separates the Rust runtime, language bindings, documentation,
integration patches, and agent-facing skills.

crates/
  core/       # Rust core runtime crate, published as nemo-relay
  adaptive/   # Adaptive runtime primitives and plugin components
  python/     # PyO3 native extension for the Python package
  ffi/        # Raw C ABI layer used by downstream bindings such as Go
  node/       # NAPI Node.js binding and JavaScript/TypeScript entry points
  wasm/       # wasm-bindgen WebAssembly binding and JS wrappers
python/
  nemo_relay/  # Python wrapper package: scopes, tools, LLM, middleware, typed helpers, plugins, adaptive helpers
  tests/      # Python tests
go/
  nemo_relay/  # Experimental Go CGo binding and tests
fern/         # Fern documentation site
scripts/      # Stable wrappers and helper scripts; build/test/docs entry points live in justfile
third_party/  # P...

Files:

  • crates/core/tests/unit/codec/resolve_tests.rs
  • crates/core/src/codec/mod.rs
  • crates/core/src/codec/traits.rs
  • crates/adaptive/src/acg/request_surfaces/mod.rs
  • crates/core/src/observability/mod.rs
  • docs/integrate-into-frameworks/provider-response-codecs.mdx
  • crates/core/src/observability/manual.rs
  • crates/core/src/api/event.rs
  • crates/core/tests/unit/types_tests.rs
  • crates/core/src/observability/atif.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/core/src/codec/resolve.rs
  • crates/core/tests/unit/observability/manual_tests.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/tests/unit/observability/openinference_tests.rs
  • crates/core/tests/unit/atif_tests.rs
  • crates/core/src/observability/otel.rs
  • crates/core/src/observability/openinference.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/resolve_tests.rs
  • crates/core/src/codec/mod.rs
  • crates/core/src/codec/traits.rs
  • crates/adaptive/src/acg/request_surfaces/mod.rs
  • crates/core/src/observability/mod.rs
  • crates/core/src/observability/manual.rs
  • crates/core/src/api/event.rs
  • crates/core/tests/unit/types_tests.rs
  • crates/core/src/observability/atif.rs
  • crates/core/src/codec/openai_responses.rs
  • crates/core/src/codec/resolve.rs
  • crates/core/tests/unit/observability/manual_tests.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/tests/unit/observability/openinference_tests.rs
  • crates/core/tests/unit/atif_tests.rs
  • crates/core/src/observability/otel.rs
  • crates/core/src/observability/openinference.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/resolve_tests.rs
  • crates/core/tests/unit/types_tests.rs
  • crates/core/tests/unit/observability/manual_tests.rs
  • crates/core/tests/unit/codec/openai_responses_tests.rs
  • crates/core/tests/unit/observability/openinference_tests.rs
  • crates/core/tests/unit/atif_tests.rs
{crates/adaptive/**,python/nemo_relay/adaptive.py,python/nemo_relay/plugin.py,go/nemo_relay/adaptive/**,go/nemo_relay/!(adaptive)/**,**/node/**,**/wasm/**}

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

Keep adaptive surface in sync across crates/adaptive, shared plugin behavior in core and bindings, Python adaptive/plugin wrappers in python/nemo_relay/adaptive.py and python/nemo_relay/plugin.py, Go adaptive helpers under go/nemo_relay/adaptive plus shared plugin helpers in go/nemo_relay, and Node/WebAssembly adaptive helpers and plugin wrappers

Files:

  • crates/adaptive/src/acg/request_surfaces/mod.rs
{crates/adaptive/**,python/nemo_relay/plugin.py,go/nemo_relay/**,**/node/**,**/wasm/**}

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

{crates/adaptive/**,python/nemo_relay/plugin.py,go/nemo_relay/**,**/node/**,**/wasm/**}: Maintain consistent plugin lifecycle across all language bindings (Python, Go, Node/WebAssembly, and Rust)
Keep plugin context surfaces aligned across all language implementations

Files:

  • crates/adaptive/src/acg/request_surfaces/mod.rs
{docs/**,README.md,CONTRIBUTING.md}

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

{docs/**,README.md,CONTRIBUTING.md}: For docs-only changes, run targeted checks only if commands, package names, or examples changed. Use just docs for docs-site builds and just docs-linkcheck when links changed
Run docs site build with just docs

Files:

  • docs/integrate-into-frameworks/provider-response-codecs.mdx
{docs/**,README.md,CONTRIBUTING.md,**/*.md}

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

Run docs link validation with just docs-linkcheck when links change

Files:

  • docs/integrate-into-frameworks/provider-response-codecs.mdx
{docs/**,README.md}

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

Verify README and docs entry points still match current package names and paths for large or public-facing changes

Files:

  • docs/integrate-into-frameworks/provider-response-codecs.mdx
{docs/**,examples/**,README.md}

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

Verify examples still run with documented commands for large or public-facing changes

Files:

  • docs/integrate-into-frameworks/provider-response-codecs.mdx
{docs/**,README.md,**/Cargo.toml,**/package.json,**/*.md}

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

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

Files:

  • docs/integrate-into-frameworks/provider-response-codecs.mdx
**/*.{md,mdx,py,sh,yaml,yml,toml,json}

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

Keep package names, repo references, and build commands current

Files:

  • docs/integrate-into-frameworks/provider-response-codecs.mdx
**/*.mdx

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

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.

MDX top-of-file SPDX comments must use {/* ... */} delimiters instead of HTML comment delimiters (Must-Fix)

Files:

  • docs/integrate-into-frameworks/provider-response-codecs.mdx
**/*.{html,md,mdx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Include SPDX license header in HTML and Markdown files using HTML comment syntax

Files:

  • docs/integrate-into-frameworks/provider-response-codecs.mdx
docs/**/*.{md,mdx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Update embedded documentation snippets, patch docs, and binding-support notes if examples or supported bindings changed

Files:

  • docs/integrate-into-frameworks/provider-response-codecs.mdx
docs/**

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Run just docs or ./scripts/build-docs.sh html to regenerate ignored Fern API reference pages before validation for documentation site changes

Files:

  • docs/integrate-into-frameworks/provider-response-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/integrate-into-frameworks/provider-response-codecs.mdx
crates/core/src/api/**/*.rs

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

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

Files:

  • crates/core/src/api/event.rs
crates/core/src/observability/{atif,otel,openinference}.rs

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

When changing event fields in ATIF, OpenTelemetry, or OpenInference observability surfaces, keep the core event model in crates/core/src/observability/atif.rs, crates/core/src/observability/otel.rs, and crates/core/src/observability/openinference.rs in sync

Files:

  • crates/core/src/observability/atif.rs
  • crates/core/src/observability/otel.rs
  • crates/core/src/observability/openinference.rs
🔇 Additional comments (19)
crates/core/src/codec/resolve.rs (1)

1-94: LGTM!

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

13-22: LGTM!

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

21-23: LGTM!

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

195-199: LGTM!

Also applies to: 252-259, 472-473

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

1-221: LGTM!

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

314-364: LGTM!

crates/adaptive/src/acg/request_surfaces/mod.rs (1)

19-51: LGTM!

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

16-17: LGTM!

crates/core/src/observability/manual.rs (1)

1-197: LGTM!

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

1-106: LGTM!

crates/core/src/observability/openinference.rs (1)

23-23: LGTM!

Also applies to: 726-745, 756-773, 807-822, 831-838, 1140-1142, 1161-1161

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

957-963: LGTM!

Also applies to: 965-1148, 2268-2268

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

482-489: LGTM!

crates/core/src/api/event.rs (2)

18-18: LGTM!

Also applies to: 27-31


614-638: 📐 Maintainability & Code Quality

Confirm required Rust/core validation before merge.

This shared Event API path affects core observability contracts; please ensure the PR/CI evidence includes the exact Rust checks and full binding matrix, or explicitly documents any draft-only omissions.

As per coding guidelines, “Any Rust change must run just test-rust”, “Run Rust formatting with cargo fmt --all”, “Run cargo clippy --workspace --all-targets -- -D warnings”, and changes to crates/core must run “the full matrix across Rust, Python, Go, Node.js, and WebAssembly”.

Source: Coding guidelines

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

604-677: LGTM!

crates/core/src/observability/otel.rs (1)

23-29: LGTM!

Also applies to: 683-704

crates/core/src/observability/atif.rs (1)

41-42: LGTM!

Also applies to: 1058-1087, 2246-2249, 2290-2293

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

11-26: LGTM!

Also applies to: 70-84, 133-142, 196-235, 275-290, 1717-1927

Comment thread crates/adaptive/src/acg/request_surfaces/mod.rs
Comment thread crates/core/tests/unit/types_tests.rs
@zhongxuanwang-nv zhongxuanwang-nv changed the title refactor: hoist provider schema handling for Responses, Messages, and Chat Completions refactor: hoist provider schema detection and normalization Jun 23, 2026
@zhongxuanwang-nv

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@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: 1

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

Inline comments:
In `@crates/adaptive/src/acg/request_surfaces/mod.rs`:
- Around line 99-109: The comment preceding the provider check for Anthropic
does not accurately describe the detection behavior. The comment states "A
messages-only request" but the actual detection via surface ==
RequestSurface::OpenAIChat is broader and matches any request with messages but
without system/input/instructions, regardless of other keys like response_format
or tools. Replace the comment block before the if provider == "anthropic"
condition with a more accurate description that explains the detection
classifies requests with messages but without system/input/instructions as
OpenAI Chat, which are also valid Anthropic Messages requests, and when the
provider is Anthropic, the surface is preferred accordingly.
🪄 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: 0832fde5-bcf6-4ff6-96b9-77eb1fef1ddf

📥 Commits

Reviewing files that changed from the base of the PR and between e64c06b and 633820a.

📒 Files selected for processing (2)
  • crates/adaptive/src/acg/request_surfaces/mod.rs
  • crates/adaptive/tests/unit/acg/request_surface_tests.rs
📜 Review details
⏰ Context from checks skipped due to timeout. (26)
  • GitHub Check: Rust / Test (macos-arm64)
  • GitHub Check: Rust / Test (windows-arm64)
  • GitHub Check: Rust / Test (linux-arm64)
  • GitHub Check: WebAssembly / Test (linux-arm64)
  • GitHub Check: WebAssembly / Test (linux-amd64)
  • GitHub Check: Rust / Test (windows-amd64)
  • GitHub Check: Rust / Test (linux-amd64)
  • GitHub Check: WebAssembly / Test (macos-arm64)
  • GitHub Check: WebAssembly / Test (windows-amd64)
  • GitHub Check: Node.js / Test (linux-arm64)
  • GitHub Check: Python / Test (windows-arm64)
  • GitHub Check: Node.js / Test (macos-arm64)
  • GitHub Check: WebAssembly / Test (windows-arm64)
  • GitHub Check: Python / Test (linux-arm64)
  • GitHub Check: Node.js / Test (windows-arm64)
  • GitHub Check: Python / Test (linux-amd64)
  • GitHub Check: Node.js / Test (linux-amd64)
  • GitHub Check: Go / Test (windows-arm64)
  • GitHub Check: Node.js / Test (windows-amd64)
  • GitHub Check: Go / Test (linux-amd64)
  • GitHub Check: Python / Test (macos-arm64)
  • GitHub Check: Go / Test (windows-amd64)
  • GitHub Check: Go / Test (linux-arm64)
  • GitHub Check: Python / Test (windows-amd64)
  • GitHub Check: Go / Test (macos-arm64)
  • GitHub Check: Preview docs
🧰 Additional context used
📓 Path-based instructions (15)
**/*.rs

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

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

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

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

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

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

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

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

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

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

Files:

  • crates/adaptive/tests/unit/acg/request_surface_tests.rs
  • crates/adaptive/src/acg/request_surfaces/mod.rs
{crates/adaptive/**,python/nemo_relay/adaptive.py,python/nemo_relay/plugin.py,go/nemo_relay/adaptive/**,go/nemo_relay/!(adaptive)/**,**/node/**,**/wasm/**}

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

Keep adaptive surface in sync across crates/adaptive, shared plugin behavior in core and bindings, Python adaptive/plugin wrappers in python/nemo_relay/adaptive.py and python/nemo_relay/plugin.py, Go adaptive helpers under go/nemo_relay/adaptive plus shared plugin helpers in go/nemo_relay, and Node/WebAssembly adaptive helpers and plugin wrappers

Files:

  • crates/adaptive/tests/unit/acg/request_surface_tests.rs
  • crates/adaptive/src/acg/request_surfaces/mod.rs
{crates/adaptive/**,python/nemo_relay/plugin.py,go/nemo_relay/**,**/node/**,**/wasm/**}

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

{crates/adaptive/**,python/nemo_relay/plugin.py,go/nemo_relay/**,**/node/**,**/wasm/**}: Maintain consistent plugin lifecycle across all language bindings (Python, Go, Node/WebAssembly, and Rust)
Keep plugin context surfaces aligned across all language implementations

Files:

  • crates/adaptive/tests/unit/acg/request_surface_tests.rs
  • crates/adaptive/src/acg/request_surfaces/mod.rs
{crates/adaptive/**/*.rs,**/*test*.{rs,py,go,ts,js},**/*adaptive*test*.{rs,py,go,ts,js},docs/plugins/adaptive/**}

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

Maintain documented and tested validation and report behavior for adaptive surfaces

Files:

  • crates/adaptive/tests/unit/acg/request_surface_tests.rs
  • crates/adaptive/src/acg/request_surfaces/mod.rs
**/{Cargo.toml,**/*.rs}

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

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

Files:

  • crates/adaptive/tests/unit/acg/request_surface_tests.rs
  • crates/adaptive/src/acg/request_surfaces/mod.rs
**/*.{h,hpp,c,cpp,rs}

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

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

Files:

  • crates/adaptive/tests/unit/acg/request_surface_tests.rs
  • crates/adaptive/src/acg/request_surfaces/mod.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/adaptive/tests/unit/acg/request_surface_tests.rs
  • crates/adaptive/src/acg/request_surfaces/mod.rs
**/*.{rs,toml}

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

Update Rust crate names and module prefixes during coordinated rename operations

Files:

  • crates/adaptive/tests/unit/acg/request_surface_tests.rs
  • crates/adaptive/src/acg/request_surfaces/mod.rs
crates/{core,adaptive}/**

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

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

Files:

  • crates/adaptive/tests/unit/acg/request_surface_tests.rs
  • crates/adaptive/src/acg/request_surfaces/mod.rs
**/*.{rs,py,js,ts,tsx,jsx,go,sh,toml,yaml,yml,md}

📄 CodeRabbit inference engine (AGENTS.md)

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

Files:

  • crates/adaptive/tests/unit/acg/request_surface_tests.rs
  • crates/adaptive/src/acg/request_surfaces/mod.rs
**/*.{rs,py,go,js,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

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

Files:

  • crates/adaptive/tests/unit/acg/request_surface_tests.rs
  • crates/adaptive/src/acg/request_surfaces/mod.rs
crates/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

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

Files:

  • crates/adaptive/tests/unit/acg/request_surface_tests.rs
  • crates/adaptive/src/acg/request_surfaces/mod.rs
**

⚙️ CodeRabbit configuration file

**:

AGENTS.md

This file provides guidance to agents, including Claude Code and OpenAI Codex, when working in this repository.

Project Overview

NeMo Relay is a multi-language agent runtime framework for execution scopes, lifecycle events, middleware, plugins, and observability around tool and LLM calls. The core runtime is Rust. Primary supported bindings are Rust, Python, and Node.js. Go, WebAssembly, and the raw C FFI are experimental and source-first.

The shared runtime model is:

  1. Scope stacks decide where work belongs and which scope-local behavior is visible.
  2. Middleware registries decide what guardrails and intercepts run around managed calls.
  3. Plugins install reusable runtime behavior from configuration.
  4. Events record runtime behavior in ATOF form.
  5. Subscribers and exporters consume events in-process or export them to ATIF, OpenTelemetry, OpenInference, or other backends.

Repository Structure

The repository layout separates the Rust runtime, language bindings, documentation,
integration patches, and agent-facing skills.

crates/
  core/       # Rust core runtime crate, published as nemo-relay
  adaptive/   # Adaptive runtime primitives and plugin components
  python/     # PyO3 native extension for the Python package
  ffi/        # Raw C ABI layer used by downstream bindings such as Go
  node/       # NAPI Node.js binding and JavaScript/TypeScript entry points
  wasm/       # wasm-bindgen WebAssembly binding and JS wrappers
python/
  nemo_relay/  # Python wrapper package: scopes, tools, LLM, middleware, typed helpers, plugins, adaptive helpers
  tests/      # Python tests
go/
  nemo_relay/  # Experimental Go CGo binding and tests
fern/         # Fern documentation site
scripts/      # Stable wrappers and helper scripts; build/test/docs entry points live in justfile
third_party/  # P...

Files:

  • crates/adaptive/tests/unit/acg/request_surface_tests.rs
  • crates/adaptive/src/acg/request_surfaces/mod.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/adaptive/tests/unit/acg/request_surface_tests.rs
  • crates/adaptive/src/acg/request_surfaces/mod.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/adaptive/tests/unit/acg/request_surface_tests.rs
🔇 Additional comments (2)
crates/adaptive/src/acg/request_surfaces/mod.rs (1)

44-51: LGTM!

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

309-322: LGTM!

Comment thread crates/adaptive/src/acg/request_surfaces/mod.rs Outdated
@zhongxuanwang-nv

Copy link
Copy Markdown
Member Author

/ok to test 633820a

@zhongxuanwang-nv zhongxuanwang-nv force-pushed the refactor/hoist-provider-schema-handling branch from 633820a to 3d93e03 Compare June 23, 2026 21:26
@zhongxuanwang-nv zhongxuanwang-nv marked this pull request as ready for review June 23, 2026 21:26
@zhongxuanwang-nv zhongxuanwang-nv requested review from a team and lvojtku as code owners June 23, 2026 21:26
@zhongxuanwang-nv zhongxuanwang-nv removed the DO NOT MERGE PR should not be merged; see PR for details label Jun 23, 2026
@bbednarski9 bbednarski9 self-requested a review June 23, 2026 22:26
@willkill07

Copy link
Copy Markdown
Member

The resolver itself is cheap, but the provider-aware ambiguity handling appears unused in the main adaptive translation path. translate_request knows provider, but build_semantic_request_view resolves from shape only. Should build_semantic_request_view take provider and call resolve_request_surface(provider, request) so Anthropic messages-only requests are decoded with AnthropicMessagesCodec?

I think this is intentional. In acg_component we intentionally pick the request surface from the shape, and there's a test acg_component_source_resolves_request_surfaces_instead_of_decoding_from_provider guarding this. So an ambiguous "message_only" request that could be from OpenAI or Anthropic deliberately passes through untranslated instead of guessing from the provider. Making it provider-aware may reverse that design?

The design was that ACG adopted the provider codec first. If we are extending Relay to use provider codecs in more places, we can change the surface to pass this in. The consequences of this are that (1) ACG is really only support with Anthropic and (2) we need to ensure compatibility without breaking the existing public configuration surface.

@zhongxuanwang-nv

Copy link
Copy Markdown
Member Author

The resolver itself is cheap, but the provider-aware ambiguity handling appears unused in the main adaptive translation path. translate_request knows provider, but build_semantic_request_view resolves from shape only. Should build_semantic_request_view take provider and call resolve_request_surface(provider, request) so Anthropic messages-only requests are decoded with AnthropicMessagesCodec?

I think this is intentional. In acg_component we intentionally pick the request surface from the shape, and there's a test acg_component_source_resolves_request_surfaces_instead_of_decoding_from_provider guarding this. So an ambiguous "message_only" request that could be from OpenAI or Anthropic deliberately passes through untranslated instead of guessing from the provider. Making it provider-aware may reverse that design?

The design was that ACG adopted the provider codec first. If we are extending Relay to use provider codecs in more places, we can change the surface to pass this in. The consequences of this are that (1) ACG is really only support with Anthropic and (2) we need to ensure compatibility without breaking the existing public configuration surface.

That makes sense! I just dropped the unused provider-aware tie-break code, and since that making build_semantic_request_view would be a behavior change (starts translating system-less Ant requests and changes the tests), could I do this also in a follow-up PR, so we can get this PR merged ASAP which is blocking Maryam's PR? Thanks Will!

Comment thread docs/integrate-into-frameworks/provider-response-codecs.mdx Outdated
Comment thread crates/core/src/observability/atif.rs
Comment thread crates/core/src/observability/atif.rs
Comment thread crates/core/src/observability/manual.rs
@zhongxuanwang-nv

Copy link
Copy Markdown
Member Author

/ok to test a369cd4

@zhongxuanwang-nv zhongxuanwang-nv force-pushed the refactor/hoist-provider-schema-handling branch from 679ce9f to a369cd4 Compare June 24, 2026 18:48
@willkill07 willkill07 removed the request for review from lvojtku June 24, 2026 18:49
Comment thread crates/core/src/codec/resolve.rs Outdated
Use OpenAIChat and OpenAIResponses to match OpenAIChatCodec and
OpenAIResponsesCodec naming.

Signed-off-by: Zhongxuan Wang <[email protected]>
@zhongxuanwang-nv zhongxuanwang-nv force-pushed the refactor/hoist-provider-schema-handling branch from 89864f0 to b200506 Compare June 24, 2026 18:59
@zhongxuanwang-nv

Copy link
Copy Markdown
Member Author

/ok to test e307e8d

@mnajafian-nv

Copy link
Copy Markdown
Contributor

/merge

@rapids-bot rapids-bot Bot merged commit 6f7e0d1 into NVIDIA:main Jun 24, 2026
71 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Improvement improvement to existing functionality lang:rust PR changes/introduces Rust code size:XL PR is extra large

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants