fix(plugins): a plugin that can't start live says why and offers a restart (#6087)
CI / lint (push) Successful in 2s
CI / unit (push) Successful in 1m28s
CI / integration (push) Successful in 1m33s
CI / publish (push) Successful in 1m29s

Saving an enabled plugin threw away hot_reload_plugin's (ok, message), so a
plugin that failed to load live read "Enabled, not loaded" with nothing
more. Now:
- a live-load failure is recorded with its reason, as a boot failure is, and
  logged; a later success clears it;
- any save of an enabled plugin that isn't running tries to start it, not
  only the off-to-on toggle;
- enabling one already running is a success, not a failure;
- the plugin's page offers "Restart to load" while it is enabled and not
  running.

Quart never marks the app as having served its first request, so
register_blueprint after startup is allowed: hot-loading is not refused
wholesale, as #6087 suspected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-18 22:56:54 -04:00
co-authored by Claude Opus 5.5
parent f7616b71c3
commit a59d1a7709
4 changed files with 102 additions and 8 deletions
+5 -2
View File
@@ -1091,8 +1091,11 @@ async def save_plugin_detail(name: str):
action = "plugin.enabled" if new_enabled else "plugin.disabled"
await log_audit(current_app, session.get("user_id"), session.get("username", ""),
action, entity_type="plugin", entity_id=name)
if new_enabled and not old_enabled:
from steward.core.plugin_manager import hot_reload_plugin
# Any save of an enabled plugin that isn't running tries to start it; a
# failure is recorded with its reason, which the page shows beside a
# restart (#6087).
from steward.core.plugin_manager import _LOADED_PLUGINS, hot_reload_plugin
if new_enabled and name not in _LOADED_PLUGINS:
hot_reload_plugin(current_app._get_current_object(), name)
return redirect(url_for("settings.plugin_detail", name=name))