Skip to content

feat: add OptionMatcherEngine plugin type #379

Merged
JarbasAl merged 3 commits into
devfrom
feat/opt_matcher
Mar 18, 2026
Merged

feat: add OptionMatcherEngine plugin type #379
JarbasAl merged 3 commits into
devfrom
feat/opt_matcher

Conversation

@JarbasAl

@JarbasAl JarbasAl commented Mar 18, 2026

Copy link
Copy Markdown
Member

for ask_selection slot resolution

Introduces a dedicated engine class for matching free-form user utterances to predefined option slots — semantically distinct from ReRankerEngine (which ranks answers against a semantic query) and modelled after the existing YesNoEngine pattern.

Changes:

  • templates/agents.py: add OptionMatcherEngine with abstract match_option()
  • utils/init.py: add AGENT_OPTION_MATCHER = "opm.agents.option_matcher" to both PluginTypes and PluginConfigTypes
  • agents.py: add find_option_matcher_plugins() and load_option_matcher_plugin()
  • test_agents.py: 4 new tests covering find, load, abstract enforcement, and concrete subclass instantiation

Summary by CodeRabbit

  • New Features

    • Added a new OptionMatcher plugin type to match free-form user utterances to predefined options, enabling more flexible decision-making in skills.
    • Added plugin discovery and loading support for option matcher plugins to make the system extensible.
    • Clarified plugin loading behavior in docs for improved developer guidance.
  • Tests

    • Added unit tests for option matcher discovery, loading, and abstract-interface validation.

…lution

Introduces a dedicated engine class for matching free-form user utterances
to predefined option slots — semantically distinct from ReRankerEngine
(which ranks answers against a semantic query) and modelled after the
existing YesNoEngine pattern.

Changes:
- templates/agents.py: add OptionMatcherEngine with abstract match_option()
- utils/__init__.py: add AGENT_OPTION_MATCHER = "opm.agents.option_matcher"
  to both PluginTypes and PluginConfigTypes
- agents.py: add find_option_matcher_plugins() and load_option_matcher_plugin()
- test_agents.py: 4 new tests covering find, load, abstract enforcement,
  and concrete subclass instantiation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Mar 18, 2026

Copy link
Copy Markdown
Contributor

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: cd90bacf-6174-48ab-8b60-0f0c1d7e86b9

📥 Commits

Reviewing files that changed from the base of the PR and between 660413e and 8e31906.

📒 Files selected for processing (1)
  • ovos_plugin_manager/templates/agents.py

📝 Walkthrough

Walkthrough

Adds a new OptionMatcherEngine abstract template, plugin discovery/loading helpers for option matcher plugins, corresponding plugin type enum entries, and unit tests validating discovery, loading, and the abstract contract.

Changes

Cohort / File(s) Summary
Option matcher template
ovos_plugin_manager/templates/agents.py
Added OptionMatcherEngine (subclass of AbstractAgentEngine) with abstract match_option(utterance, options, lang=None) -> Optional[str]. Clarified ReRankerEngine.select_answer docstring.
Plugin management API
ovos_plugin_manager/agents.py
Exported OptionMatcherEngine and added find_option_matcher_plugins() -> Dict[str, Type[OptionMatcherEngine]] and load_option_matcher_plugin(module_name: str) -> Type[OptionMatcherEngine]. Updated load_yesno_plugin docstring style.
Plugin type enums
ovos_plugin_manager/utils/__init__.py
Added AGENT_OPTION_MATCHER entries to PluginTypes ("opm.agents.option_matcher") and PluginConfigTypes ("opm.agents.option_matcher.config").
Unit tests
test/unittests/test_agents.py
Added tests to verify find_option_matcher_plugins and load_option_matcher_plugin call plugin helpers with AGENT_OPTION_MATCHER, and tests for OptionMatcherEngine abstract method behavior using a FakeMatcher implementation.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 I nose about options, one hop, then two,
I sniff the utterance and point to the true,
From many choices to one I nimbly march,
A plugin-made path beneath moonlit starch,
Hooray — I match! 🥕✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: introducing a new OptionMatcherEngine plugin type, which is reflected across all modified files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/opt_matcher
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai

coderabbitai Bot commented Mar 18, 2026

Copy link
Copy Markdown
Contributor

Note

Docstrings generation - SUCCESS
Generated docstrings and committed to branch feat/opt_matcher (commit: 660413eedcacafc421cfe5553c01cf0d0e3a7158)

@github-actions

