- name
- maintain-dynamic-plugins
- description
- Change NeMo Relay dynamic plugin loaders, manifests, native ABI, gRPC worker protocol, or Python worker SDK. Do not use for ordinary built-in plugin configuration.
- license
- Apache-2.0
# Maintain Dynamic Plugins
Use this skill for `plugin.kind = "rust_dynamic"`, `plugin.kind = "worker"`,
`nemo-relay-plugin`, `nemo-relay-worker`, `nemo-relay-worker-proto`,
`nemo-relay-types`, and the Python `nemo-relay-plugin` package.
## Rules
- Keep the stable boundary explicit: native plugins cross a C ABI; worker
plugins cross `grpc-v1`.
- Do not pass Rust runtime types, trait objects, futures, or allocator-owned
strings across the native dynamic-library boundary.
- Typed native middleware futures run on the SDK-owned Tokio executor. Keep
subscribers synchronous and preserve raw synchronous ABI registrations.
- Define closed worker transport structures in protobuf when generated clients
must enforce their fields. Keep open application payloads lossless by using
`JsonValue` or `JsonEnvelope` rather than `google.protobuf.Value`.
- Keep `relay-plugin.toml` dynamic records separate from generic runtime
components. Enabled dynamic records may synthesize internal component specs;
disabled records stay inspectable but unloaded.
- Relay 0.8 establishes the native API 1 and `grpc-v1` canonical
`ToolExecutionResult` baseline. Require every dynamic plugin to rebuild and
declare a `compat.relay` range that excludes versions before 0.8. Recommend
`>=0.8.0,<1.0`; open-ended or narrower 0.8-or-newer ranges are valid.
- Treat `compat.relay` as the plugin author's compatibility assertion, not
proof that an artifact was rebuilt. Do not add a legacy raw-result adapter.
- Relay 0.8 retains the `grpc-v1` identifier and
`nemo.relay.worker.v1` package while changing the tool-result protobuf types;
every worker must regenerate its bindings and rebuild. Native ABI v4 permits
append-only host-table extensions guarded by `struct_size`; existing fields
must remain frozen at their original offsets. Incompatible native JSON,
reordered or replaced native fields, or incompatible worker protobuf changes
must bump `native_api` or `worker_protocol`.
- Do not add tests under `src`; Rust tests belong in crate `tests/` trees and
Python SDK tests belong under `python/tests`.
- Native and worker plugins are trusted extensions. Document that native plugins
are in-process and unsandboxed; worker plugins provide process isolation but
not a security sandbox.
## Checklist
- [ ] Manifest validation covers kind, compatibility, load contract, integrity,
capability mismatch, and disabled-plugin behavior.
- [ ] Native loader keeps libraries alive until registered callbacks are cleared
and deregisters plugin kinds before unload.
- [ ] Worker activation covers process launch, token auth, handshake, validation,
declarative registration, proxy rollback, cancellation, and shutdown.
- [ ] Rust and Python SDKs expose every supported registration surface.
- [ ] Runtime helpers cover marks, scopes, continuations, and isolated scope
stacks.
- [ ] `plugins list`, `plugins inspect`, and `plugins validate` report lifecycle
and compatibility status without leaking secret config.
- [ ] Top-level `doctor` reports resolved dynamic plugin and host configuration
status.
- [ ] When detailed dynamic plugin guides exist, they keep Rust native, Python
worker, and `grpc-v1` protocol details on separate pages.
- [ ] `justfile`, Codecov, and CI package/test workflows include new plugin
crates and packages.
## Validation
Choose checks by the changed layer:
- Manifest or shared types: test the owning Rust crate.
- Native loader or ABI: prepare plugin fixtures and run the focused native
plugin integration test.
- Worker protocol or host: test the worker crates and regenerate or test the
Python worker SDK only when its protocol surface changes.
- Shared runtime behavior: run the Rust suite and only binding suites whose
observable plugin behavior changes.
- Documentation or packaging: run their targeted checks only when changed.
Canonical surface suites prepare plugin fixtures. Before a raw focused native
or worker integration test, run `just build-test-plugin-fixtures`; never compile
fixtures inside an individual test case.
## References
- `crates/core/src/plugin/dynamic/`
- `crates/plugin`
- `crates/worker`
- `crates/worker-proto`
- `crates/types`
- `python/plugin`
- `examples/rust-native-plugin`
- `docs/build-plugins`
- `examples/python-grpc-worker-plugin`
Ver en GitHub