mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-10-04 14:25:08 +00:00
refactor(web): read plugins through a PluginCatalog; only the display runs them (#688)
The web process built its own PluginManager and loaded plugins into itself: store installs and updates loaded or reloaded a web-side copy, and config saves and enable/disable called on_config_change, on_enable and on_disable on it. None of that reached the panel, and /plugins/installed reported runtime state from those copies. - Add PluginCatalog (src/plugin_system/plugin_catalog.py): manifests, directories, display modes, installed version, schema and config reads, with no way to run a plugin. app.py and both blueprints use it; the plugin_manager blueprint attribute is gone. - Remove every lifecycle call from the web routes. Config changes already reach the display through ConfigService (on_config_change) and the enabled-set reconcile. - Health and metrics readers move to api_v3.health_tracker / resource_monitor. /plugins/installed reports loaded/state/error_info as null (the display does not publish them) and enabled by the display's rule. - Store install, update and uninstall answer restart_required when the running display will not pick the change up by itself (display_restart_required). The restart banner follows the flag via window.noteRestartRequired instead of the /config/main URL heuristic; /config/main now sends restart_required: true. - The one remaining in-process import of plugin code (Starlark helper modules, oauth_flow action scripts) goes through _import_plugin_code_in_web_process() until a web-entry contract. - /plugins/installed reports vegas_participation (from #682) from the user's setting or the manifest, with vegas_participation_source; when only the plugin's code decides it, null with source 'runtime', since the web process no longer has plugin instances to ask. - Check & Update All keeps its restart flags when the final list refresh fails, and asks for a restart when an enabled plugin's first request got no answer and the re-sent one found it up to date. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+55
-12
@@ -154,10 +154,17 @@ there an unchecked checkbox — which the browser omits — is saved as
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"message": "Configuration saved successfully"
|
||||
"message": "Configuration saved successfully",
|
||||
"restart_required": true
|
||||
}
|
||||
```
|
||||
|
||||
`restart_required` is always true here: display hardware, rotation,
|
||||
durations and general settings take effect when the display restarts, and
|
||||
the web UI shows its restart banner on the flag. (Plugin sections saved
|
||||
through this route reach the running plugin live, like
|
||||
`POST /plugins/config`.)
|
||||
|
||||
Invalid values (e.g. an out-of-range `target_fps`, a hardware option the
|
||||
Raspberry Pi 5 driver cannot use) are rejected with `400` and nothing is
|
||||
saved.
|
||||
@@ -502,8 +509,8 @@ List all installed plugins with their status and metadata.
|
||||
"tags": ["sports", "football", "nfl"],
|
||||
"enabled": true,
|
||||
"verified": true,
|
||||
"loaded": true,
|
||||
"state": "loaded",
|
||||
"loaded": null,
|
||||
"state": null,
|
||||
"error_info": null,
|
||||
"last_updated": "2025-01-15T10:30:00Z",
|
||||
"last_commit": "abc1234",
|
||||
@@ -512,19 +519,34 @@ List all installed plugins with their status and metadata.
|
||||
"web_ui_actions": [],
|
||||
"vegas_mode": null,
|
||||
"vegas_content_type": null,
|
||||
"vegas_participation": "scroll"
|
||||
"vegas_participation": "scroll",
|
||||
"vegas_participation_source": "manifest"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Metadata comes from each plugin's files on disk; `enabled` is the plugin's
|
||||
`enabled` flag in `config.json` (missing means disabled, as the display
|
||||
reads it). `loaded`, `state` and `error_info` are always `null`: the web
|
||||
process runs no plugin code, and the display does not publish which plugins
|
||||
it has loaded. What the display does publish is at
|
||||
[`/plugins/health`](#get-plugin-health), `/plugins/metrics` and `/errors/*`.
|
||||
|
||||
`vegas_participation` is what Vegas mode does with the plugin: `"scroll"`,
|
||||
`"pause"` or `"exclude"` (see
|
||||
[PLUGIN_API_REFERENCE.md](PLUGIN_API_REFERENCE.md#vegas-participation)).
|
||||
For a plugin that is not loaded it is only the user's own
|
||||
`vegas_participation` setting, or `null`. `vegas_mode` and
|
||||
`vegas_content_type` are the legacy hooks' raw answers.
|
||||
[PLUGIN_API_REFERENCE.md](PLUGIN_API_REFERENCE.md#vegas-participation)),
|
||||
and `vegas_participation_source` says where it came from. The web reads it
|
||||
the way the display resolves it, as far as files can tell: the user's own
|
||||
`vegas_participation` setting (`"config"`), else the manifest's declared
|
||||
`vegas_participation` (`"manifest"`). Past those the display derives it from
|
||||
the plugin's code -- a `get_vegas_participation()` override or the legacy
|
||||
Vegas hooks -- which the web process never runs, so `vegas_participation`
|
||||
is `null` and the source is `"runtime"`. A plugin that overrides
|
||||
`get_vegas_participation()` decides at run time and can differ from its
|
||||
manifest's declaration. `vegas_mode` is the plugin's configured
|
||||
`vegas_mode`, or `null`; `vegas_content_type` is always `null`.
|
||||
|
||||
### Get Plugin Configuration
|
||||
|
||||
@@ -685,7 +707,13 @@ Install a plugin from the plugin store.
|
||||
```
|
||||
|
||||
When the operation queue is unavailable the install runs synchronously and
|
||||
the response has only a `message`.
|
||||
the response has only a `message` and the restart fields below.
|
||||
|
||||
The finished operation's `result` (from `/plugins/operation/<operation_id>`)
|
||||
carries `restart_required`: true when the plugin is already enabled in
|
||||
`config.json`, because the running display does not load newly installed
|
||||
files by itself; `restart_message` then holds the restart banner's wording.
|
||||
A plugin that is not enabled needs no restart: enabling it loads it.
|
||||
|
||||
A plugin whose registry entry (or downloaded manifest) needs a newer
|
||||
LEDMatrix is refused: the synchronous install answers `409` with a message
|
||||
@@ -716,6 +744,11 @@ Remove an installed plugin.
|
||||
}
|
||||
```
|
||||
|
||||
The finished operation's `result` carries `restart_required`. Removing the
|
||||
plugin's config (the default) lets the display unload it by itself, so it is
|
||||
false; with `preserve_config: true` an enabled plugin keeps running until
|
||||
the display restarts, and it is true.
|
||||
|
||||
### Update Plugin
|
||||
|
||||
**POST** `/api/v3/plugins/update`
|
||||
@@ -736,11 +769,18 @@ Update a plugin to the latest version. Runs synchronously.
|
||||
"message": "Plugin football-scoreboard updated ...",
|
||||
"data": {
|
||||
"last_updated": "2025-01-15T10:30:00Z",
|
||||
"commit": "abc1234..."
|
||||
}
|
||||
"commit": "abc1234...",
|
||||
"update_status": "updated"
|
||||
},
|
||||
"restart_required": true,
|
||||
"restart_message": "Plugin updated — restart the display to run the new version"
|
||||
}
|
||||
```
|
||||
|
||||
`update_status` is `updated`, `up_to_date` or `local_only`.
|
||||
`restart_required` is true when the plugin changed and is enabled: the
|
||||
running display keeps the code it loaded until it restarts.
|
||||
|
||||
An update this core cannot run answers `409` with `Plugin update refused:`
|
||||
and the reason; the installed version is left as it was.
|
||||
|
||||
@@ -772,10 +812,13 @@ Install a plugin directly from a GitHub repository URL. Runs synchronously.
|
||||
"message": "Plugin my-plugin installed successfully",
|
||||
"plugin_id": "my-plugin",
|
||||
"name": "My Plugin",
|
||||
"branch": "main"
|
||||
"branch": "main",
|
||||
"restart_required": false
|
||||
}
|
||||
```
|
||||
|
||||
`restart_required` follows the same rule as `/plugins/install`.
|
||||
|
||||
### Load Registry from URL
|
||||
|
||||
**POST** `/api/v3/plugins/registry-from-url`
|
||||
|
||||
Reference in New Issue
Block a user