Surface plugin update availability on the plugins page

The plugin manager page already showed each installed plugin's version and
had an Update button, but nothing told users an update actually existed —
they had to guess. The store manager already compares the installed
manifest version against the registry's latest_version for its reinstall
decision; this surfaces that same signal in the UI.

- api_v3 /plugins/installed now returns `latest_version` (from the registry
  cache, no extra network call) and an `update_available` flag computed by a
  new semver-aware helper `_is_plugin_update_available`. A locally modified
  plugin whose version is ahead of the registry is not flagged.
- The installed-plugin card shows "vX.Y.Z available" next to the installed
  version, and the Update button becomes emphasized ("Update to vX.Y.Z" with
  a gentle pulse) when a newer version is published — mirroring the app's own
  update banner styling.
- Added tests for the helper and the endpoint fields.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012EW8yDbsk8EceDpq6Hjgqj
This commit is contained in:
ChuckBuilds
2026-07-19 21:38:31 +00:00
co-authored by Claude Opus 4.8
parent 989162d28f
commit 5113b51234
4 changed files with 106 additions and 7 deletions
+15
View File
@@ -1334,6 +1334,21 @@ button.bg-white {
color: #93c5fd;
}
/* Installed-plugin "Update" button when a newer version is published.
A gentle pulsing ring draws the eye without being noisy. */
.plugin-update-available {
box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.6);
animation: plugin-update-pulse 2s ease-out infinite;
}
@keyframes plugin-update-pulse {
0% { box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.55); }
70% { box-shadow: 0 0 0 6px rgba(59, 130, 246, 0); }
100% { box-shadow: 0 0 0 0 rgba(59, 130, 246, 0); }
}
@media (prefers-reduced-motion: reduce) {
.plugin-update-available { animation: none; }
}
/* Under-voltage / throttling warning banner */
.power-warning-banner {
background-color: #fef2f2;