Skip to content

refactor!: opm agents plugins#13

Open
JarbasAl wants to merge 1 commit intodevfrom
opm-agents
Open

refactor!: opm agents plugins#13
JarbasAl wants to merge 1 commit intodevfrom
opm-agents

Conversation

@JarbasAl
Copy link
Member

@JarbasAl JarbasAl commented Feb 17, 2026

solver plugins have been deprecated OpenVoiceOS/ovos-plugin-manager#365

this is a breaking change and will require OpenVoiceOS/ovos-persona#143

Summary by CodeRabbit

  • New Features

    • Plugin now returns ranked search results with confidence scores instead of single answers, enabling better result relevance and selection.
  • Chores

    • Updated plugin classification and branding to align with OpenVoiceOS ecosystem.
    • Updated dependency constraints for improved plugin compatibility.

@coderabbitai
Copy link

coderabbitai bot commented Feb 17, 2026

📝 Walkthrough

Walkthrough

The AIML solver plugin transitions from a question-answering solver to a retrieval-based chatbot agent. Its base class changed from QuestionSolver to RetrievalEngine, and the single-answer method was replaced with a query method returning ranked (content, score) tuples. Dependencies and package metadata were updated to reflect the new architecture and OpenVoiceOS integration.

Changes

Cohort / File(s) Summary
Core Plugin Architecture
ovos_solver_aiml_plugin/__init__.py
Base class transitioned from QuestionSolver to RetrievalEngine; __init__ signature updated with type hints; get_spoken_answer method replaced with query method that returns List[Tuple[str, float]] representing top-k results with scores.
Dependencies
requirements.txt
Updated ovos-plugin-manager version constraint from ">=0.0.26,<3.0.0" to ">=2.2.3a1,<3.0.0".
Package Configuration
setup.py
Updated project description to reflect chatbot role; keywords adjusted for OpenVoiceOS branding; entry point changed from 'neon.plugin.solver' to 'opm.agents.retrieval'.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 From questions once to answers deep,
Through RetrievalEngine we leap,
With top-k treasures, ranked and neat,
The AIML bot makes chatbots complete,
Hopity-hop through OpenVoiceOS sweet!

🚥 Pre-merge checks | ✅ 3 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ 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 'refactor!: opm agents plugins' accurately reflects the main change: converting the plugin from a solver plugin to an OPM agents/retrieval plugin across all configuration files and the base class.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into dev

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch opm-agents

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.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

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

⚠️ Outside diff range comments (1)
ovos_solver_aiml_plugin/__init__.py (1)

123-128: ⚠️ Potential issue | 🟠 Major

__main__ block calls spoken_answer, which is not defined on AIMLSolver.

