NeMo Relay 0.7.0
·
313 commits
to main
since this release
Immutable
release. Only release title and notes can be modified.
We are proud to release NeMo Relay 0.7.0!
Notable New Features:
- 🛡️ Codec-aware sanitization and PII protection: LLM sanitizers receive the active per-call codec across Rust, Python, Node.js, native plugins, and workers, enabling provider-correct redaction for mixed OpenAI Chat, OpenAI Responses, Anthropic Messages, runtime, and opaque codec traffic.
- 📊 Unified OpenTelemetry export: one typed configuration now supports independent
full,gen_ai, andopeninferenceendpoints, standardized GenAI semantic conventions, endpoint-local credentials, and multi-endpoint fan-out. - ⚡ Asynchronous middleware: Rust middleware can await work directly, while Python callbacks may return awaitables and Node.js callbacks may return Promises. Scope and mark publication remains synchronous at the API boundary and is delivered through an ordered background queue.
- 🔀 Cross-boundary context propagation: Relay context can be carried between processes and runtimes, and Python applications can explicitly fork task-local scope stacks for concurrent
asynciowork. - 💾 Opt-in exact-match LLM response caching: the Adaptive plugin can serve eligible repeated calls from in-memory or Redis-backed caches without invoking the provider. Caching remains disabled unless explicitly configured.
- 🔧 Configuration, packaging, and operations: a structured
nemo-relay config editworkflow, consistent layered configuration precedence, size-based operational-log rotation, environment-driven binding logging, offlinedoctorprobes, package size reduction, and PyPI-packaged CLI binaries improve deployment and diagnostics.
Breaking Changes:
- Middleware callback migration: Rust middleware callbacks now return futures. Native plugins must be rebuilt against ABI v3, and native and worker plugins must be rebuilt with the matching 0.7 SDK and protocol definitions. Python and Node.js synchronous callbacks remain supported.
- LLM sanitizer contract: request and response sanitizers now use
(payload, directional_context) -> optional payload. ReturningNone,null, orundefinedomits the governed observability payload; there is no one-argument compatibility adapter. - Observability configuration version 3: migrate standalone OpenTelemetry and OpenInference configuration to typed
opentelemetry.endpoints. Standalone OpenInference subscriber APIs and theotelandopeninferenceCargo features are removed. - Configuration and Rust source compatibility: top-level component lists and observability destination lists now concatenate across layers with higher-precedence entries first. Exhaustive
FlowErrormatches must also handle the new callback-exception variant. - Switchyard deprecation: the experimental Relay-owned Switchyard plugin remains supported in 0.7 but is deprecated ahead of removal and replacement in 0.8.
Non-Exhaustive Fixes:
- Privacy and enforcement safety: redact known LLM credential headers, reject malformed PII target paths, fail closed on sanitizer errors, and make generated coding-agent enforcement hooks fail closed when Relay cannot start, authenticate, evaluate, or deliver a response.
- Observability correctness: prefer response-side model attribution, avoid duplicate ATIF continuation steps, export system prompts consistently, preserve callback exception details, and map structured failures to useful OpenTelemetry error types.
- Exporter reliability: detect colliding or equivalent OTLP destinations, resolve bare OTLP/HTTP trace endpoints, report dropped spans, validate attribute mappings, and make failed ATIF remote deliveries visible, drainable, and recoverable.
- Configuration and diagnostics: preserve explicit editor targets, apply configuration layers consistently, prevent disabled or inherited plugin configuration from masking programmatic settings, report logging errors, and expose effective upstream authentication presence without leaking credentials.
- Python and Node.js reliability: preserve Node asynchronous context and flush semantics, isolate subscriber callback failures, make Python plugin teardown safe inside
asyncio, report cancelled scopes as errors, and avoid completion callbacks targeting closed event loops. - Gateway resilience: preserve streaming provider error responses and make transparent-gateway shutdown bounded and interruptible.
What's Changed
💥 Breaking Changes
- feat(sanitizers)!: expose per-call codec capabilities by @willkill07 in #546
- feat(observability)!: unify OpenTelemetry exporters by @willkill07 in #556
- feat(middleware)!: make middleware async across primary bindings by @willkill07 in #571
✨ New Features
- feat(observability): route ATIF files with scope metadata by @cypres in #505
- feat: add size-based operational log rotation by @ericevans-nv in #555
- feat: add cross-boundary Relay propagation by @willkill07 in #562
- feat: add structured config editor by @willkill07 in #565
- feat: package CLI for PyPI and npm by @willkill07 in #569
- feat: queue scope and mark event publication by @willkill07 in #570
- feat: add asyncio scope context forking by @willkill07 in #589
- feat: add opt-in exact-match caching for LLM responses by @zhongxuanwang-nv in #404
- feat: initialize binding logging from environment by @willkill07 in #691
⚡ Improvements
- refactor: enforce cognitive complexity threshold by @willkill07 in #636
🐛 Bug Fixes
- fix: prefer response model in observability exporters by @mnajafian-nv in #543
- fix: emit OpenInference system prompts as input messages by @mnajafian-nv in #542
- fix: avoid duplicate ATIF user steps on continuations by @mnajafian-nv in #545
- fix: align ATIF model fallback with OpenTelemetry and OpenInference by @mnajafian-nv in #547
- fix: redact known LLM credential headers in core by @willkill07 in #563
- fix: reject malformed PII target paths by @afourniernv in #561
- fix: make doctor report invalid explicit config by @willkill07 in #566
- fix: preserve streaming provider error responses by @bk-nvidia in #577
- fix: allow interrupting transparent gateway shutdown by @bk-nvidia in #579
- fix: bound transparent gateway shutdown by @bk-nvidia in #578
- fix: validate OTLP attribute mappings in plugin config by @willkill07 in #580
- fix: preserve explicit configuration editor targets by @bbednarski9 in #583
- fix: layer Relay configuration by priority by @bbednarski9 in #584
- fix(node): preserve async context and flush callbacks by @willkill07 in #593
- fix(observability): reject invisible OTLP attribute mappings by @willkill07 in #608
- fix: make Python plugin teardown asyncio-safe by @willkill07 in #605
- fix: report cancelled Python scopes as errors by @mnajafian-nv in #620
- fix: fail closed on sanitizer callback errors by @willkill07 in #607
- fix: default operational logging to error by @willkill07 in #624
- fix: prevent plugin config masking by @willkill07 in #626
- fix: map FlowError to OpenTelemetry error types by @yczhang-nv in #612
- fix: warn when OpenTelemetry spans are dropped by @willkill07 in #630
- fix: address runtime and tooling findings by @willkill07 in #633
- fix: resolve bare OTLP HTTP trace endpoints by @ericevans-nv in #652
- fix: honor programmatic component enablement by @bbednarski9 in #644
- fix: reject invalid upstream shared config keys by @mnajafian-nv in #657
- fix(node): isolate subscriber callback failures by @willkill07 in #654
- fix: reject colliding typed OTLP destinations by @willkill07 in #653
- fix: report logging config errors in doctor by @ericevans-nv in #662
- fix: expose effective upstream auth presence in CLI diagnostics by @mnajafian-nv in #660
- fix(plugin): report inherited configuration files by @bbednarski9 in #646
- fix: skip disabled plugin configuration layers by @willkill07 in #668
- fix: recover failed ATIF remote deliveries by @willkill07 in #665
- fix(python): avoid closed loop completion callbacks by @willkill07 in #676
- fix: add offline mode to doctor probes by @mnajafian-nv in #670
- fix(python): preserve panic settlement after loop shutdown fix by @willkill07 in #682
- fix: report dropped OpenTelemetry spans by @willkill07 in #686
- fix: canonicalize OpenTelemetry destinations by @willkill07 in #693
- fix: stamp CLI release version before packaging by @willkill07 in #689
- fix: fail closed generated enforcement hooks by @willkill07 in #692
- fix: preserve callback error details in traces by @willkill07 in #688
- fix: surface ATIF delivery failures consistently by @willkill07 in #687
- fix(python): load dynamic plugin specs from TOML by @bbednarski9 in #694
✅ Tests
- test: avoid interactive plugin editor in dispatch test by @ericevans-nv in #467
- test: tolerate OTLP collector read timeouts by @willkill07 in #585
- test: raise Rust and binding coverage by @willkill07 in #634
- test(cli): raise component coverage above 92 percent by @willkill07 in #635
- test: stabilize terminal job-control coverage by @willkill07 in #680
🧰 Maintenance
- chore: prepare 0.6 code freeze by @willkill07 in #461
- chore: clear release notes and migration guide for 0.7 by @willkill07 in #544
- chore: pin
cargo-aboutand excludenemo-relay-pythonfrom generic workspace build by @willkill07 in #582 - ci: resolve
tyscript imports by @willkill07 in #588 - ci: package musllinux artifacts by @willkill07 in #591
- ci: publish local npm archives by path by @willkill07 in #599
- ci: publish musl npm packages to Artifactory by @willkill07 in #602
- ci: publish Python source distributions by @willkill07 in #642
- chore: narrow Chrono features for shared types by @bbednarski9 in #678
- chore: remove npm CLI packaging by @willkill07 in #690
- chore: reduce release artifact sizes by @willkill07 in #713
📝 Documentation Updates
- docs: fix generated API reference redirects by @willkill07 in #460
- docs: migrate ATOF core specification by @bbednarski9 in #568
- docs: clarify sanitizer delivery contract by @willkill07 in #587
- docs(skills): update typed OpenTelemetry guidance by @willkill07 in #557
- docs: update Nemotron integration examples by @willkill07 in #596
- docs: document the opt-in exact-match LLM response cache by @zhongxuanwang-nv in #405
- docs: clarify rootless propagation trace semantics by @bbednarski9 in #604
- docs: clarify middleware callback error semantics by @yczhang-nv in #613
- docs: document Linux libc variants by @bbednarski9 in #616
- docs: improve runtime guidance and visual accessibility by @ericevans-nv in #619
- docs(observability): clarify OTLP batch and endpoint capacity by @zhongxuanwang-nv in #606
- docs: fix fork scope stack example result path by @pasmud in #641
- docs: deprecate Switchyard plugin by @bbednarski9 in #700
- docs: finalize 0.7 release documentation by @willkill07 in #715
New Contributors
- @bk-nvidia made their first contribution in #577
Full Changelog: 0.6.0...0.7.0