chore(release): v0.20.0

Version bump via changesets.
This commit is contained in:
gsxdsm
2026-05-05 14:56:34 -07:00
parent 9f2f1fd450
commit e27e423194
73 changed files with 382 additions and 201 deletions

View File

@@ -1,5 +1,18 @@
# @fusion/dashboard
## 0.20.0
### Patch Changes
- ba6666f: Fix Planning Mode modal getting stuck at partial height on mobile. Two issues: (1) `useModalResizePersist` was replaying a desktop-saved pixel height into the inline `style` attribute, overriding the mobile `height: 100dvh` rule and leaving the modal at half-screen even before the keyboard appeared — now skipped on touch devices ≤768px wide. (2) When the iOS keyboard was dismissed, React reconciled the removed CSS custom properties (`--vv-height`, `--keyboard-overlap`, `--vv-offset-top`) by setting them to empty string instead of calling `removeProperty()`. On Safari that left `var(--vv-height, 100dvh)` resolving to empty (the fallback only kicks in when the variable is undefined), collapsing the modal to content height — now driven imperatively via `setProperty`/`removeProperty` on the modal ref.
- @fusion/core@0.20.0
- @fusion/engine@0.20.0
- @fusion-plugin-examples/dependency-graph@0.1.9
- @fusion-plugin-examples/droid-runtime@0.1.4
- @fusion-plugin-examples/hermes-runtime@0.2.28
- @fusion-plugin-examples/openclaw-runtime@0.2.28
- @fusion-plugin-examples/paperclip-runtime@0.2.28
## 0.19.0
### Patch Changes

View File

@@ -76,6 +76,11 @@ const BUNDLED_PLUGINS: BundledPlugin[] = [
path: "./plugins/fusion-plugin-droid-runtime",
experimental: true,
},
{
id: "fusion-plugin-dependency-graph",
name: "Dependency Graph",
path: "./plugins/fusion-plugin-dependency-graph",
},
];
export const STATE_COLORS: Record<string, string> = {

View File

@@ -231,6 +231,7 @@ describe("PluginManager", () => {
expect(screen.getByText("Paperclip Runtime")).toBeTruthy();
expect(screen.getByText("OpenClaw Runtime")).toBeTruthy();
expect(screen.getByText("Droid Runtime")).toBeTruthy();
expect(screen.getByText("Dependency Graph")).toBeTruthy();
});
it("installs bundled plugins from the bundled plugin section", async () => {
@@ -253,6 +254,26 @@ describe("PluginManager", () => {
});
});
it("installs dependency graph from the bundled plugin section", async () => {
render(<PluginManager addToast={addToast} />);
await waitFor(() => {
expect(fetchPlugins).toHaveBeenCalled();
});
const graphLabel = await screen.findByText("Dependency Graph");
const graphCard = graphLabel.closest(".plugin-bundled-runtime-item");
expect(graphCard).toBeTruthy();
const installButton = within(graphCard as HTMLElement).getByRole("button", { name: /Install Dependency Graph/i });
await userEvent.click(installButton);
await waitFor(() => {
expect(installPlugin).toHaveBeenCalledWith({ path: "./plugins/fusion-plugin-dependency-graph" }, undefined);
expect(addToast).toHaveBeenCalledWith("Dependency Graph installed successfully", "success");
});
});
it("renders plugin list when plugins are available", async () => {
vi.mocked(fetchPlugins).mockResolvedValueOnce(mockPlugins);
@@ -266,6 +287,7 @@ describe("PluginManager", () => {
expect(screen.getByText("v1.0.0")).toBeTruthy();
expect(screen.getByText("v2.0.0")).toBeTruthy();
expect(screen.getByRole("heading", { name: "Bundled Plugins" })).toBeTruthy();
expect(screen.getByText("Dependency Graph")).toBeTruthy();
expect(screen.getAllByText("Not installed").length).toBeGreaterThan(0);
});
@@ -505,32 +527,32 @@ describe("PluginManager", () => {
});
});
it("keeps bundled plugin manageable after install", async () => {
it("shows Manage for bundled dependency graph when already installed", async () => {
vi.mocked(fetchPlugins).mockResolvedValueOnce([
{
...mockPlugins[0],
id: "fusion-plugin-hermes-runtime",
name: "Hermes Runtime Plugin",
id: "fusion-plugin-dependency-graph",
name: "Dependency Graph",
},
]);
render(<PluginManager addToast={addToast} />);
await waitFor(() => {
expect(screen.getByText("Hermes Runtime")).toBeTruthy();
expect(screen.getAllByText("Dependency Graph").length).toBeGreaterThanOrEqual(2);
});
const hermesCard = screen.getByText("Hermes Runtime").closest(".plugin-bundled-runtime-item");
expect(hermesCard).toBeTruthy();
const graphCard = screen.getAllByText("Dependency Graph")[1]?.closest(".plugin-bundled-runtime-item");
expect(graphCard).toBeTruthy();
const manageButton = within(hermesCard as HTMLElement).getByRole("button", { name: /^Manage$/i });
const manageButton = within(graphCard as HTMLElement).getByRole("button", { name: /^Manage$/i });
expect(manageButton).not.toBeDisabled();
expect(within(hermesCard as HTMLElement).getAllByText("Installed").length).toBeGreaterThanOrEqual(1);
expect(within(graphCard as HTMLElement).getAllByText("Installed").length).toBeGreaterThanOrEqual(1);
await userEvent.click(manageButton);
await waitFor(() => {
expect(fetchPluginSettings).toHaveBeenCalledWith("fusion-plugin-hermes-runtime", undefined);
expect(fetchPluginSettings).toHaveBeenCalledWith("fusion-plugin-dependency-graph", undefined);
});
expect(screen.getByTestId("plugin-manager-detail")).toBeTruthy();

View File

@@ -1,6 +1,6 @@
{
"name": "@fusion/dashboard",
"version": "0.19.0",
"version": "0.20.0",
"license": "MIT",
"description": "Fusion dashboard: React UI and HTTP API server for monitoring and controlling the Fusion AI coding agent.",
"homepage": "https://github.com/Runfusion/Fusion#readme",