From 8e9a8d798e1b1cd8fdeef9009fe742fd8623eb6a Mon Sep 17 00:00:00 2001 From: JarbasAI <33701864+JarbasAl@users.noreply.github.com> Date: Sat, 22 Nov 2025 21:18:14 +0000 Subject: [PATCH 01/21] Update requirements.txt (#3) --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 51cd62f..96e48ec 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ rivescript -ovos-plugin-manager>=0.0.26,<2.0.0 \ No newline at end of file +ovos-plugin-manager>=0.0.26,<3.0.0 From c3b6d00fc5e8d03fe5fa9e43d691f358415f1f0c Mon Sep 17 00:00:00 2001 From: JarbasAl Date: Sat, 22 Nov 2025 21:18:29 +0000 Subject: [PATCH 02/21] Increment Version to 0.0.2a1 --- ovos_solver_rivescript_plugin/version.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ovos_solver_rivescript_plugin/version.py b/ovos_solver_rivescript_plugin/version.py index 76c4342..3d283ec 100644 --- a/ovos_solver_rivescript_plugin/version.py +++ b/ovos_solver_rivescript_plugin/version.py @@ -1,6 +1,6 @@ # START_VERSION_BLOCK VERSION_MAJOR = 0 VERSION_MINOR = 0 -VERSION_BUILD = 1 -VERSION_ALPHA = 0 +VERSION_BUILD = 2 +VERSION_ALPHA = 1 # END_VERSION_BLOCK From ee2a2565e389c25007eabee6a0e7c5bdefeeb42d Mon Sep 17 00:00:00 2001 From: JarbasAl Date: Sat, 22 Nov 2025 21:18:51 +0000 Subject: [PATCH 03/21] Update Changelog --- CHANGELOG.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ba439cd..a5dffaa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,16 @@ # Changelog -## [0.0.1a1](https://github.com/OpenVoiceOS/ovos-solver-plugin-rivescript/tree/0.0.1a1) (2025-06-08) +## [0.0.2a1](https://github.com/OpenVoiceOS/ovos-solver-plugin-rivescript/tree/0.0.2a1) (2025-11-22) -[Full Changelog](https://github.com/OpenVoiceOS/ovos-solver-plugin-rivescript/compare/0.0.0...0.0.1a1) +[Full Changelog](https://github.com/OpenVoiceOS/ovos-solver-plugin-rivescript/compare/V0.0.1...0.0.2a1) **Merged pull requests:** -- fix: compatibility with ovos-plugin-manager 1.X.X [\#1](https://github.com/OpenVoiceOS/ovos-solver-plugin-rivescript/pull/1) ([JarbasAl](https://github.com/JarbasAl)) +- Update requirements.txt [\#3](https://github.com/OpenVoiceOS/ovos-solver-plugin-rivescript/pull/3) ([JarbasAl](https://github.com/JarbasAl)) + +## [V0.0.1](https://github.com/OpenVoiceOS/ovos-solver-plugin-rivescript/tree/V0.0.1) (2025-06-08) + +[Full Changelog](https://github.com/OpenVoiceOS/ovos-solver-plugin-rivescript/compare/0.0.1...V0.0.1) From fe6f8d10e30c457e080c7c01a1d676de06718b4e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 18 Dec 2025 03:41:31 +0000 Subject: [PATCH 04/21] Add renovate.json (#5) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- renovate.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 renovate.json diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000..5db72dd --- /dev/null +++ b/renovate.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:recommended" + ] +} From 0745e2ca47a8444cb2d3033eab966bb8fe6b61ca Mon Sep 17 00:00:00 2001 From: JarbasAl Date: Thu, 18 Dec 2025 03:43:27 +0000 Subject: [PATCH 05/21] Increment Version to 0.0.2a2 --- ovos_solver_rivescript_plugin/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ovos_solver_rivescript_plugin/version.py b/ovos_solver_rivescript_plugin/version.py index 3d283ec..6e7e2ae 100644 --- a/ovos_solver_rivescript_plugin/version.py +++ b/ovos_solver_rivescript_plugin/version.py @@ -2,5 +2,5 @@ VERSION_MAJOR = 0 VERSION_MINOR = 0 VERSION_BUILD = 2 -VERSION_ALPHA = 1 +VERSION_ALPHA = 2 # END_VERSION_BLOCK From ef25cccc7d399369e6c2bf881abb47e174d10ac2 Mon Sep 17 00:00:00 2001 From: JarbasAl Date: Thu, 18 Dec 2025 03:49:46 +0000 Subject: [PATCH 06/21] Update Changelog --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a5dffaa..7d7f86a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [0.0.2a2](https://github.com/OpenVoiceOS/ovos-solver-plugin-rivescript/tree/0.0.2a2) (2025-12-18) + +[Full Changelog](https://github.com/OpenVoiceOS/ovos-solver-plugin-rivescript/compare/0.0.2a1...0.0.2a2) + +**Merged pull requests:** + +- chore: Configure Renovate [\#5](https://github.com/OpenVoiceOS/ovos-solver-plugin-rivescript/pull/5) ([renovate[bot]](https://github.com/apps/renovate)) + ## [0.0.2a1](https://github.com/OpenVoiceOS/ovos-solver-plugin-rivescript/tree/0.0.2a1) (2025-11-22) [Full Changelog](https://github.com/OpenVoiceOS/ovos-solver-plugin-rivescript/compare/V0.0.1...0.0.2a1) From 5af17de9926c9904b282b372bfae6f25fb2aeabe Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 19 Dec 2025 20:43:42 +0000 Subject: [PATCH 07/21] chore(deps): update dependency python to 3.14 (#6) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/publish_stable.yml | 2 +- .github/workflows/release_workflow.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/publish_stable.yml b/.github/workflows/publish_stable.yml index 5120025..32010b4 100644 --- a/.github/workflows/publish_stable.yml +++ b/.github/workflows/publish_stable.yml @@ -26,7 +26,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v1 with: - python-version: "3.11" + python-version: "3.14" - name: Install Build Tools run: | python -m pip install build wheel diff --git a/.github/workflows/release_workflow.yml b/.github/workflows/release_workflow.yml index 9974fae..c30d94b 100644 --- a/.github/workflows/release_workflow.yml +++ b/.github/workflows/release_workflow.yml @@ -46,7 +46,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v1 with: - python-version: "3.11" + python-version: "3.14" - name: Install Build Tools run: | python -m pip install build wheel @@ -75,7 +75,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v2 with: - python-version: '3.10' + python-version: '3.14' - name: Get version from setup.py id: get_version From 73b316f182ca24204da69cad5c9aa4f6b843c1a3 Mon Sep 17 00:00:00 2001 From: JarbasAl Date: Fri, 19 Dec 2025 20:45:57 +0000 Subject: [PATCH 08/21] Increment Version to 0.0.2a3 --- ovos_solver_rivescript_plugin/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ovos_solver_rivescript_plugin/version.py b/ovos_solver_rivescript_plugin/version.py index 6e7e2ae..b94a996 100644 --- a/ovos_solver_rivescript_plugin/version.py +++ b/ovos_solver_rivescript_plugin/version.py @@ -2,5 +2,5 @@ VERSION_MAJOR = 0 VERSION_MINOR = 0 VERSION_BUILD = 2 -VERSION_ALPHA = 2 +VERSION_ALPHA = 3 # END_VERSION_BLOCK From 629407149136309580ea3b9dce04cdc126b1dd52 Mon Sep 17 00:00:00 2001 From: JarbasAl Date: Fri, 19 Dec 2025 20:46:27 +0000 Subject: [PATCH 09/21] Update Changelog --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d7f86a..e75dd38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [0.0.2a3](https://github.com/OpenVoiceOS/ovos-solver-plugin-rivescript/tree/0.0.2a3) (2025-12-19) + +[Full Changelog](https://github.com/OpenVoiceOS/ovos-solver-plugin-rivescript/compare/0.0.2a2...0.0.2a3) + +**Merged pull requests:** + +- chore\(deps\): update dependency python to 3.14 [\#6](https://github.com/OpenVoiceOS/ovos-solver-plugin-rivescript/pull/6) ([renovate[bot]](https://github.com/apps/renovate)) + ## [0.0.2a2](https://github.com/OpenVoiceOS/ovos-solver-plugin-rivescript/tree/0.0.2a2) (2025-12-18) [Full Changelog](https://github.com/OpenVoiceOS/ovos-solver-plugin-rivescript/compare/0.0.2a1...0.0.2a2) From 326e5cbb6b105ca4829987a348cefde6e035e8c4 Mon Sep 17 00:00:00 2001 From: JarbasAI <33701864+JarbasAl@users.noreply.github.com> Date: Sat, 1 Aug 2026 01:42:56 +0100 Subject: [PATCH 10/21] docs: rewrite README in Simplified Technical English (#15) Co-authored-by: Claude Sonnet 5 --- README.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 6f18a51..efb8d48 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,16 @@ # Rivescript Chatbot - -Give Mycroft some sass with Rivescript! -Leverages the [Alice chatbot](https://www.chatbots.org/chatbot/a.l.i.c.e/) to create some fun interactions. Phrases not explicitly handled by other skills will be run by the chatbot, so nearly every interaction will have _some_ response. But be warned, Mycroft might become a bit obnoxious... +This plugin is a question solver that answers with a [Rivescript](https://www.rivescript.com/) chatbot. It uses the [Alice chatbot](https://www.chatbots.org/chatbot/a.l.i.c.e/) brain to answer phrases that no other skill handles, so almost every input gets some response. Answers can be casual and a bit sassy. + +## Examples -## Examples * "Do you like ice cream" * "Do you like dogs" * "I have a jump rope" - ## Usage -Spoken answers api with a Rivescript backend +The plugin exposes a spoken-answers API with a Rivescript backend. ```python from ovos_solver_rivescript_plugin import RivescriptSolver @@ -26,3 +24,8 @@ sentence = d.spoken_answer("Do you like ice cream", {"lang": "pt-pt"}) print(sentence) # O que queres mesmo saber? ``` + +## Related projects + +* [OpenVoiceOS/ovos-plugin-manager](https://github.com/OpenVoiceOS/ovos-plugin-manager): loads and manages solver plugins like this one. +* [OpenVoiceOS/ovos-persona-server](https://github.com/OpenVoiceOS/ovos-persona-server): runs solver plugins as chat personas. From 05686dfc1bd63926406d03d3f8e32451cc134017 Mon Sep 17 00:00:00 2001 From: JarbasAl Date: Sat, 1 Aug 2026 00:43:39 +0000 Subject: [PATCH 11/21] Increment Version to 0.0.2a4 --- ovos_solver_rivescript_plugin/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ovos_solver_rivescript_plugin/version.py b/ovos_solver_rivescript_plugin/version.py index b94a996..263731d 100644 --- a/ovos_solver_rivescript_plugin/version.py +++ b/ovos_solver_rivescript_plugin/version.py @@ -2,5 +2,5 @@ VERSION_MAJOR = 0 VERSION_MINOR = 0 VERSION_BUILD = 2 -VERSION_ALPHA = 3 +VERSION_ALPHA = 4 # END_VERSION_BLOCK From 79698e8276dd4d2aa5d84c8afd2b6e9386820d59 Mon Sep 17 00:00:00 2001 From: JarbasAl Date: Sat, 1 Aug 2026 00:44:53 +0000 Subject: [PATCH 12/21] Update Changelog --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e75dd38..a9d5610 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [0.0.2a4](https://github.com/OpenVoiceOS/ovos-solver-plugin-rivescript/tree/0.0.2a4) (2026-08-01) + +[Full Changelog](https://github.com/OpenVoiceOS/ovos-solver-plugin-rivescript/compare/0.0.2a3...0.0.2a4) + +**Merged pull requests:** + +- docs: rewrite README in Simplified Technical English [\#15](https://github.com/OpenVoiceOS/ovos-solver-plugin-rivescript/pull/15) ([JarbasAl](https://github.com/JarbasAl)) + ## [0.0.2a3](https://github.com/OpenVoiceOS/ovos-solver-plugin-rivescript/tree/0.0.2a3) (2025-12-19) [Full Changelog](https://github.com/OpenVoiceOS/ovos-solver-plugin-rivescript/compare/0.0.2a2...0.0.2a3) From 4c8927bc725080369d5656ddeea93d32c9e4de8e Mon Sep 17 00:00:00 2001 From: JarbasAI <33701864+JarbasAl@users.noreply.github.com> Date: Sun, 2 Aug 2026 17:50:40 +0100 Subject: [PATCH 13/21] ci: migrate release workflow to shared OpenVoiceOS automations (#16) The legacy workflow calls TigreGotico/gh-automations@master for tagging plus a hand-rolled pypa/gh-action-pypi-publish job that publishes to Test PyPI, not real PyPI. Replace the whole workflow with the standard OpenVoiceOS pattern (see OpenVoiceOS/ovos-gguf-plugin), calling the maintained OpenVoiceOS/gh-automations publish-alpha.yml with publish_pypi: true. AI-Generated Change: - Model: claude-sonnet-4-6 - Task: fix broken alpha-release-to-PyPI pipeline --- .github/workflows/release_workflow.yml | 98 ++------------------------ 1 file changed, 6 insertions(+), 92 deletions(-) diff --git a/.github/workflows/release_workflow.yml b/.github/workflows/release_workflow.yml index c30d94b..a27b96b 100644 --- a/.github/workflows/release_workflow.yml +++ b/.github/workflows/release_workflow.yml @@ -1,108 +1,22 @@ name: Release Alpha and Propose Stable on: + workflow_dispatch: pull_request: types: [closed] branches: [dev] jobs: publish_alpha: - if: github.event.pull_request.merged == true - uses: TigreGotico/gh-automations/.github/workflows/publish-alpha.yml@master + if: github.event.pull_request.merged == true || github.event_name == 'workflow_dispatch' + uses: OpenVoiceOS/gh-automations/.github/workflows/publish-alpha.yml@dev secrets: inherit with: branch: 'dev' version_file: 'ovos_solver_rivescript_plugin/version.py' - setup_py: 'setup.py' update_changelog: true publish_prerelease: true + propose_release: true changelog_max_issues: 100 - - notify: - if: github.event.pull_request.merged == true - needs: publish_alpha - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Send message to Matrix bots channel - id: matrix-chat-message - uses: fadenb/matrix-chat-message@v0.0.6 - with: - homeserver: 'matrix.org' - token: ${{ secrets.MATRIX_TOKEN }} - channel: '!WjxEKjjINpyBRPFgxl:krbel.duckdns.org' - message: | - new ${{ github.event.repository.name }} PR merged! https://github.com/${{ github.repository }}/pull/${{ github.event.number }} - - publish_pypi: - needs: publish_alpha - if: success() # Ensure this job only runs if the previous job succeeds - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - with: - ref: dev - fetch-depth: 0 # otherwise, there would be errors pushing refs to the destination repository. - - name: Setup Python - uses: actions/setup-python@v1 - with: - python-version: "3.14" - - name: Install Build Tools - run: | - python -m pip install build wheel - - name: version - run: echo "::set-output name=version::$(python setup.py --version)" - id: version - - name: Build Distribution Packages - run: | - python setup.py sdist bdist_wheel - - name: Publish to Test PyPI - uses: pypa/gh-action-pypi-publish@master - with: - password: ${{secrets.PYPI_TOKEN}} - - - propose_release: - needs: publish_alpha - if: success() # Ensure this job only runs if the previous job succeeds - runs-on: ubuntu-latest - steps: - - name: Checkout dev branch - uses: actions/checkout@v3 - with: - ref: dev - - - name: Setup Python - uses: actions/setup-python@v2 - with: - python-version: '3.14' - - - name: Get version from setup.py - id: get_version - run: | - VERSION=$(python setup.py --version) - echo "VERSION=$VERSION" >> $GITHUB_ENV - - - name: Create and push new branch - run: | - git checkout -b release-${{ env.VERSION }} - git push origin release-${{ env.VERSION }} - - - name: Open Pull Request from dev to master - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - # Variables - BRANCH_NAME="release-${{ env.VERSION }}" - BASE_BRANCH="master" - HEAD_BRANCH="release-${{ env.VERSION }}" - PR_TITLE="Release ${{ env.VERSION }}" - PR_BODY="Human review requested!" - - # Create a PR using GitHub API - curl -X POST \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: token $GITHUB_TOKEN" \ - -d "{\"title\":\"$PR_TITLE\",\"body\":\"$PR_BODY\",\"head\":\"$HEAD_BRANCH\",\"base\":\"$BASE_BRANCH\"}" \ - https://api.github.com/repos/${{ github.repository }}/pulls - + publish_pypi: true + notify_matrix: true From d213cdc1275e290f8bd6a74fdc21963bbd33efa1 Mon Sep 17 00:00:00 2001 From: JarbasAl <33701864+JarbasAl@users.noreply.github.com> Date: Sun, 2 Aug 2026 16:50:52 +0000 Subject: [PATCH 14/21] Increment Version to 0.0.2a5 --- ovos_solver_rivescript_plugin/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ovos_solver_rivescript_plugin/version.py b/ovos_solver_rivescript_plugin/version.py index 263731d..643f2af 100644 --- a/ovos_solver_rivescript_plugin/version.py +++ b/ovos_solver_rivescript_plugin/version.py @@ -2,5 +2,5 @@ VERSION_MAJOR = 0 VERSION_MINOR = 0 VERSION_BUILD = 2 -VERSION_ALPHA = 4 +VERSION_ALPHA = 5 # END_VERSION_BLOCK From ac260b61be4a94bb0c8b4c020ad6dbcda8f3b55c Mon Sep 17 00:00:00 2001 From: JarbasAl <33701864+JarbasAl@users.noreply.github.com> Date: Sun, 2 Aug 2026 16:51:13 +0000 Subject: [PATCH 15/21] Update Changelog --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a9d5610..64407c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [0.0.2a5](https://github.com/OpenVoiceOS/ovos-solver-plugin-rivescript/tree/0.0.2a5) (2026-08-02) + +[Full Changelog](https://github.com/OpenVoiceOS/ovos-solver-plugin-rivescript/compare/0.0.2a4...0.0.2a5) + +**Merged pull requests:** + +- ci: migrate release workflow to shared OpenVoiceOS automations [\#16](https://github.com/OpenVoiceOS/ovos-solver-plugin-rivescript/pull/16) ([JarbasAl](https://github.com/JarbasAl)) + ## [0.0.2a4](https://github.com/OpenVoiceOS/ovos-solver-plugin-rivescript/tree/0.0.2a4) (2026-08-01) [Full Changelog](https://github.com/OpenVoiceOS/ovos-solver-plugin-rivescript/compare/0.0.2a3...0.0.2a4) From dc6e6412fa44871fc6efe6b48dfc9585ee255082 Mon Sep 17 00:00:00 2001 From: JarbasAI <33701864+JarbasAl@users.noreply.github.com> Date: Fri, 14 Aug 2026 02:09:22 +0100 Subject: [PATCH 16/21] feat: migrate to pyproject.toml and register as opm.agents.chat (#18) Move packaging from setup.py to pyproject.toml, matching the sibling ovos-solver-plugin-aiml layout, and register the plugin under the modern opm.agents.chat entry point group by porting RiveScript to ChatEngine. The legacy neon.plugin.solver entry point is kept pointing at the original RivescriptSolver class, so nothing that still looks there breaks. Co-authored-by: Claude Opus 5 --- .github/workflows/build-tests.yml | 14 +++++ .github/workflows/publish_stable.yml | 77 +++++------------------ ovos_solver_rivescript_plugin/__init__.py | 54 +++++++++++++++- ovos_solver_rivescript_plugin/version.py | 8 ++- pyproject.toml | 46 ++++++++++++++ requirements.txt | 2 - setup.py | 61 ------------------ test/test_plugin.py | 62 ++++++++++++++++++ 8 files changed, 194 insertions(+), 130 deletions(-) create mode 100644 .github/workflows/build-tests.yml create mode 100644 pyproject.toml delete mode 100644 requirements.txt delete mode 100755 setup.py create mode 100644 test/test_plugin.py diff --git a/.github/workflows/build-tests.yml b/.github/workflows/build-tests.yml new file mode 100644 index 0000000..95c6f69 --- /dev/null +++ b/.github/workflows/build-tests.yml @@ -0,0 +1,14 @@ +name: Build Tests + +on: + pull_request: + branches: [dev, master] + workflow_dispatch: + +jobs: + build: + uses: OpenVoiceOS/gh-automations/.github/workflows/build-tests.yml@dev + with: + python_versions: '["3.10", "3.11", "3.12", "3.13", "3.14"]' + install_extras: 'test' + test_path: 'test' diff --git a/.github/workflows/publish_stable.yml b/.github/workflows/publish_stable.yml index 32010b4..5e43940 100644 --- a/.github/workflows/publish_stable.yml +++ b/.github/workflows/publish_stable.yml @@ -1,72 +1,23 @@ -name: Stable Release +name: Publish Stable Release + on: + workflow_dispatch: push: branches: [master] - workflow_dispatch: + +permissions: + contents: write jobs: publish_stable: - uses: TigreGotico/gh-automations/.github/workflows/publish-stable.yml@master - secrets: inherit + if: github.actor != 'github-actions[bot]' + uses: OpenVoiceOS/gh-automations/.github/workflows/publish-stable.yml@dev + secrets: + PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} + MATRIX_TOKEN: ${{ secrets.MATRIX_TOKEN }} with: - branch: 'master' version_file: 'ovos_solver_rivescript_plugin/version.py' - setup_py: 'setup.py' + publish_pypi: true publish_release: true - - publish_pypi: - needs: publish_stable - if: success() # Ensure this job only runs if the previous job succeeds - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - with: - ref: dev - fetch-depth: 0 # otherwise, there would be errors pushing refs to the destination repository. - - name: Setup Python - uses: actions/setup-python@v1 - with: - python-version: "3.14" - - name: Install Build Tools - run: | - python -m pip install build wheel - - name: version - run: echo "::set-output name=version::$(python setup.py --version)" - id: version - - name: Create Release - id: create_release - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token - with: - tag_name: V${{ steps.version.outputs.version }} - release_name: Release ${{ steps.version.outputs.version }} - body: | - Changes in this Release - ${{ steps.changelog.outputs.changelog }} - draft: false - prerelease: true - commitish: dev - - name: Build Distribution Packages - run: | - python setup.py sdist bdist_wheel - - name: Publish to Test PyPI - uses: pypa/gh-action-pypi-publish@master - with: - password: ${{secrets.PYPI_TOKEN}} - - - sync_dev: - needs: publish_stable - if: success() # Ensure this job only runs if the previous job succeeds - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 0 # otherwise, there would be errors pushing refs to the destination repository. - ref: master - - name: Push master -> dev - uses: ad-m/github-push-action@master - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - branch: dev \ No newline at end of file + sync_dev: true + notify_matrix: true diff --git a/ovos_solver_rivescript_plugin/__init__.py b/ovos_solver_rivescript_plugin/__init__.py index 330b5eb..d5c8cff 100644 --- a/ovos_solver_rivescript_plugin/__init__.py +++ b/ovos_solver_rivescript_plugin/__init__.py @@ -1,13 +1,23 @@ import os from datetime import date from os.path import dirname, isdir -from typing import Optional +from typing import List, Optional from ovos_plugin_manager.templates.solvers import QuestionSolver from ovos_utils.log import LOG from ovos_utils.xdg_utils import xdg_data_home from rivescript import RiveScript +try: + from ovos_plugin_manager.templates.agents import ChatEngine, AgentMessage, MessageRole +except ImportError: + # ovos-plugin-manager < 2.2.3a1 does not ship the agents module yet. + # The legacy QuestionSolver below still works without it; only the + # ChatEngine registration is unavailable on such an old install. + ChatEngine = object + AgentMessage = None + MessageRole = None + class RivescriptBot: XDG_PATH = f"{xdg_data_home()}/rivescript" @@ -124,7 +134,49 @@ def get_spoken_answer(self, query: str, return self.brain.ask_brain(query) +class RivescriptChatEngine(ChatEngine): + """RiveScript chatbot exposed as a modern ChatEngine agent plugin. + + RiveScript is a pattern-matching chatbot: it has no notion of tool + calling, so ``tools`` is accepted (callers pass it by keyword) and + ignored, and ``supports_tools`` stays at the base default of False. + """ + + def __init__(self, config=None): + config = config or {"lang": "en-us"} + lang = config.get("lang") or "en-us" + if lang != "en-us" and lang not in os.listdir(RivescriptBot.XDG_PATH): + config["lang"] = lang = "en-us" + super().__init__(config) + self.brain = RivescriptBot(lang, self.config) + self.brain.load_brain() + + def continue_chat(self, messages: List["AgentMessage"], + session_id: str = "default", + lang: Optional[str] = None, + units: Optional[str] = None, + tools=None) -> "AgentMessage": + """ + Answer the latest user message via the RiveScript brain. + + RiveScript itself has no concept of chat history beyond the single + reply it is asked for, so only the most recent user message is used; + earlier turns in ``messages`` are ignored, same as upstream RiveScript + usage elsewhere in this plugin. + """ + query = next((m.content for m in reversed(messages) + if m.role == MessageRole.USER), "") + if not query: + return AgentMessage(role=MessageRole.ASSISTANT, content="") + answer = self.brain.ask_brain(query) or "" + return AgentMessage(role=MessageRole.ASSISTANT, content=answer) + + if __name__ == "__main__": bot = RivescriptSolver() print(bot.get_spoken_answer("hello!")) print(bot.spoken_answer("Qual é a tua comida favorita?", lang="pt-pt")) + + chat = RivescriptChatEngine() + reply = chat.continue_chat([AgentMessage(role=MessageRole.USER, content="hello!")]) + print(reply.content) diff --git a/ovos_solver_rivescript_plugin/version.py b/ovos_solver_rivescript_plugin/version.py index 643f2af..bd238c8 100644 --- a/ovos_solver_rivescript_plugin/version.py +++ b/ovos_solver_rivescript_plugin/version.py @@ -1,6 +1,8 @@ # START_VERSION_BLOCK VERSION_MAJOR = 0 -VERSION_MINOR = 0 -VERSION_BUILD = 2 -VERSION_ALPHA = 5 +VERSION_MINOR = 1 +VERSION_BUILD = 0 +VERSION_ALPHA = 1 # END_VERSION_BLOCK + +__version__ = f"{VERSION_MAJOR}.{VERSION_MINOR}.{VERSION_BUILD}" + (f"a{VERSION_ALPHA}" if VERSION_ALPHA else "") diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..96ea131 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,46 @@ +[build-system] +requires = ["setuptools>=61.0", "wheel"] +build-backend = "setuptools.build_meta" + +[project] +name = "ovos-solver-rivescript-plugin" +dynamic = ["readme", "version"] +description = "A question solver plugin for ovos/neon/mycroft" +authors = [{ name = "JarbasAi", email = "jarbasai@mailfence.com" }] +license = { text = "MIT" } +requires-python = ">=3.9" +keywords = ["mycroft", "plugin", "utterance", "fallback", "query", "rivescript"] + +dependencies = [ + "rivescript", + "ovos-plugin-manager>=2.6.1a1,<3.0.0", +] + +[project.urls] +Homepage = "https://github.com/OpenVoiceOS/ovos-solver-plugin-rivescript" + +[project.optional-dependencies] +test = [ + "pytest>=7.0.0,<9", + "pytest-timeout>=2.0.0", +] + +[project.entry-points."opm.agents.chat"] +"ovos-solver-rivescript-plugin" = "ovos_solver_rivescript_plugin:RivescriptChatEngine" + +[project.entry-points."neon.plugin.solver"] +"ovos-solver-rivescript-plugin" = "ovos_solver_rivescript_plugin:RivescriptSolver" + +[tool.setuptools] +packages = ["ovos_solver_rivescript_plugin"] +include-package-data = true + +[tool.setuptools.package-data] +ovos_solver_rivescript_plugin = ["brain/**"] + +[tool.setuptools.dynamic] +readme = { file = "README.md", content-type = "text/markdown" } +version = { attr = "ovos_solver_rivescript_plugin.version.__version__" } + +[tool.pytest.ini_options] +testpaths = ["test"] diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 96e48ec..0000000 --- a/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -rivescript -ovos-plugin-manager>=0.0.26,<3.0.0 diff --git a/setup.py b/setup.py deleted file mode 100755 index 3f2d139..0000000 --- a/setup.py +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/env python3 -import os -from setuptools import setup - -BASEDIR = os.path.abspath(os.path.dirname(__file__)) - - -def required(requirements_file): - """ Read requirements file and remove comments and empty lines. """ - with open(os.path.join(BASEDIR, requirements_file), 'r') as f: - requirements = f.read().splitlines() - if 'MYCROFT_LOOSE_REQUIREMENTS' in os.environ: - print('USING LOOSE REQUIREMENTS!') - requirements = [r.replace('==', '>=').replace('~=', '>=') for r in requirements] - return [pkg for pkg in requirements - if pkg.strip() and not pkg.startswith("#")] - - -with open(f"{BASEDIR}/README.md", "r") as f: - long_description = f.read() - -def get_version(): - """ Find the version of the package""" - version_file = os.path.join(BASEDIR, 'ovos_solver_rivescript_plugin', 'version.py') - major, minor, build, alpha = (None, None, None, None) - with open(version_file) as f: - for line in f: - if 'VERSION_MAJOR' in line: - major = line.split('=')[1].strip() - elif 'VERSION_MINOR' in line: - minor = line.split('=')[1].strip() - elif 'VERSION_BUILD' in line: - build = line.split('=')[1].strip() - elif 'VERSION_ALPHA' in line: - alpha = line.split('=')[1].strip() - - if ((major and minor and build and alpha) or - '# END_VERSION_BLOCK' in line): - break - version = f"{major}.{minor}.{build}" - if alpha and int(alpha) > 0: - version += f"a{alpha}" - return version - -PLUGIN_ENTRY_POINT = 'ovos-solver-rivescript-plugin=ovos_solver_rivescript_plugin:RivescriptSolver' -setup( - name='ovos-solver-rivescript-plugin', - version=get_version(), - description='A question solver plugin for ovos/neon/mycroft', - url='https://github.com/OpenVoiceOS/ovos-solver-rivescript-plugin', - author='jarbasai', - author_email='jarbasai@mailfence.com', - license='MIT', - packages=['ovos_solver_rivescript_plugin'], - zip_safe=True, - keywords='mycroft plugin utterance fallback query', - entry_points={'neon.plugin.solver': PLUGIN_ENTRY_POINT}, - install_requires=required("requirements.txt"), - long_description=long_description, - long_description_content_type='text/markdown' -) diff --git a/test/test_plugin.py b/test/test_plugin.py new file mode 100644 index 0000000..8d00c12 --- /dev/null +++ b/test/test_plugin.py @@ -0,0 +1,62 @@ +"""Smoke tests: the plugin loads and answers, and is discoverable under both +the legacy question-solver entry point and the modern chat-engine entry +point. +""" +import unittest + +from ovos_plugin_manager.templates.agents import AgentMessage, MessageRole +from ovos_plugin_manager.utils import find_plugins + +from ovos_solver_rivescript_plugin import RivescriptBot, RivescriptChatEngine, RivescriptSolver + + +class TestRivescriptSolver(unittest.TestCase): + def test_brain_answers(self): + # RivescriptSolver.__init__ hardcodes enable_tx=True, which makes the + # base QuestionSolver eagerly build a language-translation plugin at + # construction time even when no translation is ever performed. That + # is a pre-existing base-class quirk unrelated to this migration, and + # it means constructing RivescriptSolver requires a translate plugin + # to be installed. Exercise the underlying brain directly instead, + # which is what actually answers queries. + bot = RivescriptBot() + bot.load_brain() + answer = bot.ask_brain("hello") + self.assertIsInstance(answer, str) + self.assertTrue(answer) + + def test_registered_under_legacy_group(self): + plugins = find_plugins("neon.plugin.solver") + self.assertIn("ovos-solver-rivescript-plugin", plugins) + self.assertIs(plugins["ovos-solver-rivescript-plugin"], RivescriptSolver) + + +class TestRivescriptChatEngine(unittest.TestCase): + def test_continue_chat(self): + engine = RivescriptChatEngine() + reply = engine.continue_chat( + [AgentMessage(role=MessageRole.USER, content="hello")] + ) + self.assertIsInstance(reply, AgentMessage) + self.assertEqual(reply.role, MessageRole.ASSISTANT) + self.assertTrue(reply.content) + + def test_continue_chat_accepts_and_ignores_tools(self): + # ChatEngine.continue_chat callers pass tools= by keyword; a pattern + # matcher has no use for it but must still accept it without raising. + engine = RivescriptChatEngine() + reply = engine.continue_chat( + [AgentMessage(role=MessageRole.USER, content="hello")], + tools=[{"type": "function", "function": {"name": "noop"}}], + ) + self.assertIsInstance(reply, AgentMessage) + self.assertFalse(engine.supports_tools) + + def test_registered_under_chat_group(self): + plugins = find_plugins("opm.agents.chat") + self.assertIn("ovos-solver-rivescript-plugin", plugins) + self.assertIs(plugins["ovos-solver-rivescript-plugin"], RivescriptChatEngine) + + +if __name__ == "__main__": + unittest.main() From da8774054d47020c3fbe03c1f94fc38c2de9180c Mon Sep 17 00:00:00 2001 From: JarbasAl <33701864+JarbasAl@users.noreply.github.com> Date: Fri, 14 Aug 2026 01:09:45 +0000 Subject: [PATCH 17/21] Increment Version to 0.1.0a2 --- ovos_solver_rivescript_plugin/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ovos_solver_rivescript_plugin/version.py b/ovos_solver_rivescript_plugin/version.py index bd238c8..39a66c5 100644 --- a/ovos_solver_rivescript_plugin/version.py +++ b/ovos_solver_rivescript_plugin/version.py @@ -2,7 +2,7 @@ VERSION_MAJOR = 0 VERSION_MINOR = 1 VERSION_BUILD = 0 -VERSION_ALPHA = 1 +VERSION_ALPHA = 2 # END_VERSION_BLOCK __version__ = f"{VERSION_MAJOR}.{VERSION_MINOR}.{VERSION_BUILD}" + (f"a{VERSION_ALPHA}" if VERSION_ALPHA else "") From 6b44e2f049ba8fcafcb326d54f1011c66734863f Mon Sep 17 00:00:00 2001 From: JarbasAl <33701864+JarbasAl@users.noreply.github.com> Date: Fri, 14 Aug 2026 01:10:18 +0000 Subject: [PATCH 18/21] Update Changelog --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 64407c9..b654845 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [0.1.0a2](https://github.com/OpenVoiceOS/ovos-solver-plugin-rivescript/tree/0.1.0a2) (2026-08-14) + +[Full Changelog](https://github.com/OpenVoiceOS/ovos-solver-plugin-rivescript/compare/0.0.2a5...0.1.0a2) + +**Merged pull requests:** + +- Migrate to pyproject.toml and register as ChatEngine \(opm.agents.chat\) [\#18](https://github.com/OpenVoiceOS/ovos-solver-plugin-rivescript/pull/18) ([JarbasAl](https://github.com/JarbasAl)) + ## [0.0.2a5](https://github.com/OpenVoiceOS/ovos-solver-plugin-rivescript/tree/0.0.2a5) (2026-08-02) [Full Changelog](https://github.com/OpenVoiceOS/ovos-solver-plugin-rivescript/compare/0.0.2a4...0.0.2a5) From 8e0f159961f30579ee491492fda504ce30cb7821 Mon Sep 17 00:00:00 2001 From: JarbasAI <33701864+JarbasAl@users.noreply.github.com> Date: Sat, 15 Aug 2026 14:04:29 +0100 Subject: [PATCH 19/21] fix: bot identity reflects the RiveScript lineage, not Mycroft or the demo persona (#22) The RiveScript bot's identity was leaking the upstream RiveScript demo personality bundled in brain/en-us/begin.rive ("Aiden" from Detroit, Michigan) and separately hardcoded name/master/website to Mycroft- or skynet-flavored placeholders (master="skynet", website="openvoiceos.com"). A prior version of this fix replaced those with generic "OVOS" branding, but RiveScript is a historical chatbot language with its own lineage: it was created by Noah Petherbridge and first released in 2005, originally in Perl (https://www.rivescript.com/about, https://www.rivescript.com/history). The defaults now name that lineage - name is "RiveScript", master credits Petherbridge as a public authorship fact (not private biography), website points at rivescript.com, and age derives from RIVESCRIPT_BIRTH_YEAR (2005) instead of an arbitrary org creation date. location/city name RiveScript's own documented origin ("CPAN" / "the Perl programming language" - it grew out of Chatbot::Alpha, was first written in Perl, and was published under its own root namespace on CPAN, per rivescript.com/history) instead of a guess about the person, since there is no sourced hometown or birthday for Petherbridge, and instead of a bland placeholder that throws away the language's history. All identity variables remain configurable via settings keys, the try/except guard around birth_year still prevents a bad config value from crashing QuestionSolversService.load_plugins, and location/city are still always set from a default so the demo brain's Michigan/Detroit values can never leak through unset. Also folds in a CI gap found while investigating this repo alongside its sibling ovos-solver-plugin-aiml: this repo had no lint workflow and no license-check workflow at all, while aiml already runs both against the same gh-automations reusable workflows. Ports aiml's lint.yml and license_check.yml verbatim. Co-authored-by: Claude Sonnet 5 --- .github/workflows/license_check.yml | 11 +++ .github/workflows/lint.yml | 14 +++ ovos_solver_rivescript_plugin/__init__.py | 48 +++++++--- test/test_bot_identity.py | 101 ++++++++++++++++++++++ 4 files changed, 161 insertions(+), 13 deletions(-) create mode 100644 .github/workflows/license_check.yml create mode 100644 .github/workflows/lint.yml create mode 100644 test/test_bot_identity.py diff --git a/.github/workflows/license_check.yml b/.github/workflows/license_check.yml new file mode 100644 index 0000000..8757eee --- /dev/null +++ b/.github/workflows/license_check.yml @@ -0,0 +1,11 @@ +name: License Check + +on: + pull_request: + branches: [dev] + workflow_dispatch: + +jobs: + license_check: + uses: OpenVoiceOS/gh-automations/.github/workflows/license-check.yml@dev + secrets: inherit diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..aa45c3d --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,14 @@ +name: Lint + +on: + pull_request: + branches: [dev, master, main] + workflow_dispatch: + +jobs: + lint: + uses: OpenVoiceOS/gh-automations/.github/workflows/lint.yml@dev + secrets: inherit + with: + ruff: true + pre_commit: false diff --git a/ovos_solver_rivescript_plugin/__init__.py b/ovos_solver_rivescript_plugin/__init__.py index d5c8cff..e829911 100644 --- a/ovos_solver_rivescript_plugin/__init__.py +++ b/ovos_solver_rivescript_plugin/__init__.py @@ -23,6 +23,23 @@ class RivescriptBot: XDG_PATH = f"{xdg_data_home()}/rivescript" os.makedirs(XDG_PATH, exist_ok=True) + # Default bot identity reflects RiveScript itself, not the upstream demo + # personality bundled in brain/en-us/begin.rive ("Aiden" from Detroit, + # Michigan - sample-brain placeholders, not creator-reflective) and not + # the Mycroft project either. RiveScript was created by Noah + # Petherbridge and first released in 2005 (originally in Perl); see + # https://www.rivescript.com/about and https://www.rivescript.com/history + # There is no sourced hometown or birthday for Petherbridge, so location/ + # city name RiveScript's own documented origin instead of the person's: + # it grew out of Chatbot::Alpha and was first written in Perl, published + # under its own root namespace on CPAN. https://www.rivescript.com/history + DEFAULT_NAME = "RiveScript" + RIVESCRIPT_BIRTH_YEAR = 2005 + DEFAULT_LOCATION = "CPAN" + DEFAULT_CITY = "the Perl programming language" + DEFAULT_MASTER = "Noah Petherbridge" + DEFAULT_WEBSITE = "rivescript.com" + def __init__(self, lang="en-us", settings=None): self.settings = settings or {} self.lang = lang @@ -36,12 +53,10 @@ def __init__(self, lang="en-us", settings=None): def load_brain(self): # secondary personal bot info - if "birthday" not in self.settings: - self.settings["birthday"] = "May 23, 2016" if "sex" not in self.settings: self.settings["sex"] = "undefined" if "master" not in self.settings: - self.settings["master"] = "skynet" + self.settings["master"] = self.DEFAULT_MASTER if "eye_color" not in self.settings: self.settings["eye_color"] = "blue" if "hair" not in self.settings: @@ -65,16 +80,19 @@ def load_brain(self): if "job" not in self.settings: self.settings["job"] = "Personal Assistant" if "website" not in self.settings: - self.settings["website"] = "openvoiceos.com" + self.settings["website"] = self.DEFAULT_WEBSITE if "pet" not in self.settings: self.settings["pet"] = "bugs" if "interests" not in self.settings: self.settings["interests"] = "I am interested in all kinds of " \ "things. We can talk about anything." + if "location" not in self.settings: + self.settings["location"] = self.DEFAULT_LOCATION + if "city" not in self.settings: + self.settings["city"] = self.DEFAULT_CITY self.rs.load_directory(self.brain_path) self.rs.sort_replies() - self.rs.set_variable("birthday", self.settings["birthday"]) self.rs.set_variable("sex", self.settings["sex"]) self.rs.set_variable("eyes", self.settings["eye_color"]) self.rs.set_variable("hair", self.settings["hair"]) @@ -91,14 +109,18 @@ def load_brain(self): self.rs.set_variable("website", self.settings["website"]) self.rs.set_variable("master", self.settings["master"]) self.rs.set_variable("interests", self.settings["interests"]) - self.rs.set_variable("name", self.settings.get("name", "mycroft")) - - self.rs.set_variable("age", str(date.today().year - 2016)) - # TODO - location from mycroft.conf - # self.rs.set_variable("location", - # self.location["city"]["state"]["country"][ - # "name"]) - # self.rs.set_variable("city", self.location_pretty) + self.rs.set_variable("name", self.settings.get("name", self.DEFAULT_NAME)) + self.rs.set_variable("location", self.settings["location"]) + self.rs.set_variable("city", self.settings["city"]) + + try: + birth_year = int(self.settings.get("birth_year", self.RIVESCRIPT_BIRTH_YEAR)) + except (TypeError, ValueError) as e: + LOG.warning(f"Invalid birth_year in config ({e}); " + f"falling back to {self.RIVESCRIPT_BIRTH_YEAR}") + birth_year = self.RIVESCRIPT_BIRTH_YEAR + age = self.settings.get("age", str(date.today().year - birth_year)) + self.rs.set_variable("age", str(age)) def ask_brain(self, utterance): try: diff --git a/test/test_bot_identity.py b/test/test_bot_identity.py new file mode 100644 index 0000000..3fee9f4 --- /dev/null +++ b/test/test_bot_identity.py @@ -0,0 +1,101 @@ +"""Regression tests: bot identity must reflect the RiveScript lineage, not +Mycroft or the upstream demo persona, and must be configurable. + +This plugin is not Mycroft and OVOS does not carry Mycroft attribution, so +the RiveScript identity variables must never default to Mycroft's identity, +and must never default to the upstream RiveScript demo personality bundled +in brain/en-us/begin.rive either ("Aiden" from Detroit, Michigan). Every +identity variable must be overridable via config. +""" +import unittest +from datetime import date + +from ovos_plugin_manager.templates.agents import AgentMessage, MessageRole + +from ovos_solver_rivescript_plugin import RivescriptBot, RivescriptChatEngine + + +class TestBotIdentity(unittest.TestCase): + def test_default_name_is_not_mycroft(self): + bot = RivescriptBot() + bot.load_brain() + name = bot.rs.get_variable("name") + self.assertNotEqual(name.lower(), "mycroft") + self.assertEqual(name, RivescriptBot.DEFAULT_NAME) + + def test_default_age_derives_from_rivescript_birth_year_not_mycroft(self): + bot = RivescriptBot() + bot.load_brain() + expected = str(date.today().year - RivescriptBot.RIVESCRIPT_BIRTH_YEAR) + self.assertEqual(bot.rs.get_variable("age"), expected) + + def test_default_master_is_not_mycroft_or_skynet(self): + bot = RivescriptBot() + bot.load_brain() + master = bot.rs.get_variable("master") + self.assertNotEqual(master.lower(), "mycroft") + self.assertNotEqual(master.lower(), "skynet") + self.assertEqual(master, RivescriptBot.DEFAULT_MASTER) + + def test_configured_name_reaches_the_answer(self): + engine = RivescriptChatEngine({"lang": "en-us", "name": "Zorb"}) + self.assertEqual(engine.brain.rs.get_variable("name"), "Zorb") + reply = engine.continue_chat( + [AgentMessage(role=MessageRole.USER, content="what is your name")] + ) + self.assertIn("zorb", reply.content.lower()) + + def test_default_location_and_city_are_not_the_upstream_demo(self): + # brain/en-us/begin.rive hardcodes "! var location = Michigan" and + # "! var city = Detroit" (the upstream RiveScript demo persona, + # "Aiden"). Both must be overridden, not left to leak through. + bot = RivescriptBot() + bot.load_brain() + self.assertNotEqual(bot.rs.get_variable("location"), "Michigan") + self.assertNotEqual(bot.rs.get_variable("city"), "Detroit") + self.assertEqual(bot.rs.get_variable("location"), RivescriptBot.DEFAULT_LOCATION) + self.assertEqual(bot.rs.get_variable("city"), RivescriptBot.DEFAULT_CITY) + + def test_default_location_and_city_name_the_language_not_the_cloud(self): + # location/city name RiveScript's own documented origin (Perl/CPAN, + # per https://www.rivescript.com/history), a fact about the + # language, not a bland placeholder and not a guess about + # Petherbridge's personal whereabouts. + bot = RivescriptBot() + bot.load_brain() + self.assertEqual(bot.rs.get_variable("location"), "CPAN") + self.assertEqual(bot.rs.get_variable("city"), "the Perl programming language") + + def test_configured_location_reaches_the_answer(self): + engine = RivescriptChatEngine({"lang": "en-us", "location": "Lisbon"}) + reply = engine.continue_chat( + [AgentMessage(role=MessageRole.USER, content="where are you from")] + ) + self.assertIn("lisbon", reply.content.lower()) + self.assertNotIn("michigan", reply.content.lower()) + + def test_configured_city_reaches_the_answer(self): + engine = RivescriptChatEngine({"lang": "en-us", "city": "Lisbon"}) + reply = engine.continue_chat( + [AgentMessage(role=MessageRole.USER, content="what city are you from")] + ) + self.assertIn("lisbon", reply.content.lower()) + self.assertNotIn("detroit", reply.content.lower()) + + def test_no_dead_birthday_constant(self): + # DEFAULT_BIRTHDAY was removed: nothing in the bundled corpus reads + # , so a constant feeding it would reach no answer. + self.assertFalse(hasattr(RivescriptBot, "DEFAULT_BIRTHDAY")) + + def test_invalid_birth_year_does_not_crash_construction(self): + # A bad config value here must degrade with a warning, not raise - + # QuestionSolversService.load_plugins has no try/except around + # plugin construction, so an uncaught ValueError here takes down the + # whole Persona, not just this handler. + engine = RivescriptChatEngine({"lang": "en-us", "birth_year": "not-a-year"}) + expected = str(date.today().year - RivescriptBot.RIVESCRIPT_BIRTH_YEAR) + self.assertEqual(engine.brain.rs.get_variable("age"), expected) + + +if __name__ == "__main__": + unittest.main() From 1432af226f0d6a7417cecd7139372d3aa592eae2 Mon Sep 17 00:00:00 2001 From: JarbasAl <33701864+JarbasAl@users.noreply.github.com> Date: Sat, 15 Aug 2026 13:04:47 +0000 Subject: [PATCH 20/21] Increment Version to 0.1.1a1 --- ovos_solver_rivescript_plugin/version.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ovos_solver_rivescript_plugin/version.py b/ovos_solver_rivescript_plugin/version.py index 39a66c5..cc79e14 100644 --- a/ovos_solver_rivescript_plugin/version.py +++ b/ovos_solver_rivescript_plugin/version.py @@ -1,8 +1,8 @@ # START_VERSION_BLOCK VERSION_MAJOR = 0 VERSION_MINOR = 1 -VERSION_BUILD = 0 -VERSION_ALPHA = 2 +VERSION_BUILD = 1 +VERSION_ALPHA = 1 # END_VERSION_BLOCK __version__ = f"{VERSION_MAJOR}.{VERSION_MINOR}.{VERSION_BUILD}" + (f"a{VERSION_ALPHA}" if VERSION_ALPHA else "") From cf5e2d43682117cf3a8d8da17228332e99f1869e Mon Sep 17 00:00:00 2001 From: JarbasAl <33701864+JarbasAl@users.noreply.github.com> Date: Sat, 15 Aug 2026 13:05:14 +0000 Subject: [PATCH 21/21] Update Changelog --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b654845..5e43af8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [0.1.1a1](https://github.com/OpenVoiceOS/ovos-solver-plugin-rivescript/tree/0.1.1a1) (2026-08-15) + +[Full Changelog](https://github.com/OpenVoiceOS/ovos-solver-plugin-rivescript/compare/0.1.0a2...0.1.1a1) + +**Merged pull requests:** + +- fix: bot identity reflects RiveScript's own origins, not Mycroft or the demo brain [\#22](https://github.com/OpenVoiceOS/ovos-solver-plugin-rivescript/pull/22) ([JarbasAl](https://github.com/JarbasAl)) + ## [0.1.0a2](https://github.com/OpenVoiceOS/ovos-solver-plugin-rivescript/tree/0.1.0a2) (2026-08-14) [Full Changelog](https://github.com/OpenVoiceOS/ovos-solver-plugin-rivescript/compare/0.0.2a5...0.1.0a2)