mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-04-10 13:02:59 +00:00
* feat: adapt LEDMatrix for monorepo plugin architecture Update store_manager to fetch manifests from subdirectories within the monorepo (plugin_path/manifest.json) instead of repo root. Remove 21 plugin submodule entries from .gitmodules, simplify workspace file to reference the monorepo, and clean up scripts for the new layout. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: auto-reinstall plugins when registry repo URL changes When a user clicks "Update" on a git-cloned plugin, detect if the local git remote URL no longer matches the registry's repo URL (e.g. after monorepo migration). Instead of pulling from the stale archived repo, automatically remove and reinstall from the new registry source. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: plugin store "View" button links to correct monorepo subdirectory When a plugin has a plugin_path (monorepo plugin), construct the GitHub URL as repo/tree/main/plugin_path so users land on the specific plugin directory. Pass plugin_path through the store API response to the frontend. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: monorepo manifest fetch in search + version-based update detection Fix search_plugins() to pass plugin_path when fetching manifests from GitHub, matching the fix already in get_plugin_info(). Without this, monorepo plugin descriptions 404 in search results. Add version comparison for non-git plugins (monorepo installs) so "Update All" skips plugins already at latest_version instead of blindly reinstalling every time. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: show plugin version instead of misleading monorepo commit info Replace commit hash, date, and stars on plugin cards with the plugin's version number. In a monorepo all plugins share the same commit history and star count, making those fields identical and misleading. Version is the meaningful per-plugin signal users care about. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: add CLAUDE.md with project structure and plugin store docs Documents plugin store architecture, monorepo install flow, version- based update detection, and the critical version bump workflow. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * perf: extract only target plugin from monorepo ZIP instead of all files Previously _install_from_monorepo() called extractall() on the entire monorepo ZIP (~13MB, 600+ files) just to grab one plugin subdirectory. Now filter zip members by the plugin prefix and extract only matching files, reducing disk I/O by ~96% per install/update. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * perf: download only target plugin files via GitHub Trees API Replace full monorepo ZIP download (~5MB) with targeted file downloads (~200KB per plugin) using the GitHub Git Trees API for directory listing and raw.githubusercontent.com for individual file content. One API call fetches the repo tree, client filters for the target plugin's files, then downloads each file individually. Falls back to ZIP if the API is unavailable (rate limited, no network, etc.). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: clean up partial files between API and ZIP install fallbacks Ensure target_path is fully removed before the ZIP fallback runs, and before shutil.move() in the ZIP method. Prevents directory nesting if the API method creates target_path then fails mid-download. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: harden scripts and fix monorepo URL handling - setup_plugin_repos.py: add type hints, remove unnecessary f-string, wrap manifest parsing in try/except to skip malformed manifests - update_plugin_repos.py: add 120s timeout to git pull with TimeoutExpired handling - store_manager.py: fix rstrip('.zip') stripping valid branch chars, use removesuffix('.zip'); remove redundant import json - plugins_manager.js: View button uses dynamic branch, disables when repo is missing, encodes plugin_path in URL - CLAUDE.md: document plugin repo naming convention Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: harden monorepo install security and cleanup - store_manager: fix temp dir leak in _install_from_monorepo_zip by moving cleanup to finally block - store_manager: add zip-slip guard validating extracted paths stay inside temp directory - store_manager: add 500-file sanity cap to API-based install - store_manager: extract _normalize_repo_url as @staticmethod - setup_plugin_repos: propagate create_symlinks() failure via sys.exit, narrow except to OSError Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: add path traversal guard to API-based monorepo installer Validate that each file's resolved destination stays inside target_path before creating directories or writing bytes, mirroring the zip-slip guard in _install_from_monorepo_zip. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: use _safe_remove_directory for monorepo migration cleanup Replace shutil.rmtree(ignore_errors=True) with _safe_remove_directory which handles permission errors gracefully and returns status, preventing install_plugin from running against a partially-removed directory. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Chuck <chuck@example.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2.0 KiB
2.0 KiB
LEDMatrix
Project Structure
src/plugin_system/— Plugin loader, manager, store manager, base plugin classweb_interface/— Flask web UI (blueprints, templates, static JS)config/config.json— User plugin configuration (persists across plugin reinstalls)plugins/— Installed plugins directory (gitignored)plugin-repos/— Development symlinks to monorepo plugin dirs
Plugin System
- Plugins inherit from
BasePlugininsrc/plugin_system/base_plugin.py - Required abstract methods:
update(),display(force_clear=False) - Each plugin needs:
manifest.json,config_schema.json,manager.py,requirements.txt - Plugin instantiation args:
plugin_id, config, display_manager, cache_manager, plugin_manager - Config schemas use JSON Schema Draft-7
- Display dimensions: always read dynamically from
self.display_manager.matrix.width/height
Plugin Store Architecture
- Official plugins live in the
ledmatrix-pluginsmonorepo (not individual repos) - Plugin repo naming convention:
ledmatrix-<plugin-id>(e.g.,ledmatrix-football-scoreboard) plugins.jsonregistry athttps://raw.githubusercontent.com/ChuckBuilds/ledmatrix-plugins/main/plugins.json- Store manager (
src/plugin_system/store_manager.py) handles install/update/uninstall - Monorepo plugins are installed via ZIP extraction (no
.gitdirectory) - Update detection for monorepo plugins uses version comparison (manifest version vs registry latest_version)
- Plugin configs stored in
config/config.json, NOT in plugin directories — safe across reinstalls - Third-party plugins can use their own repo URL with empty
plugin_path
Common Pitfalls
- paho-mqtt 2.x needs
callback_api_version=mqtt.CallbackAPIVersion.VERSION1for v1 compat - BasePlugin uses
get_logger()fromsrc.logging_config, not standardlogging.getLogger() - When modifying a plugin in the monorepo, you MUST bump
versionin itsmanifest.jsonand runpython update_registry.py— otherwise users won't receive the update