feat: land GUI adapter/template rework (session_id-only); fix B1-B9 (supersedes #100) - #112
feat: land GUI adapter/template rework (session_id-only); fix B1-B9 (supersedes #100)#112JarbasAl wants to merge 7 commits into
Conversation
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
Back again! I've just finished another round of automated checks. 🔄I've aggregated the results of the automated checks for this PR below. 🔨 Build TestsEnsuring the code is correctly packaged and ready. 📦 ✅ All versions pass
The bits and bytes are looking good today. 💾 |
Replace the uninstallable file:// pins with version specs: - ovos-plugin-manager>=2.1.0,<3.0.0 (carries OVOSGUIAdapterFactory) - ovos-bus-client>=1.0.0,<3.0.0 (allows 2.x), reconciled as the single source - optional 'gui' extra for ovos-legacy-mycroft-gui-plugin (display backend) - 'test' extra for the test deps Drop the now-unused tornado dependency (the WS server moved to the legacy adapter) and the stale res/**/* package-data (QML resources removed). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ovos-gui becomes a pure state/dispatch hub: it runs no WebSocket server and renders nothing itself. GUIService.\_load_adapter_plugins calls the published OVOSGUIAdapterFactory.create_all(bus, config) directly (no hasattr fallback). A headless device with zero adapters installed logs and continues with no-op dispatch instead of raising RuntimeError. Remove the in-process Tornado WS server (bus.py), the GUIExtension/homescreen machinery (extensions.py, homescreen.py, constants.py) and the bundled QML resources — these now live in the adapter plugins. Add message_types.py documenting the GUI bus protocol. BREAKING CHANGE: ovos-gui no longer starts a WebSocket server or loads QML; install an opm.gui_adapter plugin to render. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Collapse routing to a single key: session_id (shared screens share a session_id). Drop site_id from every adapter call and internal helper and remove the 3-case routing-key logic; \_session_id(message) reads context['session']['session_id'] (default 'default'). - B3: drop the dead duplicate first copies of \_safe_call/forward_to_gui/ handle_clear_namespace/\_parse_persistence; keep the live block. - B7/B8: emit gui.namespace.removed/displayed context with session_id only. - B9: remove the silent TypeError-retry-with-fewer-args in \_safe_call; log and surface signature errors. Adapters are now called as dispatch_template(template, skill_id, data, session_id), on_namespace_activated/deactivated(skill_id, session_id), on_session_update(skill_id, data, session_id), on_status_event(event, data, session_id) — matching the AbstractGUIPlugin contract. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…B4/B5) - B5: rewrite GUI_DESIGN.md routing/hook sections and add canonical docs/adapter-development/CONTRACT.md + architecture.md to the session_id-only hook signatures (name, session_id) / (msg_type, data, session_id). Drop the 3-case routing-key/site_id text and the stale OVOSGuiFactory.create signature. - B4: remove the dead GuiPage model (ovos_gui/page.py); the page-delete handlers that referenced the non-existent namespace.pages/remove_pages are gone, so gui.page.delete* no longer raises AttributeError. The template-only Namespace has no per-page model. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the Mock() adapters in test/end2end with a concrete RecordingGUIPlugin subclassing AbstractGUIPlugin (enforces handler/hook arity). Cover: real factory loading on a headless device (B1), default + UUID session_id routing, two clients sharing one session_id getting the same dispatch, multi-adapter fan-out with per-adapter failure isolation, and that the removed page-delete path no longer crashes (B4). Update unit tests to the session_id-only API: drop GuiPage/site_id, assert the real adapter call signatures, add a B1 headless-no-raise regression for the service, and derive the expected version from the constants instead of a hard-coded string. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Drive a real GUIInterface (show_weather/show_text) through NamespaceManager to a spec-conformant adapter, proving the skill-side wire format matches what ovos-gui parses and dispatches (incl. multi-adapter fanout). Adds the api-client as a test dep (git-installed in CI until released).
b896fd0 to
299ce38
Compare
The opm.gui_adapter loader (OVOSGUIAdapterFactory) is not yet on PyPI; it lives on the ovos-plugin-manager gui branch. Install it from git before the editable install, mirroring the pre_install_pip used by build_tests, so the resolver keeps the branch instead of substituting the PyPI release. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
GUI rework landing — adapter/template architecture (supersedes #100)
Lands the template/adapter rework on top of current
origin/devas a clean,reviewable diff, and fixes the release-blocking bugs from the Phase-0 audit
(
REVIEW_2026-06-20.md, B1–B9). Routing issession_idonly —site_idisdropped entirely; a shared/multi-room screen is expressed by clients sharing a
session_id.ovos-gui becomes a pure state/dispatch hub: it runs no WebSocket server and
renders nothing. It loads every installed
opm.gui_adapterplugin viaOVOSGUIAdapterFactory.create_all(bus, config)and fans eachSYSTEM_*templateevent out to all of them. A headless device with zero adapters degrades to no-op
dispatch — it never crashes.
Bugs fixed
service.pynow calls the realOVOSGUIAdapterFactory.create_all(nohasattrfallback); zero adapters logs + continues instead of raisingRuntimeError.pyproject.tomlhas nofile://pins; declaresovos-plugin-manager>=2.1.0,<3.0.0,ovos-bus-client>=1.0.0,<3.0.0(allows2.x), an optional
guiextra forovos-legacy-mycroft-gui-plugin, and atestextra. The package builds an sdist/wheel cleanly._safe_call/forward_to_gui/handle_clear_namespace/_parse_persistenceinnamespace.py.GuiPagemodel and the page-delete handlers thatreferenced the non-existent
namespace.pages/remove_pages;gui.page.delete*no longer raises
AttributeError.GUI_DESIGN.md+ newdocs/adapter-development/CONTRACT.md&architecture.mdmatch the session_id-only hook signatures; stalerouting-key/site_id text removed.
site_idand the 3-case routing logic; the routing keyis the
session_id. Emit context (gui.namespace.removed/displayed) carriessession_idonly.TypeError-retry in_safe_call; signature errorsare logged/surfaced.
Tests
116 passing locally.
test/end2enduses a concreteRecordingGUIPlugin(subclass of
AbstractGUIPlugin) instead ofMock()so handler/hook arity isenforced. Coverage: real factory loading (B1), default + UUID
session_id,two clients sharing one
session_idgetting the same dispatch, multi-adapterfan-out + failure isolation, and the removed page-delete path.
CI / unreleased deps
The reusable
build-tests/coverageworkflows install the unreleased loader andadapter from git until they publish to PyPI:
These pins revert to PyPI versions once the deps release.
🤖 Generated with Claude Code