github-actions Bot commented Mar 18, 2026

Copy link
Copy Markdown
Contributor

Hello there! I've processed your latest changes. 🌊

I've aggregated the results of the automated checks for this PR below.

📋 Repo Health

I've checked the repo's balance (aka feature parity). ⚖️

✅ All required files present.

Latest Version: 2.3.0a1

ovos_plugin_manager/version.py — Version file
README.md — README
LICENSE — License file
pyproject.toml — pyproject.toml
CHANGELOG.md — Changelog
⚠️ requirements.txt — Requirements
ovos_plugin_manager/version.py has valid version block markers

🔒 Security (pip-audit)

Ensuring no malicious actors are hitching a ride. 🎭

✅ No known vulnerabilities found (59 packages scanned).

📊 Coverage

Ensuring every logical path is accounted for. 🛣️

84.9% total coverage

Files below 80% coverage (22 files)
File Coverage Missing lines
ovos_plugin_manager/utils/audio.py 22.5% 69
ovos_plugin_manager/hardware/__init__.py 31.6% 13
ovos_plugin_manager/templates/gui.py 39.0% 25
ovos_plugin_manager/audio.py 40.5% 22
ovos_plugin_manager/templates/language.py 58.0% 21
ovos_plugin_manager/audio2ipa.py 58.1% 13
ovos_plugin_manager/gui.py 62.5% 15
ovos_plugin_manager/postag.py 63.0% 17
ovos_plugin_manager/segmentation.py 63.0% 17
ovos_plugin_manager/tokenization.py 63.0% 17
ovos_plugin_manager/templates/solvers.py 68.5% 82
ovos_plugin_manager/plugin_entry.py 69.1% 46
ovos_plugin_manager/coreference.py 69.2% 16
ovos_plugin_manager/templates/hotwords.py 71.0% 9
ovos_plugin_manager/templates/ocp.py 72.2% 5
ovos_plugin_manager/dialog_transformers.py 72.7% 3
ovos_plugin_manager/templates/segmentation.py 73.7% 5
ovos_plugin_manager/templates/audio2ipa.py 75.0% 3
ovos_plugin_manager/templates/postag.py 75.0% 5
ovos_plugin_manager/persona.py 77.8% 2
ovos_plugin_manager/templates/keywords.py 78.9% 4
ovos_plugin_manager/wakewords.py 79.3% 19

Full report: download the coverage-report artifact.

🏷️ Release Preview

The release notes are being translated as we speak. 🌍

Current: 2.3.0a1Next: 2.4.0a1

Signal Value
Label feature
PR title feat: add OptionMatcherEngine plugin type
Bump minor

✅ PR title follows conventional commit format.


🚀 Release Channel Compatibility

Predicted next version: 2.4.0a1

Channel Status Note Current Constraint
Stable Too new (must be <0.10.0) ovos-plugin-manager>=0.9.0,<0.10.0
Testing Compatible ovos-plugin-manager>=1.0.3,<3.0.0
Alpha Compatible ovos-plugin-manager>=2.2.3a1

🔍 Lint

Evaluating the overall progress of your contribution. 📉

ruff: issues found — see job log

⚖️ License Check

Ensuring our CLA requirements are met. 🖋️

✅ No license violations found (40 packages).

License distribution: 10× MIT License, 6× Apache Software License, 6× MIT, 4× Apache-2.0, 2× BSD-3-Clause, 2× ISC License (ISCL), 2× PSF-2.0, 2× Python Software Foundation License, +6 more

Full breakdown — 40 packages
Package Version License URL
audioop-lts 0.2.2 PSF-2.0 link
build 1.4.0 MIT link
certifi 2026.2.25 Mozilla Public License 2.0 (MPL 2.0) link
charset-normalizer 3.4.6 MIT link
click 8.3.1 BSD-3-Clause link
combo_lock 0.3.0 Apache Software License link
filelock 3.25.2 MIT link
idna 3.11 BSD-3-Clause link
importlib_metadata 8.7.1 Apache-2.0 link
json-database 0.10.1 MIT link
kthread 0.2.3 MIT License link
langcodes 3.5.1 MIT License link
markdown-it-py 4.0.0 MIT License link
mdurl 0.1.2 MIT License link
memory-tempfile 2.2.3 MIT License link
ovos-config 2.1.1 Apache-2.0 link
ovos-plugin-manager 2.3.0a1 Apache-2.0 link
ovos-utils 0.8.5 Apache-2.0 link
ovos_bus_client 1.5.0 Apache Software License link
packaging 26.0 Apache-2.0 OR BSD-2-Clause link
pexpect 4.9.0 ISC License (ISCL) link
ptyprocess 0.7.0 ISC License (ISCL) link
pyee 12.1.1 MIT License link
Pygments 2.19.2 BSD License link
pyproject_hooks 1.2.0 MIT License link
python-dateutil 2.9.0.post0 Apache Software License; BSD License link
PyYAML 6.0.3 MIT License link
quebra-frases 0.3.7 Apache Software License link
regex 2026.2.28 Apache-2.0 AND CNRI-Python link
requests 2.32.5 Apache Software License link
rich 13.9.4 MIT License link
rich-click 1.9.7 MIT License

