fix(updates): report a plugin build installed beside the running one, never "up to date" on a failed check
A `claude plugin update` run from a terminal (or with only the Claude desktop
app open) unpacks the new build and starts nothing: no SessionStart fires, so
the dashboard kept running the old cache dir across reboots, and with the
forge unreachable the sidebar read "Up to date" (seen on a machine stuck at
1.8.10).
- pluginStatus asks supersededBy for its own root: a recorded sibling install
sets `installed_not_running: {root, version}` and `update_available`, with
no network needed
- the sidebar reads "<version> installed, not running"; the update modal keys
on it, so Update now is offered even with no release tag or sha
- plugin-update-helper hands over to the recorded install first, the newest
sibling dir only as a fallback
- a plugin install whose release lookup failed reads "Could not check for
updates" instead of "Up to date"
- docs/PLUGINS.md: the case and the manual hand-over command
This commit is contained in:
@@ -137,6 +137,33 @@ describe("UpdateNotifier — Update now", () => {
|
||||
expect(screen.queryByText(i18n.t("updates:notGit"))).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("offers Update now for a build installed from a terminal, even with no release read", async () => {
|
||||
// `claude plugin update` started nothing and the forge was unreachable:
|
||||
// no release tag and no sha to key the modal on, yet a newer build sits
|
||||
// on disk. That used to read as "up to date" with no way to switch.
|
||||
statusMock.mockResolvedValue({
|
||||
...BASE_STATUS,
|
||||
git_repo: false,
|
||||
situation: "plugin_managed",
|
||||
install_kind: "plugin",
|
||||
plugin_marketplace: "sg",
|
||||
plugin_name: "agenthub",
|
||||
remote_sha: null,
|
||||
commits_behind: 0,
|
||||
local_version: "1.8.10",
|
||||
release_check: "unreachable",
|
||||
latest_release: null,
|
||||
installed_not_running: { root: "/cache/sg/agenthub/new", version: "1.8.12" },
|
||||
});
|
||||
render(<UpdateNotifier />);
|
||||
|
||||
await screen.findByText(i18n.t("updates:installedTitle", { version: "1.8.12" }));
|
||||
expect(
|
||||
screen.getByText(i18n.t("updates:releaseSubtitle", { current: "1.8.10" }))
|
||||
).toBeInTheDocument();
|
||||
expect(screen.getByText(i18n.t("updates:updateNow"))).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("surfaces a previous plugin chain's failure so a dead update isn't silent", async () => {
|
||||
statusMock.mockResolvedValue({
|
||||
...BASE_STATUS,
|
||||
|
||||
Reference in New Issue
Block a user