AIMLSolver extends RetrievalEngine which does not provide a spoken_answer method. Lines 127-128 will raise an AttributeError at runtime. Either define spoken_answer on AIMLSolver or replace the calls with the appropriate method (likely query).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ovos_solver_aiml_plugin/__init__.py` around lines 123 - 128, The __main__
block calls AIMLSolver.spoken_answer which does not exist (AIMLSolver extends
RetrievalEngine); replace those calls with the correct method (likely
AIMLSolver.query) or implement a spoken_answer wrapper on AIMLSolver that
delegates to query and handles lang parameter; update the demo lines that
currently reference AimlBot.XDG_PATH and the two spoken_answer calls to use
AIMLSolver.query (or add a method named spoken_answer in class AIMLSolver that
calls self.query) so the script runs without AttributeError.
🤖 Fix all issues with AI agents
Verify each finding against the current code and only fix it if needed.


In `@ovos_solver_aiml_plugin/__init__.py`:
- Around line 108-120: The query method can return (None, 0.5) because
AimlBot.ask() may return None; update query (method query in
ovos_solver_aiml_plugin.__init__.py) to filter out empty answers and only return
List[Tuple[str,float]] entries with non-empty string content (return [] when
ask() is None), and respect k by limiting results to k; also either honor or
explicitly document that lang is ignored (or implement language switching via
the brain if supported). Specifically: call self.brain.ask(query), check for
falsy/None/empty-string response before adding to the result list, cap the
returned list at k, and add a short code comment or docstring note about the
ignored lang parameter if you don’t implement language switching.
- Around line 98-106: The constructor for AIMLSolver currently mutates the
passed-in dict by assigning config["lang"] = "en-us"; instead, make a shallow
copy of the incoming config (e.g., new_config = dict(config) or config.copy())
and operate on that copy so the caller's dict is not modified; update references
in __init__ to use the local copy when computing lang, checking
AimlBot.XDG_PATH, calling super().__init__ and creating self.brain (i.e., change
usages of config to the new local_config variable).
- Around line 123-128: The __main__ block calls AIMLSolver.spoken_answer which
does not exist (AIMLSolver extends RetrievalEngine); replace those calls with
the correct method (likely AIMLSolver.query) or implement a spoken_answer
wrapper on AIMLSolver that delegates to query and handles lang parameter; update
the demo lines that currently reference AimlBot.XDG_PATH and the two
spoken_answer calls to use AIMLSolver.query (or add a method named spoken_answer
in class AIMLSolver that calls self.query) so the script runs without
AttributeError.

In `@requirements.txt`:
- Line 2: The requirements line pins an alpha pre-release
("ovos-plugin-manager>=2.2.3a1,<3.0.0") which breaks default pip resolution;
update that requirement to reference a stable release (e.g., change the
constraint to "ovos-plugin-manager>=2.2.3,<3.0.0" once 2.2.3 is released) or
temporarily use the latest stable series ("ovos-plugin-manager>=2.2.0,<3.0.0")
and/or document that installing requires --pre until a stable 2.2.3 is
available; locate the package entry "ovos-plugin-manager>=2.2.3a1,<3.0.0" in
requirements.txt and update it accordingly.
🧹 Nitpick comments (1)
🤖 Fix all nitpicks with AI agents
Verify each finding against the current code and only fix it if needed.


In `@ovos_solver_aiml_plugin/__init__.py`:
- Around line 98-106: The constructor for AIMLSolver currently mutates the
passed-in dict by assigning config["lang"] = "en-us"; instead, make a shallow
copy of the incoming config (e.g., new_config = dict(config) or config.copy())
and operate on that copy so the caller's dict is not modified; update references
in __init__ to use the local copy when computing lang, checking
AimlBot.XDG_PATH, calling super().__init__ and creating self.brain (i.e., change
usages of config to the new local_config variable).
ovos_solver_aiml_plugin/__init__.py (1)

98-106: Constructor mutates the caller's config dict.

Line 103 mutates the config dict that was passed in (config["lang"] = "en-us"). If a caller passes a shared config object, this side-effect could be surprising. Consider working on a copy.

Proposed fix
     def __init__(self, config: Optional[Dict[str, Any]] = None):
-        config = config or {"lang": "en-us"}
+        config = dict(config) if config else {"lang": "en-us"}
         lang = config.get("lang") or "en-us"
         if lang != "en-us" and lang not in os.listdir(AimlBot.XDG_PATH):
             config["lang"] = "en-us"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ovos_solver_aiml_plugin/__init__.py` around lines 98 - 106, The constructor
for AIMLSolver currently mutates the passed-in dict by assigning config["lang"]
= "en-us"; instead, make a shallow copy of the incoming config (e.g., new_config
= dict(config) or config.copy()) and operate on that copy so the caller's dict
is not modified; update references in __init__ to use the local copy when
computing lang, checking AimlBot.XDG_PATH, calling super().__init__ and creating
self.brain (i.e., change usages of config to the new local_config variable).

