fix: Fix LangChain input serialization in callback handler and fix deadlock in plugin context manager#208
Conversation
…_outputs to _prepare_lc_payloads Signed-off-by: David Gardner <dagardner@nvidia.com>
… appears to be a gil deadlock when calling clear() Signed-off-by: David Gardner <dagardner@nvidia.com>
Signed-off-by: David Gardner <dagardner@nvidia.com>
WalkthroughRefactors LangChain payload serialization into ChangesLangChain serialization refactoring
Plugin lifecycle management enhancement
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Important Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional. ❌ Failed checks (1 error, 1 inconclusive)
✅ Passed checks (3 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Signed-off-by: David Gardner <dagardner@nvidia.com>
…-ctx-gil Signed-off-by: David Gardner <dagardner@nvidia.com>
There was a problem hiding this comment.
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 `@python/nemo_relay/integrations/langchain/_serialization.py`:
- Around line 307-358: Rename the misspelled parameter pyaload to payload in the
function _prepare_lc_payloads and update every internal reference and its type
annotation accordingly (e.g., replace pyaload.items(), pyaload.graph,
pyaload.arg, etc. with payload.*). Keep the function logic identical and ensure
recursive calls use _prepare_lc_payloads(payload) so signature and docstring are
consistent; also search for any internal or nearby callers in the module that
pass by keyword to this function and update them if they used the old name.
In `@python/nemo_relay/plugin.py`:
- Line 336: Change the plugin function signature to make clear_on_exit
keyword-only by updating async def plugin(config: PluginConfig | JsonObject,
clear_on_exit: bool = True) -> AsyncIterator[ConfigReport]: to async def
plugin(config: PluginConfig | JsonObject, *, clear_on_exit: bool = True) ->
AsyncIterator[ConfigReport]: in python/nemo_relay/plugin.py, and update the type
stub in python/nemo_relay/plugin.pyi to def plugin(config: PluginConfig |
JsonObject, *, clear_on_exit: bool = True) -> AsyncContextManager[ConfigReport]:
...; also scan and adjust any call sites that pass clear_on_exit positionally to
use the keyword form.
🪄 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: e4002412-8cfe-4317-8ecb-ae9f4391fbc7
📒 Files selected for processing (4)
python/nemo_relay/integrations/langchain/_serialization.pypython/nemo_relay/integrations/langchain/callbacks.pypython/nemo_relay/integrations/langgraph/callbacks.pypython/nemo_relay/plugin.py
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Check / Run
- GitHub Check: Preview docs
🧰 Additional context used
📓 Path-based instructions (12)
{crates/python/src/py_api/**/*.rs,python/nemo_relay/**/*.py,python/nemo_relay/**/*.pyi}
📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)
Update Python native binding in
crates/python/src/py_api/mod.rswith Python wrapper docstring inpython/nemo_relay/<module>.pyand type stubs inpython/nemo_relay/*.pyimodules
Files:
python/nemo_relay/integrations/langgraph/callbacks.pypython/nemo_relay/plugin.pypython/nemo_relay/integrations/langchain/callbacks.pypython/nemo_relay/integrations/langchain/_serialization.py
python/nemo_relay/**/*.py
📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)
Use
snake_casenaming convention for Python identifiers (e.g.,nemo_relay.tools.call)Format changed Python wrapper and test files with
uv run ruff format pythonPython wrapper modules live under
python/nemo_relay/; the native extension is built fromcrates/pythonwithmaturin.
Files:
python/nemo_relay/integrations/langgraph/callbacks.pypython/nemo_relay/plugin.pypython/nemo_relay/integrations/langchain/callbacks.pypython/nemo_relay/integrations/langchain/_serialization.py
{pyproject.toml,**/*.py}
📄 CodeRabbit inference engine (.agents/skills/maintain-packaging/SKILL.md)
Maintain consistency between Python package names in
pyproject.tomland import paths used throughout the codebase
Files:
python/nemo_relay/integrations/langgraph/callbacks.pypython/nemo_relay/plugin.pypython/nemo_relay/integrations/langchain/callbacks.pypython/nemo_relay/integrations/langchain/_serialization.py
**/*.{py,txt,toml,cfg,yaml,yml}
📄 CodeRabbit inference engine (.agents/skills/rename-surfaces/SKILL.md)
Update Python package names and top-level module imports during coordinated rename operations
Files:
python/nemo_relay/integrations/langgraph/callbacks.pypython/nemo_relay/plugin.pypython/nemo_relay/integrations/langchain/callbacks.pypython/nemo_relay/integrations/langchain/_serialization.py
**/*.py
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
**/*.py: Run Python formatting withuv run ruff format python
Run Python testing withuv run pytest -k "<pattern>"
**/*.py: Use Ruff with rule sets E, F, W, I for Python linting
Use Ruff formatter with line length 120 and double quotes for Python code formatting
Runtyfor Python type checking
Use Python snake_case naming convention for Python identifiers
Include SPDX license header in all Python source files using hash comment syntax
Validate Python code withuv run pre-commit run --all-filesto enforce Ruff linting and formatting, and ty type checking
Files:
python/nemo_relay/integrations/langgraph/callbacks.pypython/nemo_relay/plugin.pypython/nemo_relay/integrations/langchain/callbacks.pypython/nemo_relay/integrations/langchain/_serialization.py
**/*.{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:
python/nemo_relay/integrations/langgraph/callbacks.pypython/nemo_relay/plugin.pypython/nemo_relay/integrations/langchain/callbacks.pypython/nemo_relay/integrations/langchain/_serialization.py
**/*.{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:
python/nemo_relay/integrations/langgraph/callbacks.pypython/nemo_relay/plugin.pypython/nemo_relay/integrations/langchain/callbacks.pypython/nemo_relay/integrations/langchain/_serialization.py
**/*.{rs,py,go,js,ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Follow binding naming conventions: Rust and Python use
snake_case, C FFI exports prefixednemo_relay_, Go usesPascalCasefor public APIs, Node.js usescamelCase.
Files:
python/nemo_relay/integrations/langgraph/callbacks.pypython/nemo_relay/plugin.pypython/nemo_relay/integrations/langchain/callbacks.pypython/nemo_relay/integrations/langchain/_serialization.py
python/nemo_relay/**/*
⚙️ CodeRabbit configuration file
python/nemo_relay/**/*: Review Python wrapper changes for typed API consistency, contextvars-based scope isolation, async behavior, and parity with the native extension.
Stubs and runtime implementations should stay aligned.
Files:
python/nemo_relay/integrations/langgraph/callbacks.pypython/nemo_relay/plugin.pypython/nemo_relay/integrations/langchain/callbacks.pypython/nemo_relay/integrations/langchain/_serialization.py
{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:
python/nemo_relay/plugin.py
{python/nemo_relay/adaptive.py,python/nemo_relay/plugin.py,go/nemo_relay/adaptive/**,**/node/adaptive/**,**/wasm/adaptive/**}
📄 CodeRabbit inference engine (.agents/skills/maintain-optimizer/SKILL.md)
Ensure typed helper constructors still map cleanly to the same config document in adaptive bindings across Python, Go, Node, and WebAssembly
Files:
python/nemo_relay/plugin.py
{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:
python/nemo_relay/plugin.py
🧠 Learnings (6)
📓 Common learnings
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/maintain-optimizer/SKILL.md:0-0
Timestamp: 2026-05-21T22:49:09.811Z
Learning: Applies to {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)
📚 Learning: 2026-05-26T21:03:12.012Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/review-doc-style/SKILL.md:0-0
Timestamp: 2026-05-26T21:03:12.012Z
Learning: Keep documentation aligned with current NeMo Relay behavior, repo layout, and entry points
Applied to files:
python/nemo_relay/integrations/langgraph/callbacks.py
📚 Learning: 2026-05-21T22:47:48.663Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/add-integration/SKILL.md:0-0
Timestamp: 2026-05-21T22:47:48.663Z
Learning: Applies to **/*.{py} : LLM calls should use NeMo Relay managed execution where possible
Applied to files:
python/nemo_relay/integrations/langgraph/callbacks.py
📚 Learning: 2026-05-29T21:25:49.977Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-05-29T21:25:49.977Z
Learning: Applies to python/nemo_relay/**/*.py : Python wrapper modules live under `python/nemo_relay/`; the native extension is built from `crates/python` with `maturin`.
Applied to files:
python/nemo_relay/integrations/langgraph/callbacks.pypython/nemo_relay/integrations/langchain/callbacks.py
📚 Learning: 2026-05-21T22:49:09.811Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/maintain-optimizer/SKILL.md:0-0
Timestamp: 2026-05-21T22:49:09.811Z
Learning: Applies to {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)
Applied to files:
python/nemo_relay/plugin.py
📚 Learning: 2026-05-21T22:47:48.663Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/add-integration/SKILL.md:0-0
Timestamp: 2026-05-21T22:47:48.663Z
Learning: Applies to **/*.{py} : Keep `nemo_relay` as an optional dependency and ensure framework behavior falls back cleanly when NeMo Relay is unavailable
Applied to files:
python/nemo_relay/integrations/langchain/callbacks.py
🪛 Ruff (0.15.15)
python/nemo_relay/plugin.py
[warning] 336-336: Boolean-typed positional argument in function definition
(FBT001)
[warning] 336-336: Boolean default positional argument in function definition
(FBT002)
python/nemo_relay/integrations/langchain/callbacks.py
[warning] 73-73: Logging .exception(...) should be used instead of .error(..., exc_info=True)
(G201)
[warning] 106-106: Logging .exception(...) should be used instead of .error(..., exc_info=True)
(G201)
python/nemo_relay/integrations/langchain/_serialization.py
[warning] 307-307: Dynamically typed expressions (typing.Any) are disallowed in pyaload
(ANN401)
[warning] 307-307: Dynamically typed expressions (typing.Any) are disallowed in _prepare_lc_payloads
(ANN401)
🔇 Additional comments (4)
python/nemo_relay/plugin.py (2)
31-31: LGTM!
353-355: LGTM!python/nemo_relay/integrations/langchain/callbacks.py (1)
57-73: LGTM!Also applies to: 97-106
python/nemo_relay/integrations/langgraph/callbacks.py (1)
14-14: LGTM!Also applies to: 23-23
Signed-off-by: David Gardner <dagardner@nvidia.com>
… make clear_on_exit a keyword only argument Signed-off-by: David Gardner <dagardner@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 (2)
python/nemo_relay/plugin.py (2)
336-356: 🧹 Nitpick | 🔵 TrivialConsider cross-binding parity for
clear_on_exit.The new
clear_on_exitparameter provides useful lifecycle control. Per project learnings on maintaining consistent plugin lifecycle across bindings, consider whether Go/Node/Wasm plugin context managers should expose an equivalent option for parity.🤖 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 `@python/nemo_relay/plugin.py` around lines 336 - 356, The new async context manager function plugin(config: PluginConfig | JsonObject, *, clear_on_exit: bool = True) adds a clear_on_exit lifecycle flag but the comment requests parity across other language bindings; update the equivalent context/constructor APIs in the Go, Node, and Wasm plugin modules to accept the same option (e.g., add a clearOnExit/clear_on_exit parameter to their plugin/context init functions), wire it to call the same cleanup behavior (subscribers.flush and clear equivalents) when true, and update any docs/tests for Plugin initialization/cleanup to reflect the new parameter for cross-binding consistency.
336-351:⚠️ Potential issue | 🟠 MajorFix
python/nemo_relay/plugin.pyisignature to includeclear_on_exit
python/nemo_relay/plugin.pyadds the keyword-onlyclear_on_exit: bool = True, butpython/nemo_relay/plugin.pyistill declaresdef plugin(config: PluginConfig | JsonObject) -> AsyncContextManager[ConfigReport]: ...withoutclear_on_exit. Update the stub signature to match the runtime API.🤖 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 `@python/nemo_relay/plugin.py` around lines 336 - 351, The stub for the async context manager is out of sync: update python/nemo_relay/plugin.pyi so the signature for plugin matches the runtime implementation by including the keyword-only parameter clear_on_exit: bool = True (keeping types PluginConfig | JsonObject and return AsyncContextManager[ConfigReport]); ensure the stub's import/type references for PluginConfig, JsonObject, and ConfigReport match the module so the type checker sees the same API as the plugin function.
🤖 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 `@python/nemo_relay/plugin.py`:
- Around line 336-356: The new async context manager function plugin(config:
PluginConfig | JsonObject, *, clear_on_exit: bool = True) adds a clear_on_exit
lifecycle flag but the comment requests parity across other language bindings;
update the equivalent context/constructor APIs in the Go, Node, and Wasm plugin
modules to accept the same option (e.g., add a clearOnExit/clear_on_exit
parameter to their plugin/context init functions), wire it to call the same
cleanup behavior (subscribers.flush and clear equivalents) when true, and update
any docs/tests for Plugin initialization/cleanup to reflect the new parameter
for cross-binding consistency.
- Around line 336-351: The stub for the async context manager is out of sync:
update python/nemo_relay/plugin.pyi so the signature for plugin matches the
runtime implementation by including the keyword-only parameter clear_on_exit:
bool = True (keeping types PluginConfig | JsonObject and return
AsyncContextManager[ConfigReport]); ensure the stub's import/type references for
PluginConfig, JsonObject, and ConfigReport match the module so the type checker
sees the same API as the plugin function.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Enterprise
Run ID: 41bc2903-33b9-4950-b315-700c64bc7eab
📒 Files selected for processing (1)
python/nemo_relay/plugin.py
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Check / Run
- GitHub Check: Preview docs
🧰 Additional context used
📓 Path-based instructions (12)
{crates/python/src/py_api/**/*.rs,python/nemo_relay/**/*.py,python/nemo_relay/**/*.pyi}
📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)
Update Python native binding in
crates/python/src/py_api/mod.rswith Python wrapper docstring inpython/nemo_relay/<module>.pyand type stubs inpython/nemo_relay/*.pyimodules
Files:
python/nemo_relay/plugin.py
python/nemo_relay/**/*.py
📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)
Use
snake_casenaming convention for Python identifiers (e.g.,nemo_relay.tools.call)Format changed Python wrapper and test files with
uv run ruff format pythonPython wrapper modules live under
python/nemo_relay/; the native extension is built fromcrates/pythonwithmaturin.
Files:
python/nemo_relay/plugin.py
{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:
python/nemo_relay/plugin.py
{python/nemo_relay/adaptive.py,python/nemo_relay/plugin.py,go/nemo_relay/adaptive/**,**/node/adaptive/**,**/wasm/adaptive/**}
📄 CodeRabbit inference engine (.agents/skills/maintain-optimizer/SKILL.md)
Ensure typed helper constructors still map cleanly to the same config document in adaptive bindings across Python, Go, Node, and WebAssembly
Files:
python/nemo_relay/plugin.py
{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:
python/nemo_relay/plugin.py
{pyproject.toml,**/*.py}
📄 CodeRabbit inference engine (.agents/skills/maintain-packaging/SKILL.md)
Maintain consistency between Python package names in
pyproject.tomland import paths used throughout the codebase
Files:
python/nemo_relay/plugin.py
**/*.{py,txt,toml,cfg,yaml,yml}
📄 CodeRabbit inference engine (.agents/skills/rename-surfaces/SKILL.md)
Update Python package names and top-level module imports during coordinated rename operations
Files:
python/nemo_relay/plugin.py
**/*.py
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
**/*.py: Run Python formatting withuv run ruff format python
Run Python testing withuv run pytest -k "<pattern>"
**/*.py: Use Ruff with rule sets E, F, W, I for Python linting
Use Ruff formatter with line length 120 and double quotes for Python code formatting
Runtyfor Python type checking
Use Python snake_case naming convention for Python identifiers
Include SPDX license header in all Python source files using hash comment syntax
Validate Python code withuv run pre-commit run --all-filesto enforce Ruff linting and formatting, and ty type checking
Files:
python/nemo_relay/plugin.py
**/*.{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:
python/nemo_relay/plugin.py
**/*.{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:
python/nemo_relay/plugin.py
**/*.{rs,py,go,js,ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Follow binding naming conventions: Rust and Python use
snake_case, C FFI exports prefixednemo_relay_, Go usesPascalCasefor public APIs, Node.js usescamelCase.
Files:
python/nemo_relay/plugin.py
python/nemo_relay/**/*
⚙️ CodeRabbit configuration file
python/nemo_relay/**/*: Review Python wrapper changes for typed API consistency, contextvars-based scope isolation, async behavior, and parity with the native extension.
Stubs and runtime implementations should stay aligned.
Files:
python/nemo_relay/plugin.py
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/maintain-optimizer/SKILL.md:0-0
Timestamp: 2026-05-21T22:49:09.811Z
Learning: Applies to {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)
📚 Learning: 2026-05-21T22:49:09.811Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/maintain-optimizer/SKILL.md:0-0
Timestamp: 2026-05-21T22:49:09.811Z
Learning: Applies to {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)
Applied to files:
python/nemo_relay/plugin.py
🔇 Additional comments (2)
python/nemo_relay/plugin.py (2)
17-32: LGTM!
352-355: LGTM!
|
/merge |
Overview
Ensure LC inputs are JSON serializable in the callbacks prior to pushing the scope, and call
subscribers.flush()prior to exiting from the plugin context manager.Details
plugin.clear()optional in theplugin.plugincontext manager via theclear_on_exitkeyword argument.subscribers.flush()prior to exiting from the plugin context manager, ensures that all pending events have been sent to plugins prior to clearing the plugins.Where should the reviewer start?
Related Issues: (use one of the action keywords Closes / Fixes / Resolves / Relates to)
Summary by CodeRabbit
New Features
Bug Fixes
Refactor