feat(FN-3718): add droid runtime to tsup bundle with asset gate
Stages the droid runtime as a bundled plugin in the CLI's tsup configuration, gates the bundle bootstrap on droid asset availability, and adds tests asserting correct staging behavior in bundle output. Fusion-Task-Id: FN-3718
This commit is contained in:
8
.changeset/FN-3718-droid-runtime-bundle.md
Normal file
8
.changeset/FN-3718-droid-runtime-bundle.md
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
"@runfusion/fusion": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Stage `fusion-plugin-droid-runtime` (including its `mcp-schema-server.cjs`
|
||||||
|
bridge asset) into the published CLI tarball, mirroring the
|
||||||
|
`fusion-plugin-openclaw-runtime` build pipeline. The droid runtime plugin
|
||||||
|
is now bundled and asserted by the bundle-output test suite.
|
||||||
@@ -16,6 +16,7 @@ import {
|
|||||||
bundlePath,
|
bundlePath,
|
||||||
clientIndexPath,
|
clientIndexPath,
|
||||||
dashboardClientStubMarker,
|
dashboardClientStubMarker,
|
||||||
|
droidPluginMcpServerPath,
|
||||||
hasBuiltDashboardAssets,
|
hasBuiltDashboardAssets,
|
||||||
openclawMcpSchemaServerPath,
|
openclawMcpSchemaServerPath,
|
||||||
} from "./bundle-output-helpers";
|
} from "./bundle-output-helpers";
|
||||||
@@ -39,11 +40,21 @@ describe("hasBuiltDashboardAssets", () => {
|
|||||||
expect(hasBuiltDashboardAssets()).toBe(false);
|
expect(hasBuiltDashboardAssets()).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("returns false when droid mcp-schema-server.cjs is missing", () => {
|
||||||
|
state.existingPaths.add(bundlePath);
|
||||||
|
state.existingPaths.add(clientIndexPath);
|
||||||
|
state.existingPaths.add(cursorPluginManifestPath);
|
||||||
|
state.existingPaths.add(openclawMcpSchemaServerPath);
|
||||||
|
|
||||||
|
expect(hasBuiltDashboardAssets()).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
it("returns true when all required assets exist and dashboard stub marker is absent", () => {
|
it("returns true when all required assets exist and dashboard stub marker is absent", () => {
|
||||||
state.existingPaths.add(bundlePath);
|
state.existingPaths.add(bundlePath);
|
||||||
state.existingPaths.add(clientIndexPath);
|
state.existingPaths.add(clientIndexPath);
|
||||||
state.existingPaths.add(cursorPluginManifestPath);
|
state.existingPaths.add(cursorPluginManifestPath);
|
||||||
state.existingPaths.add(openclawMcpSchemaServerPath);
|
state.existingPaths.add(openclawMcpSchemaServerPath);
|
||||||
|
state.existingPaths.add(droidPluginMcpServerPath);
|
||||||
|
|
||||||
expect(hasBuiltDashboardAssets()).toBe(true);
|
expect(hasBuiltDashboardAssets()).toBe(true);
|
||||||
});
|
});
|
||||||
@@ -53,6 +64,7 @@ describe("hasBuiltDashboardAssets", () => {
|
|||||||
state.existingPaths.add(clientIndexPath);
|
state.existingPaths.add(clientIndexPath);
|
||||||
state.existingPaths.add(cursorPluginManifestPath);
|
state.existingPaths.add(cursorPluginManifestPath);
|
||||||
state.existingPaths.add(openclawMcpSchemaServerPath);
|
state.existingPaths.add(openclawMcpSchemaServerPath);
|
||||||
|
state.existingPaths.add(droidPluginMcpServerPath);
|
||||||
state.indexHtml = dashboardClientStubMarker;
|
state.indexHtml = dashboardClientStubMarker;
|
||||||
|
|
||||||
expect(hasBuiltDashboardAssets()).toBe(false);
|
expect(hasBuiltDashboardAssets()).toBe(false);
|
||||||
|
|||||||
@@ -14,6 +14,13 @@ export const openclawMcpSchemaServerPath = join(
|
|||||||
"fusion-plugin-openclaw-runtime",
|
"fusion-plugin-openclaw-runtime",
|
||||||
"mcp-schema-server.cjs",
|
"mcp-schema-server.cjs",
|
||||||
);
|
);
|
||||||
|
export const droidPluginMcpServerPath = join(
|
||||||
|
cliRoot,
|
||||||
|
"dist",
|
||||||
|
"plugins",
|
||||||
|
"fusion-plugin-droid-runtime",
|
||||||
|
"mcp-schema-server.cjs",
|
||||||
|
);
|
||||||
|
|
||||||
export const dashboardClientStubMarker = "Dashboard assets not built";
|
export const dashboardClientStubMarker = "Dashboard assets not built";
|
||||||
|
|
||||||
@@ -40,7 +47,8 @@ export function hasBuiltDashboardAssets(): boolean {
|
|||||||
!existsSync(bundlePath) ||
|
!existsSync(bundlePath) ||
|
||||||
!existsSync(clientIndexPath) ||
|
!existsSync(clientIndexPath) ||
|
||||||
!existsSync(cursorPluginManifestPath) ||
|
!existsSync(cursorPluginManifestPath) ||
|
||||||
!existsSync(openclawMcpSchemaServerPath)
|
!existsSync(openclawMcpSchemaServerPath) ||
|
||||||
|
!existsSync(droidPluginMcpServerPath)
|
||||||
) {
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -189,6 +189,17 @@ describe("CLI bundle output", () => {
|
|||||||
expect(existsSync(join(stagedRoot, "mcp-schema-server.cjs"))).toBe(true);
|
expect(existsSync(join(stagedRoot, "mcp-schema-server.cjs"))).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("dist/plugins/fusion-plugin-droid-runtime/ is staged with required bridge assets", () => {
|
||||||
|
const stagedRoot = join(cliRoot, "dist", "plugins", "fusion-plugin-droid-runtime");
|
||||||
|
const manifestPath = join(stagedRoot, "manifest.json");
|
||||||
|
|
||||||
|
expect(existsSync(manifestPath)).toBe(true);
|
||||||
|
const manifest = JSON.parse(readFileSync(manifestPath, "utf-8")) as { id?: string };
|
||||||
|
expect(manifest.id).toBe("fusion-plugin-droid-runtime");
|
||||||
|
expect(existsSync(join(stagedRoot, "bundled.js"))).toBe(true);
|
||||||
|
expect(existsSync(join(stagedRoot, "mcp-schema-server.cjs"))).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
it("dist/plugins/fusion-plugin-cursor-runtime/ is staged with a valid manifest", () => {
|
it("dist/plugins/fusion-plugin-cursor-runtime/ is staged with a valid manifest", () => {
|
||||||
const stagedRoot = join(cliRoot, "dist", "plugins", "fusion-plugin-cursor-runtime");
|
const stagedRoot = join(cliRoot, "dist", "plugins", "fusion-plugin-cursor-runtime");
|
||||||
const manifestPath = join(stagedRoot, "manifest.json");
|
const manifestPath = join(stagedRoot, "manifest.json");
|
||||||
|
|||||||
@@ -13,8 +13,14 @@ const RUNTIME_PLUGIN_IDS = [
|
|||||||
"fusion-plugin-openclaw-runtime",
|
"fusion-plugin-openclaw-runtime",
|
||||||
"fusion-plugin-paperclip-runtime",
|
"fusion-plugin-paperclip-runtime",
|
||||||
"fusion-plugin-cursor-runtime",
|
"fusion-plugin-cursor-runtime",
|
||||||
|
"fusion-plugin-droid-runtime",
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
|
const RUNTIME_PLUGINS_WITH_MCP_SCHEMA_SERVER = new Set([
|
||||||
|
"fusion-plugin-openclaw-runtime",
|
||||||
|
"fusion-plugin-droid-runtime",
|
||||||
|
]);
|
||||||
|
|
||||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||||
const dashboardClientSrc = join(__dirname, "..", "dashboard", "dist", "client");
|
const dashboardClientSrc = join(__dirname, "..", "dashboard", "dist", "client");
|
||||||
const dashboardClientDest = join(__dirname, "dist", "client");
|
const dashboardClientDest = join(__dirname, "dist", "client");
|
||||||
@@ -214,11 +220,11 @@ export default defineConfig({
|
|||||||
logLevel: "warning",
|
logLevel: "warning",
|
||||||
});
|
});
|
||||||
|
|
||||||
if (pluginId === "fusion-plugin-openclaw-runtime") {
|
if (RUNTIME_PLUGINS_WITH_MCP_SCHEMA_SERVER.has(pluginId)) {
|
||||||
const mcpServerAsset = join(pluginSrcDir, "src", "mcp-schema-server.cjs");
|
const mcpServerAsset = join(pluginSrcDir, "src", "mcp-schema-server.cjs");
|
||||||
if (!existsSync(mcpServerAsset)) {
|
if (!existsSync(mcpServerAsset)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`[tsup] Missing required openclaw bridge asset at ${mcpServerAsset}; expected committed source file mcp-schema-server.cjs.`,
|
`[tsup] Missing required bridge asset for ${pluginId} at ${mcpServerAsset}; expected committed source file mcp-schema-server.cjs.`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
cpSync(mcpServerAsset, join(pluginDestDir, "mcp-schema-server.cjs"));
|
cpSync(mcpServerAsset, join(pluginDestDir, "mcp-schema-server.cjs"));
|
||||||
|
|||||||
Reference in New Issue
Block a user