Comment on lines +108 to +120
def query(self, query: str, lang: Optional[str] = None, k: int = 3) -> List[Tuple[str, float]]:
"""
Obtain the spoken answer for a given query.
Searches the knowledge base for relevant documents or data.

Args:
query (str): The query text.
lang (Optional[str]): Optional language code. Defaults to None.
units (Optional[str]): Optional units for the query. Defaults to None.
query: The search string.
lang: BCP-47 language code.
k: The maximum number of results to return.

Returns:
str: The spoken answer as a text response.
List of tuples (content, score) for the top k matches.
"""
return self.brain.ask(query)
return [(self.brain.ask(query), 0.5)]
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

query can return (None, 0.5) when the brain has no answer.

AimlBot.ask() returns None when the AIML kernel produces an empty response (Line 89-90). This propagates a None content value into the result list, which callers will not expect from a List[Tuple[str, float]] return type.

Additionally, the lang and k parameters are accepted but ignored — lang cannot switch the brain's language at query time, and k has no effect since at most one result is returned. Consider documenting this or handling them.

Proposed fix: filter out empty responses
     def query(self, query: str, lang: Optional[str] = None, k: int = 3) -> List[Tuple[str, float]]:
         """
         Searches the knowledge base for relevant documents or data.
 
         Args:
             query: The search string.
             lang: BCP-47 language code.
             k: The maximum number of results to return.
 
         Returns:
             List of tuples (content, score) for the top k matches.
         """
-        return [(self.brain.ask(query), 0.5)]
+        answer = self.brain.ask(query)
+        if answer:
+            return [(answer, 0.5)]
+        return []
🧰 Tools
🪛 Ruff (0.15.0)

[warning] 108-108: Unused method argument: lang

(ARG002)


[warning] 108-108: Unused method argument: k

(ARG002)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ovos_solver_aiml_plugin/__init__.py` around lines 108 - 120, The query method
can return (None, 0.5) because AimlBot.ask() may return None; update query
(method query in ovos_solver_aiml_plugin.__init__.py) to filter out empty
answers and only return List[Tuple[str,float]] entries with non-empty string
content (return [] when ask() is None), and respect k by limiting results to k;
also either honor or explicitly document that lang is ignored (or implement
language switching via the brain if supported). Specifically: call
self.brain.ask(query), check for falsy/None/empty-string response before adding
to the result list, cap the returned list at k, and add a short code comment or
docstring note about the ignored lang parameter if you don’t implement language
switching.

@@ -1,2 +1,2 @@
aiml
ovos-plugin-manager>=0.0.26,<3.0.0
ovos-plugin-manager>=2.2.3a1,<3.0.0 No newline at end of file
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

ovos-plugin-manager PyPI latest version

💡 Result:

  • Latest stable (non–pre-release) on PyPI: 2.2.0 (released Jan 28, 2026) [1]
  • Latest pre-release on PyPI: 2.2.3a1 (released Jan 30, 2026) [1]

Source: PyPI project page for ovos-plugin-manager [1]


Minimum version pinned to an alpha pre-release.

Requiring >=2.2.3a1 means downstream consumers must install a pre-release of ovos-plugin-manager. The latest stable release is only 2.2.0, so by default, pip install will fail to resolve this constraint (pre-releases are ignored unless --pre is passed or an explicit pre-release is already installed). This will cause dependency resolution failures for users.

Consider waiting for ovos-plugin-manager 2.2.3 stable to be released and then update the constraint to >=2.2.3,<3.0.0, or document that --pre is required until then.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@requirements.txt` at line 2, The requirements line pins an alpha pre-release
("ovos-plugin-manager>=2.2.3a1,<3.0.0") which breaks default pip resolution;
update that requirement to reference a stable release (e.g., change the
constraint to "ovos-plugin-manager>=2.2.3,<3.0.0" once 2.2.3 is released) or
temporarily use the latest stable series ("ovos-plugin-manager>=2.2.0,<3.0.0")
and/or document that installing requires --pre until a stable 2.2.3 is
available; locate the package entry "ovos-plugin-manager>=2.2.3a1,<3.0.0" in
requirements.txt and update it accordingly.

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