fix: require Relay 0.7 for coding-agent gateways - #180
Conversation
Signed-off-by: Ajay Thorve <athorve@nvidia.com>
WalkthroughThe PR updates Relay CLI support from 0.6.x to 0.7.x. It reports observability contract version 3 and converts version-2 plugin configuration into version-3 endpoint configuration with validation. ChangesRelay 0.7 migration
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant Adapter
participant write_relay_configs
participant _relay_plugin_config_for_version
participant RelayConfigFile
Adapter->>write_relay_configs: request Relay configuration version 3
write_relay_configs->>_relay_plugin_config_for_version: convert plugin configuration
_relay_plugin_config_for_version-->>write_relay_configs: return validated endpoint configuration
write_relay_configs->>RelayConfigFile: write serialized configuration
Important Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional. ❌ Failed checks (1 error, 1 warning)
✅ Passed checks (3 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
Fern docs preview: https://nvidia-preview-pull-request-180.docs.buildwithfern.com/nemo/fabric |
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
tests/adapters/test_adapaters_common_utils.py (1)
760-769: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winReplace the hardcoded
/tmppaths withtmp_pathto clear the Ruff S108 error.Ruff reports S108 at Line 769 and ast-grep reports
hardcoded-tmp-file. These values are inert test data, so the fix costs one line each and keeps the lint gate green.🧹 Proposed fix
"atof": { "enabled": True, "sinks": [ { "type": "file", - "output_directory": "/tmp/atof", + "output_directory": str(tmp_path / "atof"), } ], }, - "atif": {"enabled": True, "output_directory": "/tmp/atif"}, + "atif": { + "enabled": True, + "output_directory": str(tmp_path / "atif"), + },🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/adapters/test_adapaters_common_utils.py` around lines 760 - 769, Replace the hardcoded “/tmp/atof” and “/tmp/atif” values in the test configuration with paths derived from the pytest tmp_path fixture, preserving the existing directory names and configuration structure.Source: Linters/SAST tools
🤖 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 `@docs/sdk/python.mdx`:
- Line 509: Update the sentence near “translates its public observability model”
to use “NeMo Relay” consistently instead of “Relay’s,” and replace the vague “At
launch” qualifier with wording that identifies the specific launch or timeframe.
- Around line 507-512: Update the NeMo Relay CLI installation section in the
install guide to explicitly require versions from 0.7.0 inclusive through below
0.8.0, matching the range documented near the Claude and Codex streaming
requirements in the SDK guide.
In `@tests/adapters/test_adapaters_common_utils.py`:
- Around line 827-868: Parametrize the two rejection cases in the test module
using shared plugin configuration and expected ValueError-message inputs, while
preserving each case’s distinct error match. Add a third parametrized case
covering an unsupported observability version (a value other than 3) through
_relay_plugin_config_for_version, and add coverage for write_relay_configs using
its default observability version of 3.
---
Outside diff comments:
In `@tests/adapters/test_adapaters_common_utils.py`:
- Around line 760-769: Replace the hardcoded “/tmp/atof” and “/tmp/atif” values
in the test configuration with paths derived from the pytest tmp_path fixture,
preserving the existing directory names and configuration structure.
🪄 Autofix
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: 6100a717-eb7e-45ab-8d45-0e8699a2c03c
📒 Files selected for processing (15)
adapters/claude/README.mdadapters/codex/README.mdadapters/common/src/nemo_fabric_adapters/common/relay_gateway.pyadapters/common/src/nemo_fabric_adapters/common/utils.pydocs/integrations/harness/claude.mdxdocs/integrations/harness/codex.mdxdocs/sdk/python.mdxexamples/code_review_agent/README.mdexamples/harbor/README.mdexamples/harbor/swebench/README.mdtests/adapters/test_adapaters_common_utils.pytests/adapters/test_adapters_common_relay_gateway.pytests/adapters/test_claude_adapter.pytests/adapters/test_codex_adapter.pytests/e2e/test_claude.py
📜 Review details
⏰ Context from checks skipped due to timeout. (18)
- GitHub Check: Preview docs
- GitHub Check: Test (Python 3.13, macos-arm64)
- GitHub Check: Test (Python 3.14, windows-amd64)
- GitHub Check: Test (Python 3.12, windows-amd64)
- GitHub Check: Test (Python 3.12, macos-arm64)
- GitHub Check: Test (Python 3.14, macos-arm64)
- GitHub Check: Test (Python 3.12, linux-amd64)
- GitHub Check: Test (Python 3.13, linux-amd64)
- GitHub Check: Test (Python 3.14, linux-amd64)
- GitHub Check: Test (Python 3.11, windows-amd64)
- GitHub Check: Test (Python 3.11, macos-arm64)
- GitHub Check: Test (Python 3.13, linux-arm64)
- GitHub Check: Test (Python 3.13, windows-amd64)
- GitHub Check: Test (Python 3.14, linux-arm64)
- GitHub Check: Test (Python 3.11, linux-amd64)
- GitHub Check: Test (Python 3.11, linux-arm64)
- GitHub Check: Test (Python 3.12, linux-arm64)
- GitHub Check: Pre-commit
🧰 Additional context used
📓 Path-based instructions (33)
**/*.{md,rst}
📄 CodeRabbit inference engine (.agents/skills/contribute-api/SKILL.md)
Update documentation and examples in the same branch as the public API change.
Files:
examples/harbor/README.mdexamples/code_review_agent/README.mdadapters/claude/README.mdadapters/codex/README.mdexamples/harbor/swebench/README.md
{README.md,docs/**/*.{md,mdx,yml},examples/**/*.{md,mdx,yml}}
📄 CodeRabbit inference engine (.agents/skills/contribute-docs/SKILL.md)
Keep package names, repository references, and build commands current in documentation and examples.
Files:
examples/harbor/README.mdexamples/code_review_agent/README.mddocs/integrations/harness/codex.mdxdocs/integrations/harness/claude.mdxdocs/sdk/python.mdxexamples/harbor/swebench/README.md
{docs/**/*.{md,mdx,yml},examples/**/*.{md,mdx,yml}}
📄 CodeRabbit inference engine (.agents/skills/contribute-docs/SKILL.md)
Update relevant getting-started, reference, adapter, and example documentation when the corresponding examples or adapters change.
Files:
examples/harbor/README.mdexamples/code_review_agent/README.mddocs/integrations/harness/codex.mdxdocs/integrations/harness/claude.mdxdocs/sdk/python.mdxexamples/harbor/swebench/README.md
**/*
📄 CodeRabbit inference engine (.agents/skills/karpathy-guidelines/SKILL.md)
**/*: Before implementing, explicitly state assumptions, surface ambiguity and tradeoffs, present multiple interpretations when relevant, and ask for clarification rather than silently deciding or proceeding when requirements are unclear.
Prefer the minimum code needed to solve the requested problem: avoid speculative features, unnecessary abstractions, unrequested flexibility, and handling of impossible scenarios; simplify overcomplicated solutions.
When editing existing code, make surgical changes only: do not modify unrelated code, comments, formatting, or pre-existing dead code; match the existing style, and remove only unused imports, variables, or functions introduced by your changes.
Define verifiable success criteria for each task, such as writing regression tests for bugs and invalid-input tests for validation, then verify the implementation against those criteria. For multi-step work, state a brief plan with a verification check for each step.
**/*: Always spellNVIDIAin all caps; do not useNvidia,nvidia,nVidia,nVIDIA, orNV.
Usean NVIDIAbefore a noun, because the name begins with an “en” sound.
Do not add a registered trademark symbol afterNVIDIAwhen referring to the company; use trademark symbols with product names only when required by the document type or legal guidance.
Verify official capitalization, spacing, hyphenation, and spelling for NVIDIA and third-party product names; do not rewrite official product names for grammar or title-case rules.
Precede NVIDIA product names withNVIDIAon first mention when natural and accurate, and link the first mention when the destination helps the reader.
On first use, include the company name and full model qualifier when it helps identify the model; preserve official capitalization and punctuation, and use shorter family names only after establishing the full name.
For learning-oriented and developer content, do not force trademark symbols unless explicitly required; for press, ...
Files:
examples/harbor/README.mdexamples/code_review_agent/README.mdadapters/claude/README.mddocs/integrations/harness/codex.mdxdocs/integrations/harness/claude.mdxadapters/common/src/nemo_fabric_adapters/common/relay_gateway.pydocs/sdk/python.mdxtests/e2e/test_claude.pyadapters/codex/README.mdtests/adapters/test_codex_adapter.pyadapters/common/src/nemo_fabric_adapters/common/utils.pytests/adapters/test_adapaters_common_utils.pyexamples/harbor/swebench/README.mdtests/adapters/test_adapters_common_relay_gateway.pytests/adapters/test_claude_adapter.py
**/*.{md,mdx,rst}
📄 CodeRabbit inference engine (.agents/skills/review-doc-style/assets/nvidia-style-guide.md)
**/*.{md,mdx,rst}: For NeMo Fabric documentation, verify technical claims against the current repository, public API, or documented command before reviewing style.
Always spellNVIDIAin all caps; do not useNvidia,nvidia, orNV.
Format commands, code elements, expressions, package names, file names, and paths as inline code.
Use descriptive link text; avoid raw URLs and weak anchors such ashereorread more.
Use title case consistently for technical documentation headings.
Introduce code blocks, lists, tables, and images with complete sentences.
Write procedures as imperative, parallel steps; split long procedures into smaller tasks.
Prefer active voice, present tense, short sentences, contractions, and plain English while preserving necessary technical precision.
Usecanfor possibility and reservemayfor permission.
Useafterfor temporal relationships instead ofonce, and preferrefer tooverseewhen directing readers to another resource.
Avoid culture-specific idioms, unnecessary Latinisms, jokes, and marketing exaggeration in technical documentation.
Spell out months in body text, avoid ordinal dates, and use clear time zones.
Spell out whole numbers from zero through nine unless they are technical values, parameters, versions, or UI values; use numerals for 10 or greater and commas in thousands.
Do not add trademark symbols to learning-oriented documentation unless the source, platform, or legal guidance explicitly requires them.
Do not replace precise technical terms with simpler words when doing so would lose precision.
Do not flag passive voice when the actor is unknown or the action is the important part.
Do not rewrite API names, package names, command flags, or code literals for style.
**/*.{md,mdx,rst}: Use consistent title case for technical-document headings and table headers; avoid quotation marks, ampersands, and exclamation marks in headings, while preserving official product, event, research, and whitepaper title ...
Files:
examples/harbor/README.mdexamples/code_review_agent/README.mdadapters/claude/README.mddocs/integrations/harness/codex.mdxdocs/integrations/harness/claude.mdxdocs/sdk/python.mdxadapters/codex/README.mdexamples/harbor/swebench/README.md
**/*.{md,rst,txt,adoc}
📄 CodeRabbit inference engine (.agents/skills/review-doc-style/assets/nvidia-style-language-mechanics.md)
**/*.{md,rst,txt,adoc}: For technical documentation, use professional, active, conversational, engaging, precise, and plain-English prose. Prefer active voice, present tense, short sentences, and scannable paragraphs. Avoid casual or imprecise language, swearing, threats, insults, jokes, puns, culture-specific idioms, marketing exaggeration, and unsupported third-party comparisons.
Usecanfor possibility and reservemayfor permission; useafterfor temporal order; userefer tofor cross-references; prefer short direct sentences and specific verbs; avoid unnecessarypleasein technical documentation.
Prefer active voice when the actor matters. Passive voice is acceptable when the actor is unknown or irrelevant, when the action or result is the focus, or in programmer documentation.
Use natural contractions in conversational technical prose, but do not force them in formal legal copy, API references, or generated text.
Prefer simpler English over Latinisms: usefor exampleorsuch asinstead ofe.g.,and so oninstead ofetc.,that isinstead ofi.e.,compared toinstead ofvs., andby,through, orusinginstead ofvia. Use industry-standard terms such as in silico, in vitro, and in vivo when appropriate, and italicize them in running text.
Usethatwithout commas for essential clauses, andwhichwith commas for nonessential clauses.
Format dates and times clearly: spell out months in body text; use forms such asJune 12, 2025; avoid numeric or ordinal dates; capitalize days; use 12-hour time when appropriate; include a space beforea.m.orp.m.; useETandPTfor needed time zones; avoid24/7; and preferfrom 12:30 to 1:00 p.m.for prose ranges.
Format numbers consistently: spell out zero through nine in body text, use numerals for 10 or greater and for technical values, use commas in thousands, do not begin a sentence with a numeral, spell out ordinals, and use numerals consistently within a category wh...
Files:
examples/harbor/README.mdexamples/code_review_agent/README.mdadapters/claude/README.mdadapters/codex/README.mdexamples/harbor/swebench/README.md
examples/{README.md,**/*}
📄 CodeRabbit inference engine (AGENTS.md)
Update examples documentation and relevant examples when public behavior, the package, or supported bindings change.
Files:
examples/harbor/README.mdexamples/code_review_agent/README.mdexamples/harbor/swebench/README.md
**/*.{md,mdx,yml,py,rs,sh}
📄 CodeRabbit inference engine (.agents/skills/review-doc-style/SKILL.md)
Keep documentation aligned with current NeMo Fabric behavior, repository layout, entry points, commands, package names, APIs, bindings, and support claims.
Files:
examples/harbor/README.mdexamples/code_review_agent/README.mdadapters/claude/README.mddocs/integrations/harness/codex.mdxdocs/integrations/harness/claude.mdxadapters/common/src/nemo_fabric_adapters/common/relay_gateway.pydocs/sdk/python.mdxtests/e2e/test_claude.pyadapters/codex/README.mdtests/adapters/test_codex_adapter.pyadapters/common/src/nemo_fabric_adapters/common/utils.pytests/adapters/test_adapaters_common_utils.pyexamples/harbor/swebench/README.mdtests/adapters/test_adapters_common_relay_gateway.pytests/adapters/test_claude_adapter.py
**/*.{md,mdx}
📄 CodeRabbit inference engine (.agents/skills/review-doc-style/SKILL.md)
**/*.{md,mdx}: Use the full product nameNVIDIA NeMo Fabricon first use, typically in the title and H1; useNeMo Fabricthereafter. Usefabricalone only for the CLI tool and surround it with backticks.
Treat incorrect or stale commands, package names, paths, APIs, support claims, procedures, examples, terminology, or public behavior documentation as blocking issues.
CapitalizeNVIDIAcorrectly and format code, commands, paths, and filenames as inline code where needed.
Use title case for technical-documentation headings.
Introduce code blocks, tables, and lists with complete lead-in sentences; ensure examples match current APIs and build commands.
Use descriptive anchor text, avoid raw URLs and generic labels such ashere, and use repository-relative.mdxpaths for links withindocs/.
Prefer active voice, present tense, short sentences, plain English, consistent terminology, and imperative, parallel, scannable procedures.
Useafterinstead ofoncewhen expressing temporal sequence, and usecanrather thanmaywhen describing possibility rather than permission.
Avoid ambiguous numeric dates and ordinal dates in body text.
For learning-oriented documentation, do not force trademark symbols unless the source document explicitly requires them.
When reporting documentation-review findings, lead withMust fix,Should fix, andNice to havecategories; include file path, line reference, current problem, rationale, and a concrete rewrite or direction.
Files:
examples/harbor/README.mdexamples/code_review_agent/README.mdadapters/claude/README.mddocs/integrations/harness/codex.mdxdocs/integrations/harness/claude.mdxdocs/sdk/python.mdxadapters/codex/README.mdexamples/harbor/swebench/README.md
**/*.md
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Update relevant SDK, API reference, adapter, example, integration, and support documentation when the corresponding public surface changes.
Files:
examples/harbor/README.mdexamples/code_review_agent/README.mdadapters/claude/README.mdadapters/codex/README.mdexamples/harbor/swebench/README.md
**/*.{html,md}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
HTML and Markdown files must use the specified SPDX HTML-comment header.
Files:
examples/harbor/README.mdexamples/code_review_agent/README.mdadapters/claude/README.mdadapters/codex/README.mdexamples/harbor/swebench/README.md
{adapters/**,examples/**}
⚙️ CodeRabbit configuration file
{adapters/**,examples/**}: Review adapter and example changes for command correctness, config/schema consistency, artifact handling, and compatibility with the public NeMo Fabric contracts.
Files:
examples/harbor/README.mdexamples/code_review_agent/README.mdadapters/claude/README.mdadapters/common/src/nemo_fabric_adapters/common/relay_gateway.pyadapters/codex/README.mdadapters/common/src/nemo_fabric_adapters/common/utils.pyexamples/harbor/swebench/README.md
{*.md,**/*.md,**/*.mdx,**/*.ipynb}
⚙️ CodeRabbit configuration file
{*.md,**/*.md,**/*.mdx,**/*.ipynb}: Enforce the product name in user-facing prose: use "NVIDIA NeMo Fabric" on first use and "NeMo Fabric" thereafter. Flag standalone capitalized "Fabric" when it refers to the product. Do not flag the lowercasefabricCLI command, package/import/crate names, code identifiers, API symbols, configuration keys, file paths, or unrelated generic uses of the word.
Files:
examples/harbor/README.mdexamples/code_review_agent/README.mdadapters/claude/README.mddocs/integrations/harness/codex.mdxdocs/integrations/harness/claude.mdxdocs/sdk/python.mdxadapters/codex/README.mdexamples/harbor/swebench/README.md
adapters/*/README.md
📄 CodeRabbit inference engine (AGENTS.md)
Update adapter integration READMEs when public behavior, examples, or supported bindings change.
Document adapter installation, supported configuration, harness-only settings, credentials, lifecycle, telemetry, artifacts, limitations, and focused test commands. Include a canonical typed SDK example and, when required, a canonical harness-native YAML fixture.
Files:
adapters/claude/README.mdadapters/codex/README.md
adapters/**/*
📄 CodeRabbit inference engine (.agents/skills/contribute-adapter/SKILL.md)
Place repository adapters under
adapters/<name>, define their install extra and packaged descriptor, select the matchingharness.resolutionstrategy, and document repository orbase_dirdescriptor discovery.
Files:
adapters/claude/README.mdadapters/common/src/nemo_fabric_adapters/common/relay_gateway.pyadapters/codex/README.mdadapters/common/src/nemo_fabric_adapters/common/utils.py
**/*.mdx
📄 CodeRabbit inference engine (.agents/skills/contribute-docs/SKILL.md)
In MDX files, use JSX comment delimiters (
{/*and*/}) for top-of-file comments, including SPDX headers; do not use HTML comments.
**/*.mdx: For documentation site changes, runjust docsto regenerate Python and Rust API references and validate Fern configuration.
MDX files must use the specified JSX-comment SPDX header.
Files:
docs/integrations/harness/codex.mdxdocs/integrations/harness/claude.mdxdocs/sdk/python.mdx
docs/**/*.{md,mdx,yml}
📄 CodeRabbit inference engine (.agents/skills/contribute-docs/SKILL.md)
Run
just docswhen the documentation site changes.Update user-facing Fern documentation, including
docs/index.yml, when public behavior, the package, examples, or supported bindings change.
Files:
docs/integrations/harness/codex.mdxdocs/integrations/harness/claude.mdxdocs/sdk/python.mdx
docs/**/*.mdx
📄 CodeRabbit inference engine (.agents/skills/review-doc-style/SKILL.md)
docs/**/*.mdx: Use source-relative links with the target.mdxextension for links between files underdocs/; do not use Fern site-root paths.
Use{/* ... */}delimiters for top-of-file MDX SPDX comments, not HTML comment delimiters.
Files:
docs/integrations/harness/codex.mdxdocs/integrations/harness/claude.mdxdocs/sdk/python.mdx
{docs/**,README.md,AGENTS.md}
⚙️ CodeRabbit configuration file
{docs/**,README.md,AGENTS.md}: Review documentation for technical accuracy against the current API, command correctness, and consistency with generated schemas.
For links between files under docs/, require paths relative to the source file with the target file's .mdx extension so they work in both Fern builds and repository browsers. Flag Fern site-root links such as NeMo Fabric overview; use the repository-relative equivalent, such as NeMo Fabric overview.
Files:
docs/integrations/harness/codex.mdxdocs/integrations/harness/claude.mdxdocs/sdk/python.mdx
**/*.{rs,py,pyi,json,yaml,yml}
📄 CodeRabbit inference engine (.agents/skills/contribute-api/SKILL.md)
Determine and update every affected public surface, including the CLI, PyO3 bindings, Python SDK, type stubs, schemas, and adapter contract, so they remain in parity.
Files:
adapters/common/src/nemo_fabric_adapters/common/relay_gateway.pytests/e2e/test_claude.pytests/adapters/test_codex_adapter.pyadapters/common/src/nemo_fabric_adapters/common/utils.pytests/adapters/test_adapaters_common_utils.pytests/adapters/test_adapters_common_relay_gateway.pytests/adapters/test_claude_adapter.py
**/*.{rs,py}
📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)
For native binding changes, run
cargo check -p fabric-python --locked.Use
snake_casefor functions and variables; usePascalCasefor Rust types and Python classes.
Files:
adapters/common/src/nemo_fabric_adapters/common/relay_gateway.pytests/e2e/test_claude.pytests/adapters/test_codex_adapter.pyadapters/common/src/nemo_fabric_adapters/common/utils.pytests/adapters/test_adapaters_common_utils.pytests/adapters/test_adapters_common_relay_gateway.pytests/adapters/test_claude_adapter.py
**/*.{py,pyi}
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
If Python code or a Python-facing adapter changes, run
just test-python.In Python SDK, adapters, examples, and tests, follow the existing style, use type annotations for public APIs, and keep native binding declarations synchronized with their Rust implementations.
Files:
adapters/common/src/nemo_fabric_adapters/common/relay_gateway.pytests/e2e/test_claude.pytests/adapters/test_codex_adapter.pyadapters/common/src/nemo_fabric_adapters/common/utils.pytests/adapters/test_adapaters_common_utils.pytests/adapters/test_adapters_common_relay_gateway.pytests/adapters/test_claude_adapter.py
**/*.{rs,py,pyi}
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
**/*.{rs,py,pyi}: If public configuration types change, confirm schema snapshot tests injust test-rustpass and review generated schema diffs.
For schema or public contract changes, run both language suites and review changes underschemas/and generated API references.
Files:
adapters/common/src/nemo_fabric_adapters/common/relay_gateway.pytests/e2e/test_claude.pytests/adapters/test_codex_adapter.pyadapters/common/src/nemo_fabric_adapters/common/utils.pytests/adapters/test_adapaters_common_utils.pytests/adapters/test_adapters_common_relay_gateway.pytests/adapters/test_claude_adapter.py
**/*.{py,pyi,rs}
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
For Python SDK or PyO3 binding changes, use
python-tests, run focused pytest tests first, thenjust test-python; rebuild withjust build-pythonwhen native code or packaging changes.Public contract changes must keep native Python binding declarations synchronized with their Rust implementations.
Files:
adapters/common/src/nemo_fabric_adapters/common/relay_gateway.pytests/e2e/test_claude.pytests/adapters/test_codex_adapter.pyadapters/common/src/nemo_fabric_adapters/common/utils.pytests/adapters/test_adapaters_common_utils.pytests/adapters/test_adapters_common_relay_gateway.pytests/adapters/test_claude_adapter.py
**/*.{rs,py,toml}
📄 CodeRabbit inference engine (.agents/skills/update-project-version/SKILL.md)
When editing version helpers, verify every
nemo-fabric-*workspace package through Cargo metadata and reject a static version inpython/pyproject.toml.
Files:
adapters/common/src/nemo_fabric_adapters/common/relay_gateway.pytests/e2e/test_claude.pytests/adapters/test_codex_adapter.pyadapters/common/src/nemo_fabric_adapters/common/utils.pytests/adapters/test_adapaters_common_utils.pytests/adapters/test_adapters_common_relay_gateway.pytests/adapters/test_claude_adapter.py
**/*.{toml,rs,py}
📄 CodeRabbit inference engine (.agents/skills/update-project-version/SKILL.md)
Avoid blind repository-wide replacement of version-like strings; distinguish package-version references from examples and unrelated dependency versions.
Files:
adapters/common/src/nemo_fabric_adapters/common/relay_gateway.pytests/e2e/test_claude.pytests/adapters/test_codex_adapter.pyadapters/common/src/nemo_fabric_adapters/common/utils.pytests/adapters/test_adapaters_common_utils.pytests/adapters/test_adapters_common_relay_gateway.pytests/adapters/test_claude_adapter.py
adapters/**/*.{py,js,ts,java,go,rs}
📄 CodeRabbit inference engine (.agents/skills/contribute-adapter/SKILL.md)
adapters/**/*.{py,js,ts,java,go,rs}: Use the existing Fabricpythonorprocessrunner and normalized request/result contracts. Reuseadapters/common/only when its contract fits; do not add a runner or abstraction for one adapter.
For adapters consuming normalized configuration or runtime context, use the complete Fabric invocation and treatconfig,capability_plan,telemetry_plan, andruntime_contextas authoritative. Reserveharness.settingsfor harness-specific behavior.
Apply configuration precedence in this order: normalized config; Fabric-resolved plans and runtime context; harness-specific settings; descriptor and adapter defaults. Reject conflicting duplicate declarations or unsupported behavior with actionable field-specific errors; never silently drop configuration.
Run dependency and authentication preflight before invoking the harness. Declare fixed dependencies in descriptor requirements, validate versions, hooks, and credentials, and never expose credential values in output, errors, events, logs, or fixtures.
Forward only required system variables, selected credential variables, telemetry variables, and documented harness-specific environment; never forward or log unrelated environment values.
Run one local adapter host per Fabric runtime for orderedstart→invoke*→stop. Emit one JSON lifecycle response per request on stdout and diagnostics on stderr; treat early exit as a host crash.
Return harness-level invoke failures in a successful lifecycle response withresponse: null,failed: true, and structurederrorcontainingcode,message,retryable, and optionalmetadata.
Do not emit NeMo Relay stream records on adapter stdout. Relay records are sent out of band through the SDK-owned NDJSON ATOF endpoint; the adapter must return exactly one terminal lifecycle response.
Scope workspace, generated configuration, state, sessions, and artifacts to the resolved runtime context. Write artifacts only within the resolved r...
Files:
adapters/common/src/nemo_fabric_adapters/common/relay_gateway.pyadapters/common/src/nemo_fabric_adapters/common/utils.py
docs/sdk/python.mdx
📄 CodeRabbit inference engine (AGENTS.md)
Keep the Python/Rust binding contract current when the public API changes.
Files:
docs/sdk/python.mdx
tests/**/*.{rs,py}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
When adding functionality, include tests in the corresponding Rust crate or the relevant area under
tests/.
Files:
tests/e2e/test_claude.pytests/adapters/test_codex_adapter.pytests/adapters/test_adapaters_common_utils.pytests/adapters/test_adapters_common_relay_gateway.pytests/adapters/test_claude_adapter.py
tests/**/*.py
📄 CodeRabbit inference engine (.agents/skills/python-tests/SKILL.md)
tests/**/*.py: Use pytest to run Python tests.
Do not add@pytest.mark.asyncioto tests; async tests are automatically detected by the async runner.
Do not add-> Nonereturn type annotations to test functions.
When mocking a class, useunittest.mock.MagicMockorAsyncMock, using thespecargument when necessary, rather than defining a new class.
Prefix mocked class names withmock, notfake.
Prefer pytest fixtures over helper methods.
If a fixture is needed in multiple test files, define it once inconftest.pyrather than repeating it.
Define fixtures using@pytest.fixture(name="<fixture_name>"[, scope="<scope>"])and a<fixture_name>_fixturefunction; specifyscopeonly when it is notfunction.
Preferpytest.mark.parametrizeover separate tests for different input types.
Use@pytest.mark.usefixtureswhen a fixture is needed but its returned value is unused or it returns no value.
Avoid defensive programming in tests; access expected values directly so missing data raises a clear failure, such as usingresults["data"]instead ofresults.get("data").
When adapter installation metadata changes, packaging metadata tests must directly assert that the root project depends unconditionally on the exact-versionnemo-fabric-runtimedistribution.
Packaging metadata tests must verify that each root harness extra delegates to the matching version of the leaf adapter'sharnessextra.
Packaging metadata tests must verify that bare leaf dependencies remain adapter-owned and that the rootadapter-testsdependency group installs each leaf through itsharnessextra.
Packaging metadata tests must verify that every leaf providesfull; only adapters importing NeMo Relay Python APIs providerelay, while adapters using an external Relay executable havefullequal toharness.
Files:
tests/e2e/test_claude.pytests/adapters/test_codex_adapter.pytests/adapters/test_adapaters_common_utils.pytests/adapters/test_adapters_common_relay_gateway.pytests/adapters/test_claude_adapter.py
{tests/**,python/tests/**}
⚙️ CodeRabbit configuration file
{tests/**,python/tests/**}: Tests should cover the behavior promised by the changed API surface, including error paths, lifecycle cleanup, and SDK/native parity where relevant.
Files:
tests/e2e/test_claude.pytests/adapters/test_codex_adapter.pytests/adapters/test_adapaters_common_utils.pytests/adapters/test_adapters_common_relay_gateway.pytests/adapters/test_claude_adapter.py
tests/adapters/**/*.py
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
tests/adapters/**/*.py: If an adapter or integration changes, run its focused tests.
For adapter behavior changes, run focused adapter tests undertests/adapters, then runjust test-python.
Files:
tests/adapters/test_codex_adapter.pytests/adapters/test_adapaters_common_utils.pytests/adapters/test_adapters_common_relay_gateway.pytests/adapters/test_claude_adapter.py
tests/adapters/test_*.py
📄 CodeRabbit inference engine (.agents/skills/contribute-adapter/SKILL.md)
tests/adapters/test_*.py: Add focused tests for descriptor shape and exact capabilities, positive normalized-surface mappings, rejection of unsupported values and unenforceable policies, result normalization without secret leakage, one-shot execution, continuation, runtime isolation, and the packaged subprocess entry point.
Provide a credential-free fixture coveringplan,doctor, andrun; keep credential-dependent live-harness tests opt-in while retaining a deterministic CI end-to-end path.
Files:
tests/adapters/test_codex_adapter.pytests/adapters/test_adapaters_common_utils.pytests/adapters/test_adapters_common_relay_gateway.pytests/adapters/test_claude_adapter.py
🪛 ast-grep (0.45.0)
tests/adapters/test_adapaters_common_utils.py
[info] 768-768: Do not hardcode temporary file or directory names
Context: "/tmp/atif"
Note: [CWE-377] Insecure Temporary File.
(hardcoded-tmp-file)
🪛 Ruff (0.16.1)
adapters/common/src/nemo_fabric_adapters/common/utils.py
[warning] 404-407: Avoid specifying long messages outside the exception class
(TRY003)
[warning] 412-415: Avoid specifying long messages outside the exception class
(TRY003)
[warning] 431-434: Avoid specifying long messages outside the exception class
(TRY003)
[warning] 448-451: Avoid specifying long messages outside the exception class
(TRY003)
[warning] 465-467: Prefer TypeError exception for invalid type
(TRY004)
[warning] 465-467: Avoid specifying long messages outside the exception class
(TRY003)
tests/adapters/test_adapaters_common_utils.py
[error] 769-769: Probable insecure usage of temporary file or directory: "/tmp/atif"
(S108)
🔇 Additional comments (19)
tests/adapters/test_adapters_common_relay_gateway.py (2)
72-73: LGTM!Also applies to: 76-76, 86-86
49-60: 🎯 Functional CorrectnessDefine Relay prerelease compatibility.
relay_cli_contractignores prerelease identifiers, so0.7.0-alpha.20260805is accepted as(0, 7, 0). If>=0.7.0,<0.8.0follows SemVer, reject this fixture; otherwise document that the compatibility check uses numeric components only.adapters/claude/README.md (1)
123-124: LGTM!adapters/codex/README.md (1)
148-149: LGTM!docs/integrations/harness/claude.mdx (1)
173-174: LGTM!docs/integrations/harness/codex.mdx (1)
206-207: LGTM!examples/harbor/README.md (1)
76-76: LGTM!adapters/common/src/nemo_fabric_adapters/common/relay_gateway.py (1)
23-24: 🗄️ Data Integrity & IntegrationNo shared-contract change is required.
relay_cli_contractis used only by Claude and Codex, which both require the external NeMo Relay 0.7.x CLI. Hermes and Deep Agents use the separate Python package path.docs/sdk/python.mdx (1)
278-278: LGTM!examples/code_review_agent/README.md (1)
77-77: LGTM!adapters/common/src/nemo_fabric_adapters/common/utils.py (4)
8-8: LGTM!
427-451: 🩺 Stability & AvailabilityNo change needed.
relay_cli_contractrejects Relay CLI versions outside>=0.7.0,<0.8.0and returnsobservability_version=3; repository callers cannot pass version 2 to this function.> Likely an incorrect or invalid review comment.
486-490: 🎯 Functional CorrectnessNo test change is needed
The parametrized fixtures contain no observability component, and all production call sites pass
observability_versionexplicitly. The round-trip assertion remains valid.> Likely an incorrect or invalid review comment.
396-424: 🗄️ Data Integrity & IntegrationConfirm the disabled empty-endpoint representation.
NeMo Relay 0.7 uses this version-3 endpoint schema. Confirm that
opentelemetry = { enabled = false, endpoints = [] }is accepted when all legacy exporters are disabled, rather than omittingendpoints.tests/adapters/test_adapaters_common_utils.py (1)
750-750: LGTM!Also applies to: 790-824
tests/adapters/test_claude_adapter.py (1)
331-331: LGTM!Also applies to: 407-407
tests/adapters/test_codex_adapter.py (1)
815-815: LGTM!Also applies to: 843-843
tests/e2e/test_claude.py (1)
50-50: LGTM!examples/harbor/swebench/README.md (1)
34-38: 🗄️ Data Integrity & IntegrationKeep the exact
0.7.0pin. The stable release exists, andinstall.shaccepts this version format.> Likely an incorrect or invalid review comment.
| Claude and Codex streaming use the NeMo Relay `nemo-relay` gateway CLI and require a | ||
| stream-sink-capable release from `0.6.0` up to, but not including, `0.7.0`. Follow | ||
| release from `0.7.0` up to, but not including, `0.8.0`. At launch, NeMo Fabric | ||
| translates its public observability model to Relay's version 3 configuration. Follow | ||
| the [NeMo Relay CLI installation instructions](../getting-started/install.mdx#install-nemo-relay) | ||
| to provision it. Hermes Agent and Deep Agents use their in-process NeMo Relay | ||
| integrations. |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Find remaining NeMo Relay 0.6 references and check the install page range.
set -euo pipefail
# Locate the install page and print its Relay section.
fd -t f 'install.mdx' docs | while IFS= read -r f; do
echo "== $f =="
rg -n -C 5 'nemo-relay|NEMO_RELAY_VERSION|0\.6|0\.7' "$f" || true
done
# Any lingering 0.6.x Relay CLI references across docs, examples, code, and manifests.
rg -n -C 2 '0\.6\.0|0\.6\.x|<0\.7' --glob '!**/*.lock' || trueRepository: NVIDIA/NeMo-Fabric
Length of output: 2029
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== docs/getting-started/install.mdx: Relay section =="
sed -n '126,186p' docs/getting-started/install.mdx
echo "== References to the install-page anchor =="
rg -n -C 2 'install\.mdx#install-nemo-relay|0\.7\.0|0\.8\.0|0\.6\.[0-9]+' \
docs examples README.md --glob '!**/*.lock' || trueRepository: NVIDIA/NeMo-Fabric
Length of output: 6660
Add the NeMo Relay CLI version range to the installation guide.
docs/getting-started/install.mdx#install-nemo-relay does not state the required 0.7.0 to <0.8.0 range. Add it so the linked installation guidance matches the adapter documentation.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/sdk/python.mdx` around lines 507 - 512, Update the NeMo Relay CLI
installation section in the install guide to explicitly require versions from
0.7.0 inclusive through below 0.8.0, matching the range documented near the
Claude and Codex streaming requirements in the SDK guide.
| Claude and Codex streaming use the NeMo Relay `nemo-relay` gateway CLI and require a | ||
| stream-sink-capable release from `0.6.0` up to, but not including, `0.7.0`. Follow | ||
| release from `0.7.0` up to, but not including, `0.8.0`. At launch, NeMo Fabric | ||
| translates its public observability model to Relay's version 3 configuration. Follow |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Use NeMo Relay instead of Relay's, and replace the vague At launch qualifier.
The rest of this page uses NeMo Relay consistently. At launch does not identify which launch.
📝 Proposed wording
-release from `0.7.0` up to, but not including, `0.8.0`. At launch, NeMo Fabric
-translates its public observability model to Relay's version 3 configuration. Follow
+release from `0.7.0` up to, but not including, `0.8.0`. When it starts the gateway,
+NeMo Fabric translates its public observability model to the NeMo Relay version 3
+configuration. FollowAs per coding guidelines: "Use the same term consistently for the same concept."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/sdk/python.mdx` at line 509, Update the sentence near “translates its
public observability model” to use “NeMo Relay” consistently instead of
“Relay’s,” and replace the vague “At launch” qualifier with wording that
identifies the specific launch or timeframe.
Source: Coding guidelines
| def test_relay_0_7_config_requires_enabled_otlp_endpoint(): | ||
| plugin_config = { | ||
| "components": [ | ||
| { | ||
| "kind": "observability", | ||
| "config": { | ||
| "version": 2, | ||
| "openinference": {"enabled": True}, | ||
| }, | ||
| } | ||
| ] | ||
| } | ||
| assert rendered == plugin_config | ||
|
|
||
| with pytest.raises( | ||
| ValueError, | ||
| match="version 3 requires an endpoint for enabled openinference export", | ||
| ): | ||
| common_utils._relay_plugin_config_for_version(plugin_config, 3) | ||
|
|
||
|
|
||
| def test_relay_0_7_config_rejects_removed_otlp_controls(): | ||
| plugin_config = { | ||
| "components": [ | ||
| { | ||
| "kind": "observability", | ||
| "config": { | ||
| "version": 2, | ||
| "opentelemetry": { | ||
| "enabled": True, | ||
| "endpoint": "http://localhost:4318/v1/traces", | ||
| "mark_projection": "tool", | ||
| }, | ||
| }, | ||
| } | ||
| ] | ||
| } | ||
|
|
||
| with pytest.raises( | ||
| ValueError, | ||
| match="cannot preserve opentelemetry fields: mark_projection", | ||
| ): | ||
| common_utils._relay_plugin_config_for_version(plugin_config, 3) |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
Parametrize the two rejection tests and add the missing unsupported-version case.
Both tests share one shape: a plugin configuration and an expected ValueError message. The observability_version != 3 branch at adapters/common/src/nemo_fabric_adapters/common/utils.py Line 430 has no coverage, and neither does the new default of 3 in write_relay_configs.
♻️ Proposed parametrized rewrite
-def test_relay_0_7_config_requires_enabled_otlp_endpoint():
- plugin_config = {
- "components": [
- {
- "kind": "observability",
- "config": {
- "version": 2,
- "openinference": {"enabled": True},
- },
- }
- ]
- }
-
- with pytest.raises(
- ValueError,
- match="version 3 requires an endpoint for enabled openinference export",
- ):
- common_utils._relay_plugin_config_for_version(plugin_config, 3)
-
-
-def test_relay_0_7_config_rejects_removed_otlp_controls():
- plugin_config = {
- "components": [
- {
- "kind": "observability",
- "config": {
- "version": 2,
- "opentelemetry": {
- "enabled": True,
- "endpoint": "http://localhost:4318/v1/traces",
- "mark_projection": "tool",
- },
- },
- }
- ]
- }
-
- with pytest.raises(
- ValueError,
- match="cannot preserve opentelemetry fields: mark_projection",
- ):
- common_utils._relay_plugin_config_for_version(plugin_config, 3)
+@pytest.mark.parametrize(
+ ("observability_config", "target_version", "expected_message"),
+ [
+ (
+ {"version": 2, "openinference": {"enabled": True}},
+ 3,
+ "version 3 requires an endpoint for enabled openinference export",
+ ),
+ (
+ {
+ "version": 2,
+ "opentelemetry": {
+ "enabled": True,
+ "endpoint": "http://localhost:4318/v1/traces",
+ "mark_projection": "tool",
+ },
+ },
+ 3,
+ "cannot preserve opentelemetry fields: mark_projection",
+ ),
+ (
+ {"version": 2},
+ 2,
+ "unsupported NeMo Relay observability config version 2",
+ ),
+ ],
+)
+def test_relay_0_7_config_rejects_invalid_observability_config(
+ observability_config, target_version, expected_message
+):
+ plugin_config = {
+ "components": [
+ {"kind": "observability", "config": observability_config}
+ ]
+ }
+
+ with pytest.raises(ValueError, match=expected_message):
+ common_utils._relay_plugin_config_for_version(
+ plugin_config, target_version
+ )As per coding guidelines: "Prefer pytest.mark.parametrize over separate tests for different input types."
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| def test_relay_0_7_config_requires_enabled_otlp_endpoint(): | |
| plugin_config = { | |
| "components": [ | |
| { | |
| "kind": "observability", | |
| "config": { | |
| "version": 2, | |
| "openinference": {"enabled": True}, | |
| }, | |
| } | |
| ] | |
| } | |
| assert rendered == plugin_config | |
| with pytest.raises( | |
| ValueError, | |
| match="version 3 requires an endpoint for enabled openinference export", | |
| ): | |
| common_utils._relay_plugin_config_for_version(plugin_config, 3) | |
| def test_relay_0_7_config_rejects_removed_otlp_controls(): | |
| plugin_config = { | |
| "components": [ | |
| { | |
| "kind": "observability", | |
| "config": { | |
| "version": 2, | |
| "opentelemetry": { | |
| "enabled": True, | |
| "endpoint": "http://localhost:4318/v1/traces", | |
| "mark_projection": "tool", | |
| }, | |
| }, | |
| } | |
| ] | |
| } | |
| with pytest.raises( | |
| ValueError, | |
| match="cannot preserve opentelemetry fields: mark_projection", | |
| ): | |
| common_utils._relay_plugin_config_for_version(plugin_config, 3) | |
| `@pytest.mark.parametrize`( | |
| ("observability_config", "target_version", "expected_message"), | |
| [ | |
| ( | |
| {"version": 2, "openinference": {"enabled": True}}, | |
| 3, | |
| "version 3 requires an endpoint for enabled openinference export", | |
| ), | |
| ( | |
| { | |
| "version": 2, | |
| "opentelemetry": { | |
| "enabled": True, | |
| "endpoint": "http://localhost:4318/v1/traces", | |
| "mark_projection": "tool", | |
| }, | |
| }, | |
| 3, | |
| "cannot preserve opentelemetry fields: mark_projection", | |
| ), | |
| ( | |
| {"version": 2}, | |
| 2, | |
| "unsupported NeMo Relay observability config version 2", | |
| ), | |
| ], | |
| ) | |
| def test_relay_0_7_config_rejects_invalid_observability_config( | |
| observability_config, target_version, expected_message | |
| ): | |
| plugin_config = { | |
| "components": [ | |
| {"kind": "observability", "config": observability_config} | |
| ] | |
| } | |
| with pytest.raises(ValueError, match=expected_message): | |
| common_utils._relay_plugin_config_for_version( | |
| plugin_config, target_version | |
| ) |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@tests/adapters/test_adapaters_common_utils.py` around lines 827 - 868,
Parametrize the two rejection cases in the test module using shared plugin
configuration and expected ValueError-message inputs, while preserving each
case’s distinct error match. Add a third parametrized case covering an
unsupported observability version (a value other than 3) through
_relay_plugin_config_for_version, and add coverage for write_relay_configs using
its default observability version of 3.
Source: Coding guidelines
Signed-off-by: Ajay Thorve <athorve@nvidia.com>
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
tests/adapters/test_adapaters_common_utils.py (1)
806-835: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winAssert that the complete input configuration remains unchanged.
The test checks selected fields and the source version. A mutation to another nested field could update
plugin_configand still allow the current assertions to pass.Deep-copy
plugin_configbefore callingwrite_relay_configs, then assert equality after the call.As per path instructions: tests should cover the behavior promised by the changed API surface.
Proposed test assertion
+ original_plugin_config = copy.deepcopy(plugin_config) + _, plugin_path = common_utils.write_relay_configs( plugin_config=plugin_config, observability_version=3, ) + assert plugin_config == original_plugin_config🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/adapters/test_adapaters_common_utils.py` around lines 806 - 835, Update the test around write_relay_configs to deep-copy plugin_config before invoking it, then assert the original plugin_config equals that copy after the call. Preserve the existing output assertions while adding this complete deep-equality check to detect mutations in any nested configuration field.Source: Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@tests/adapters/test_adapaters_common_utils.py`:
- Around line 806-835: Update the test around write_relay_configs to deep-copy
plugin_config before invoking it, then assert the original plugin_config equals
that copy after the call. Preserve the existing output assertions while adding
this complete deep-equality check to detect mutations in any nested
configuration field.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Enterprise
Run ID: 13e4b1e5-8de7-4294-b1aa-4959886c719c
📒 Files selected for processing (2)
adapters/common/src/nemo_fabric_adapters/common/utils.pytests/adapters/test_adapaters_common_utils.py
📜 Review details
⏰ Context from checks skipped due to timeout. (19)
- GitHub Check: Preview docs
- GitHub Check: Test (Python 3.13, linux-arm64)
- GitHub Check: Test (Python 3.12, linux-amd64)
- GitHub Check: Test (Python 3.11, windows-amd64)
- GitHub Check: Test (Python 3.12, windows-amd64)
- GitHub Check: Test (Python 3.11, linux-amd64)
- GitHub Check: Test (Python 3.11, macos-arm64)
- GitHub Check: Test (Python 3.13, macos-arm64)
- GitHub Check: Test (Python 3.12, macos-arm64)
- GitHub Check: Test (Python 3.13, linux-amd64)
- GitHub Check: Test (Python 3.14, windows-amd64)
- GitHub Check: Test (Python 3.14, linux-arm64)
- GitHub Check: Test (Python 3.14, linux-amd64)
- GitHub Check: Test (Python 3.14, macos-arm64)
- GitHub Check: Test (Python 3.11, linux-arm64)
- GitHub Check: Test (Python 3.13, windows-amd64)
- GitHub Check: Test (Python 3.12, linux-arm64)
- GitHub Check: Pre-commit
- GitHub Check: Test (arm64)
🧰 Additional context used
📓 Path-based instructions (17)
**/*.{rs,py,pyi,json,yaml,yml}
📄 CodeRabbit inference engine (.agents/skills/contribute-api/SKILL.md)
Determine and update every affected public surface, including the CLI, PyO3 bindings, Python SDK, type stubs, schemas, and adapter contract, so they remain in parity.
Files:
adapters/common/src/nemo_fabric_adapters/common/utils.pytests/adapters/test_adapaters_common_utils.py
**/*
📄 CodeRabbit inference engine (.agents/skills/karpathy-guidelines/SKILL.md)
**/*: Before implementing, explicitly state assumptions, surface ambiguity and tradeoffs, present multiple interpretations when relevant, and ask for clarification rather than silently deciding or proceeding when requirements are unclear.
Prefer the minimum code needed to solve the requested problem: avoid speculative features, unnecessary abstractions, unrequested flexibility, and handling of impossible scenarios; simplify overcomplicated solutions.
When editing existing code, make surgical changes only: do not modify unrelated code, comments, formatting, or pre-existing dead code; match the existing style, and remove only unused imports, variables, or functions introduced by your changes.
Define verifiable success criteria for each task, such as writing regression tests for bugs and invalid-input tests for validation, then verify the implementation against those criteria. For multi-step work, state a brief plan with a verification check for each step.
**/*: Always spellNVIDIAin all caps; do not useNvidia,nvidia,nVidia,nVIDIA, orNV.
Usean NVIDIAbefore a noun, because the name begins with an “en” sound.
Do not add a registered trademark symbol afterNVIDIAwhen referring to the company; use trademark symbols with product names only when required by the document type or legal guidance.
Verify official capitalization, spacing, hyphenation, and spelling for NVIDIA and third-party product names; do not rewrite official product names for grammar or title-case rules.
Precede NVIDIA product names withNVIDIAon first mention when natural and accurate, and link the first mention when the destination helps the reader.
On first use, include the company name and full model qualifier when it helps identify the model; preserve official capitalization and punctuation, and use shorter family names only after establishing the full name.
For learning-oriented and developer content, do not force trademark symbols unless explicitly required; for press, ...
Files:
adapters/common/src/nemo_fabric_adapters/common/utils.pytests/adapters/test_adapaters_common_utils.py
**/*.{rs,py}
📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)
For native binding changes, run
cargo check -p fabric-python --locked.Use
snake_casefor functions and variables; usePascalCasefor Rust types and Python classes.
Files:
adapters/common/src/nemo_fabric_adapters/common/utils.pytests/adapters/test_adapaters_common_utils.py
**/*.{py,pyi}
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
If Python code or a Python-facing adapter changes, run
just test-python.In Python SDK, adapters, examples, and tests, follow the existing style, use type annotations for public APIs, and keep native binding declarations synchronized with their Rust implementations.
Files:
adapters/common/src/nemo_fabric_adapters/common/utils.pytests/adapters/test_adapaters_common_utils.py
**/*.{rs,py,pyi}
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
**/*.{rs,py,pyi}: If public configuration types change, confirm schema snapshot tests injust test-rustpass and review generated schema diffs.
For schema or public contract changes, run both language suites and review changes underschemas/and generated API references.
Files:
adapters/common/src/nemo_fabric_adapters/common/utils.pytests/adapters/test_adapaters_common_utils.py
**/*.{py,pyi,rs}
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
For Python SDK or PyO3 binding changes, use
python-tests, run focused pytest tests first, thenjust test-python; rebuild withjust build-pythonwhen native code or packaging changes.Public contract changes must keep native Python binding declarations synchronized with their Rust implementations.
Files:
adapters/common/src/nemo_fabric_adapters/common/utils.pytests/adapters/test_adapaters_common_utils.py
**/*.{rs,py,toml}
📄 CodeRabbit inference engine (.agents/skills/update-project-version/SKILL.md)
When editing version helpers, verify every
nemo-fabric-*workspace package through Cargo metadata and reject a static version inpython/pyproject.toml.
Files:
adapters/common/src/nemo_fabric_adapters/common/utils.pytests/adapters/test_adapaters_common_utils.py
**/*.{toml,rs,py}
📄 CodeRabbit inference engine (.agents/skills/update-project-version/SKILL.md)
Avoid blind repository-wide replacement of version-like strings; distinguish package-version references from examples and unrelated dependency versions.
Files:
adapters/common/src/nemo_fabric_adapters/common/utils.pytests/adapters/test_adapaters_common_utils.py
**/*.{md,mdx,yml,py,rs,sh}
📄 CodeRabbit inference engine (.agents/skills/review-doc-style/SKILL.md)
Keep documentation aligned with current NeMo Fabric behavior, repository layout, entry points, commands, package names, APIs, bindings, and support claims.
Files:
adapters/common/src/nemo_fabric_adapters/common/utils.pytests/adapters/test_adapaters_common_utils.py
adapters/**/*
📄 CodeRabbit inference engine (.agents/skills/contribute-adapter/SKILL.md)
Place repository adapters under
adapters/<name>, define their install extra and packaged descriptor, select the matchingharness.resolutionstrategy, and document repository orbase_dirdescriptor discovery.
Files:
adapters/common/src/nemo_fabric_adapters/common/utils.py
adapters/**/*.{py,js,ts,java,go,rs}
📄 CodeRabbit inference engine (.agents/skills/contribute-adapter/SKILL.md)
adapters/**/*.{py,js,ts,java,go,rs}: Use the existing Fabricpythonorprocessrunner and normalized request/result contracts. Reuseadapters/common/only when its contract fits; do not add a runner or abstraction for one adapter.
For adapters consuming normalized configuration or runtime context, use the complete Fabric invocation and treatconfig,capability_plan,telemetry_plan, andruntime_contextas authoritative. Reserveharness.settingsfor harness-specific behavior.
Apply configuration precedence in this order: normalized config; Fabric-resolved plans and runtime context; harness-specific settings; descriptor and adapter defaults. Reject conflicting duplicate declarations or unsupported behavior with actionable field-specific errors; never silently drop configuration.
Run dependency and authentication preflight before invoking the harness. Declare fixed dependencies in descriptor requirements, validate versions, hooks, and credentials, and never expose credential values in output, errors, events, logs, or fixtures.
Forward only required system variables, selected credential variables, telemetry variables, and documented harness-specific environment; never forward or log unrelated environment values.
Run one local adapter host per Fabric runtime for orderedstart→invoke*→stop. Emit one JSON lifecycle response per request on stdout and diagnostics on stderr; treat early exit as a host crash.
Return harness-level invoke failures in a successful lifecycle response withresponse: null,failed: true, and structurederrorcontainingcode,message,retryable, and optionalmetadata.
Do not emit NeMo Relay stream records on adapter stdout. Relay records are sent out of band through the SDK-owned NDJSON ATOF endpoint; the adapter must return exactly one terminal lifecycle response.
Scope workspace, generated configuration, state, sessions, and artifacts to the resolved runtime context. Write artifacts only within the resolved r...
Files:
adapters/common/src/nemo_fabric_adapters/common/utils.py
{adapters/**,examples/**}
⚙️ CodeRabbit configuration file
{adapters/**,examples/**}: Review adapter and example changes for command correctness, config/schema consistency, artifact handling, and compatibility with the public NeMo Fabric contracts.
Files:
adapters/common/src/nemo_fabric_adapters/common/utils.py
tests/adapters/**/*.py
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
tests/adapters/**/*.py: If an adapter or integration changes, run its focused tests.
For adapter behavior changes, run focused adapter tests undertests/adapters, then runjust test-python.
Files:
tests/adapters/test_adapaters_common_utils.py
tests/**/*.{rs,py}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
When adding functionality, include tests in the corresponding Rust crate or the relevant area under
tests/.
Files:
tests/adapters/test_adapaters_common_utils.py
tests/**/*.py
📄 CodeRabbit inference engine (.agents/skills/python-tests/SKILL.md)
tests/**/*.py: Use pytest to run Python tests.
Do not add@pytest.mark.asyncioto tests; async tests are automatically detected by the async runner.
Do not add-> Nonereturn type annotations to test functions.
When mocking a class, useunittest.mock.MagicMockorAsyncMock, using thespecargument when necessary, rather than defining a new class.
Prefix mocked class names withmock, notfake.
Prefer pytest fixtures over helper methods.
If a fixture is needed in multiple test files, define it once inconftest.pyrather than repeating it.
Define fixtures using@pytest.fixture(name="<fixture_name>"[, scope="<scope>"])and a<fixture_name>_fixturefunction; specifyscopeonly when it is notfunction.
Preferpytest.mark.parametrizeover separate tests for different input types.
Use@pytest.mark.usefixtureswhen a fixture is needed but its returned value is unused or it returns no value.
Avoid defensive programming in tests; access expected values directly so missing data raises a clear failure, such as usingresults["data"]instead ofresults.get("data").
When adapter installation metadata changes, packaging metadata tests must directly assert that the root project depends unconditionally on the exact-versionnemo-fabric-runtimedistribution.
Packaging metadata tests must verify that each root harness extra delegates to the matching version of the leaf adapter'sharnessextra.
Packaging metadata tests must verify that bare leaf dependencies remain adapter-owned and that the rootadapter-testsdependency group installs each leaf through itsharnessextra.
Packaging metadata tests must verify that every leaf providesfull; only adapters importing NeMo Relay Python APIs providerelay, while adapters using an external Relay executable havefullequal toharness.
Files:
tests/adapters/test_adapaters_common_utils.py
tests/adapters/test_*.py
📄 CodeRabbit inference engine (.agents/skills/contribute-adapter/SKILL.md)
tests/adapters/test_*.py: Add focused tests for descriptor shape and exact capabilities, positive normalized-surface mappings, rejection of unsupported values and unenforceable policies, result normalization without secret leakage, one-shot execution, continuation, runtime isolation, and the packaged subprocess entry point.
Provide a credential-free fixture coveringplan,doctor, andrun; keep credential-dependent live-harness tests opt-in while retaining a deterministic CI end-to-end path.
Files:
tests/adapters/test_adapaters_common_utils.py
{tests/**,python/tests/**}
⚙️ CodeRabbit configuration file
{tests/**,python/tests/**}: Tests should cover the behavior promised by the changed API surface, including error paths, lifecycle cleanup, and SDK/native parity where relevant.
Files:
tests/adapters/test_adapaters_common_utils.py
🔇 Additional comments (7)
tests/adapters/test_adapaters_common_utils.py (3)
801-804: 📐 Maintainability & Code QualityCover the changed version contract.
This test passes
observability_version=3, so it does not exercise the new default. The rejection cases also need a non-3 target to exercise the guard in_relay_plugin_config_for_version.Omit the argument for the default case. Add the unsupported-version case in the same parametrized table.
As per coding guidelines: “Prefer
pytest.mark.parametrizeover separate tests for different input types.”
As per path instructions: tests should cover the behavior promised by the changed API surface, including error paths.Also applies to: 838-879
Sources: Coding guidelines, Path instructions
750-752: 🗄️ Data Integrity & IntegrationMake the Relay 0.7 acceptance claim executable.
This test checks TOML values with
tomllib. It does not validate the file with the external Relay executable.The supplied context lists
nemo-relay0.6.0. The Python package and CLI are separate install surfaces. Official documentation is version-sensitive: released documentation shows observability version 2, while the version-3 migration documentation definesfullandopeninferenceendpoints. Confirm that an end-to-end test pins external Relay 0.7.x. Keep the unchanged Python dependency path separate. (github.com)Source: MCP tools
753-800: LGTM!adapters/common/src/nemo_fabric_adapters/common/utils.py (4)
8-8: LGTM!Also applies to: 514-519
427-461: LGTM!Also applies to: 465-485
492-492: 🎯 Functional CorrectnessNo in-repository caller requests observability version 2.
All callers use the version-3 contract returned by
relay_cli_contract; no version-2 reference exists.> Likely an incorrect or invalid review comment.
462-464: 🎯 Functional CorrectnessKeep explicit
Nonesections as disabled exports.
opentelemetryandopeninferenceacceptnullin the public schema and Python model. TreatingNoneas absent is therefore valid behavior.> Likely an incorrect or invalid review comment.
#### Overview Fix the Relay artifact lifecycle race for both Codex and Claude without upgrading Relay or changing the observability schema. Fabric now waits for the configured local ATIF exporter to finish before it snapshots relay_artifacts, so a successful invocation cannot be returned while its trajectory is still in Relay's asynchronous subscriber queue. The readiness logic is shared in adapters/common. The existing nemo-relay>=0.6.0,<0.7 contract remains unchanged, so this fix is suitable for the release/0.1 line and supersedes the Relay 0.7 dependency-upgrade mitigation in #180. This branch also sets the release version to 0.1.1 across the Rust workspace, all seven Python distributions, exact internal dependency pins, and lockfiles. #### Details - Snapshot cheap filesystem fingerprints (device, inode, size, and nanosecond mtime) for runtime-scoped ATIF files before an invocation. - After a successful Codex or Claude turn, inspect only new or metadata-changed paths and return as soon as one contains a complete JSON object. This supports a new file, atomic replacement, overwrite, and append. - Do not hash, read, or parse unchanged artifacts from prior turns. - Keep JSON parsing as the readiness condition because Relay writes directly to the final path; file existence or timestamps do not prove the write is complete. Metadata selects candidates, while successful JSON parsing proves readiness. - Use a hard five-second deadline instead of a fixed sleep. A timeout returns codex_relay_atif_timeout or claude_relay_atif_timeout and makes the persistent runtime unavailable, preventing a late artifact from being attributed to a later turn. - Return an empty relay_artifacts list on timeout and bypass artifact rescanning on the later runtime-unavailable response. - Skip the local-file wait when ATIF uses non-empty remote storage, because Relay does not produce a local ATIF in that mode. - Preserve ATOF collection, streaming, persistent SDK sessions, and the runtime-owned Relay gateway. Codex and Claude need this guard because both collect artifacts immediately after an SDK terminal result while Relay hook events are dispatched asynchronously. Hermes already flushes subscribers before collection, and Deep Agents collects after leaving its Relay plugin context, so those adapters are unchanged. Runtime-scoped output directories keep parallel evaluator sessions isolated. The wait is condition-based and normally adds only the time Relay needs to finish the file. #### Release packaging - Ran just set-version 0.1.1. - Updated Cargo and Python package versions plus exact internal 0.1.1 pins. - Regenerated the Python lockfiles with the CI-pinned uv 0.9.22. Dependency versions are unchanged; the locks add newly published Relay 0.6 source and musllinux artifact records. - Regenerated Python attributions; the only generated attribution change is the aiohttp license-file path. - No public configuration or API contract changed. #### Validation - just test-python — 582 passed, 15 skipped. - just test-rust — 68 passed. - cargo check --workspace --locked — passed. - cargo fmt --all -- --check — passed. - just build-python — passed for all seven 0.1.1 distributions. - just wheels — built all seven wheels; wheel metadata and exact internal 0.1.1 pins were verified. - Pre-commit on all files — passed, including Ruff, GitHub Actions lint, Cargo/uv lock freshness, generated attributions, and dependency-license checks. - Real Relay 0.6 Codex and Claude E2E — passed one-shot artifact semantics and persistent two-turn streaming runtimes. - Platform Codex and Claude matrix at p=1,3,5,10 — 80/80 total trials completed with isolated runtime-scoped ATIF directories, valid ATIF-v1.7 trajectories, non-empty steps, and zero contract failures. - Exact final-head Platform regression at p=10 — Codex 10/10 and Claude 10/10, with 20 distinct runtime-scoped ATIF directories and zero failures. - Exact final-head non-target Platform regression at p=5 — Deep Agents 5/5 and Hermes 5/5 against Relay 0.6, with ten distinct runtime-scoped directories, valid trajectories and promoted trace evidence, and zero failures. Documentation is unchanged because public configuration and dependency contracts are unchanged. There are no breaking changes. #### Where should the reviewer start? Start with adapters/common/src/nemo_fabric_adapters/common/relay_artifacts.py, then the calls from CodexRuntime.invoke() and ClaudeRuntime.invoke(). The focused tests cover delayed and partial writes, unchanged-path exclusion, changed-path detection, remote-only configuration, the hard timeout, no-rescan timeout behavior, unusable-runtime behavior, and parallel runtime-directory isolation. #### Related Issues: (use one of the action keywords Closes / Fixes / Resolves / Relates to) - Relates to #180 and the NeMo Platform 0.4 ATIF release blocker. - [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. ## Summary by CodeRabbit * **New Features** * Added reliable Relay ATIF artifact tracking for supported Codex and Claude sessions. * Turns now wait for newly generated, valid artifacts before completing. * Added a five-second timeout for artifact finalization. * **Bug Fixes** * Prevented stale or incomplete artifacts from being treated as finalized. * Improved isolation when multiple sessions await artifact generation. * Timed-out runtimes are marked unavailable to prevent subsequent use. * Artifact finalization timeouts now return clear, non-retryable errors. * Runtime failures now report a clear, generic error message. Authors: - Ajay Thorve (https://github.com/AjayThorve) Approvers: - Anuradha Karuppiah (https://github.com/AnuradhaKaruppiah) - David Gardner (https://github.com/dagardner-nv) URL: #181
Overview
This hotfix moves the external NeMo Relay CLI contract used by the Codex and
Claude adapters from
>=0.6.0,<0.7.0to>=0.7.0,<0.8.0.Relay 0.6 reproduced the Platform 0.4 blocker: successful Codex turns returned
ATOF before the corresponding ATIF was visible to Fabric, so
relay_atifandthe Evaluator
tracedescriptor were omitted. The released Relay 0.7.0 binaryreturned both artifacts in the same live test and under parallel persistent
runtime load. Requiring 0.7 removes the known-bad runtime combination without
adding a polling loop or process-global session state.
Relay 0.7 also requires observability configuration version 3. Fabric now
renders its stable public configuration model into that contract at gateway
launch:
OpenTelemetry endpoints.
before Relay starts instead of being silently discarded.
The separately imported
nemo-relayPython dependency used by Deep Agents andHermes remains unchanged; this PR only changes the external CLI contract owned
by the coding-agent adapters.
Breaking change: Relay-enabled Codex and Claude runtimes must install the
external NeMo Relay 0.7.x CLI.
Where should the reviewer start?
Start with
adapters/common/src/nemo_fabric_adapters/common/relay_gateway.pyfor the CLIversion boundary, then
adapters/common/src/nemo_fabric_adapters/common/utils.pyfor the isolatedversion-2 to version-3 configuration translation. The regression assertions
are in
tests/adapters/test_adapters_common_relay_gateway.pyandtests/adapters/test_adapaters_common_utils.py.Validation:
uv run --no-sync pytest -q— 576 passed, 15 skipped.uv run --no-sync pre-commit run --all-files— passed.just docs— passed; only the expected unauthenticated Fern redirect warning.execution.
persistent runtimes with two turns each all returned ATOF and ATIF with the
correct per-session marker.
sinks, ATIF, full OpenTelemetry, and OpenInference configuration.
Related Issues: (use one of the action keywords Closes / Fixes / Resolves / Relates to)
Relates to the NeMo Platform 0.4 Codex ATIF release blocker.
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.
Summary by CodeRabbit
New Features
Documentation