Copyright (c) 2022 Phil Ewels

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
| link |
| six | 1.17.0 | MIT License | link |
| standard-aifc | 3.13.0 | Python Software Foundation License | link |
| standard-chunk | 3.13.0 | Python Software Foundation License | link |
| typing_extensions | 4.15.0 | PSF-2.0 | link |
| urllib3 | 2.6.3 | MIT | link |
| watchdog | 6.0.0 | Apache Software License | link |
| websocket-client | 1.9.0 | Apache Software License | link |
| zipp | 3.23.0 | MIT | link |

Policy: Apache 2.0 (universal donor). StrongCopyleft / NetworkCopyleft / WeakCopyleft / Other / Error categories fail. MPL allowed.

🔨 Build Tests

Checking if the code is ready for prime time. 📺

✅ All versions pass

Python Build Install Tests
3.9
3.10
3.11
3.12
3.13
3.14

Processing completed in 0.0001 bot-seconds ⚡

Docstrings generation was requested by @JarbasAl.

The following files were modified:

* `ovos_plugin_manager/agents.py`
* `ovos_plugin_manager/templates/agents.py`
* `test/unittests/test_agents.py`
@github-actions github-actions Bot added feature and removed feature labels Mar 18, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
ovos_plugin_manager/templates/agents.py (1)

469-485: ⚠️ Potential issue | 🟡 Minor

Handle empty ranking results before indexing top-1.

At Line 485, self.rerank(...)[0][1] will raise on empty options (or any empty rerank result). Add an explicit guard and raise a clearer error.

💡 Suggested fix
     def select_answer(self, query: str,
                       options: List[str],
                       lang: Optional[str] = None,
                       return_index: bool = False) -> Union[str, int]:
@@
-        return self.rerank(query, options, lang=lang, return_index=return_index)[0][1]
+        ranked = self.rerank(query, options, lang=lang, return_index=return_index)
+        if not ranked:
+            raise ValueError("No ranked options available; ensure `options` is non-empty.")
+        return ranked[0][1]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ovos_plugin_manager/templates/agents.py` around lines 469 - 485, The
select_answer method currently indexes into the first element of
self.rerank(...) without checking for an empty result which will raise
IndexError when options is empty; change select_answer to call rerank_result =
self.rerank(query, options, lang=lang, return_index=return_index), check if not
rerank_result and raise a clear ValueError (e.g. "No candidate options provided
or rerank returned empty result in select_answer"), then return the top item
from rerank_result[0][1] as before (preserving the return_index behavior).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@ovos_plugin_manager/templates/agents.py`:
- Around line 469-485: The select_answer method currently indexes into the first
element of self.rerank(...) without checking for an empty result which will
raise IndexError when options is empty; change select_answer to call
rerank_result = self.rerank(query, options, lang=lang,
return_index=return_index), check if not rerank_result and raise a clear
ValueError (e.g. "No candidate options provided or rerank returned empty result
in select_answer"), then return the top item from rerank_result[0][1] as before
(preserving the return_index behavior).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0cad4302-b478-40f6-b4e1-63fce6c5c26a

📥 Commits

Reviewing files that changed from the base of the PR and between 1ccdfce and 660413e.

📒 Files selected for processing (4)
  • ovos_plugin_manager/agents.py
  • ovos_plugin_manager/templates/agents.py
  • ovos_plugin_manager/utils/__init__.py
  • test/unittests/test_agents.py

@JarbasAl JarbasAl merged commit 2324eee into dev Mar 18, 2026
13 of 14 checks passed
@JarbasAl JarbasAl deleted the feat/opt_matcher branch March 18, 2026 18:18
@github-actions github-actions Bot added feature and removed feature labels Mar 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant