feat(FN-3717): gate bootstrap on openclaw bridge asset
Stabilizes the OpenClaw bundle by hardening the asset copy logic and gating the bootstrap flow on the openclaw bridge asset being present, with regression tests covering the new bundle-output helpers and a patch changeset for `@runfusion/fusion`. Fusion-Task-Id: FN-3717
This commit is contained in:
60
packages/cli/src/__tests__/bundle-output-helpers.test.ts
Normal file
60
packages/cli/src/__tests__/bundle-output-helpers.test.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const state = {
|
||||
existingPaths: new Set<string>(),
|
||||
indexHtml: "",
|
||||
};
|
||||
|
||||
vi.mock("node:fs", () => ({
|
||||
existsSync: (path: string) => state.existingPaths.has(path),
|
||||
readFileSync: () => state.indexHtml,
|
||||
execFileSync: vi.fn(),
|
||||
execSync: vi.fn(),
|
||||
}));
|
||||
|
||||
import {
|
||||
bundlePath,
|
||||
clientIndexPath,
|
||||
dashboardClientStubMarker,
|
||||
hasBuiltDashboardAssets,
|
||||
openclawMcpSchemaServerPath,
|
||||
} from "./bundle-output-helpers";
|
||||
|
||||
const cursorPluginManifestPath = bundlePath.replace(
|
||||
"dist/bin.js",
|
||||
"dist/plugins/fusion-plugin-cursor-runtime/manifest.json",
|
||||
);
|
||||
|
||||
describe("hasBuiltDashboardAssets", () => {
|
||||
beforeEach(() => {
|
||||
state.existingPaths.clear();
|
||||
state.indexHtml = "<html><body><script src=\"assets/app.js\"></script></body></html>";
|
||||
});
|
||||
|
||||
it("returns false when openclaw mcp-schema-server.cjs is missing", () => {
|
||||
state.existingPaths.add(bundlePath);
|
||||
state.existingPaths.add(clientIndexPath);
|
||||
state.existingPaths.add(cursorPluginManifestPath);
|
||||
|
||||
expect(hasBuiltDashboardAssets()).toBe(false);
|
||||
});
|
||||
|
||||
it("returns true when all required assets exist and dashboard stub marker is absent", () => {
|
||||
state.existingPaths.add(bundlePath);
|
||||
state.existingPaths.add(clientIndexPath);
|
||||
state.existingPaths.add(cursorPluginManifestPath);
|
||||
state.existingPaths.add(openclawMcpSchemaServerPath);
|
||||
|
||||
expect(hasBuiltDashboardAssets()).toBe(true);
|
||||
});
|
||||
|
||||
it("returns false when dashboard client index contains stub marker", () => {
|
||||
state.existingPaths.add(bundlePath);
|
||||
state.existingPaths.add(clientIndexPath);
|
||||
state.existingPaths.add(cursorPluginManifestPath);
|
||||
state.existingPaths.add(openclawMcpSchemaServerPath);
|
||||
state.indexHtml = dashboardClientStubMarker;
|
||||
|
||||
expect(hasBuiltDashboardAssets()).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -7,6 +7,13 @@ export const workspaceRoot = join(cliRoot, "..", "..");
|
||||
export const bundlePath = join(cliRoot, "dist", "bin.js");
|
||||
export const clientIndexPath = join(cliRoot, "dist", "client", "index.html");
|
||||
const cursorPluginManifestPath = join(cliRoot, "dist", "plugins", "fusion-plugin-cursor-runtime", "manifest.json");
|
||||
export const openclawMcpSchemaServerPath = join(
|
||||
cliRoot,
|
||||
"dist",
|
||||
"plugins",
|
||||
"fusion-plugin-openclaw-runtime",
|
||||
"mcp-schema-server.cjs",
|
||||
);
|
||||
|
||||
export const dashboardClientStubMarker = "Dashboard assets not built";
|
||||
|
||||
@@ -28,8 +35,13 @@ function runBuildCommand(command: string, cwd: string) {
|
||||
});
|
||||
}
|
||||
|
||||
function hasBuiltDashboardAssets(): boolean {
|
||||
if (!existsSync(bundlePath) || !existsSync(clientIndexPath) || !existsSync(cursorPluginManifestPath)) {
|
||||
export function hasBuiltDashboardAssets(): boolean {
|
||||
if (
|
||||
!existsSync(bundlePath) ||
|
||||
!existsSync(clientIndexPath) ||
|
||||
!existsSync(cursorPluginManifestPath) ||
|
||||
!existsSync(openclawMcpSchemaServerPath)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -216,9 +216,12 @@ export default defineConfig({
|
||||
|
||||
if (pluginId === "fusion-plugin-openclaw-runtime") {
|
||||
const mcpServerAsset = join(pluginSrcDir, "src", "mcp-schema-server.cjs");
|
||||
if (existsSync(mcpServerAsset)) {
|
||||
cpSync(mcpServerAsset, join(pluginDestDir, "mcp-schema-server.cjs"));
|
||||
if (!existsSync(mcpServerAsset)) {
|
||||
throw new Error(
|
||||
`[tsup] Missing required openclaw bridge asset at ${mcpServerAsset}; expected committed source file mcp-schema-server.cjs.`,
|
||||
);
|
||||
}
|
||||
cpSync(mcpServerAsset, join(pluginDestDir, "mcp-schema-server.cjs"));
|
||||
}
|
||||
|
||||
console.log(`Bundled runtime plugin ${pluginId} to dist/plugins/${pluginId}/bundled.js`);
|
||||
|
||||
Reference in New Issue
Block a user