build: externalize bundled plugin runtime deps

This commit is contained in:
Peter Steinberger
2026-03-31 15:20:55 +01:00
parent 9537094841
commit e1da91791a
6 changed files with 51 additions and 12 deletions

View File

@@ -6,16 +6,6 @@ import { decode, encode, isSilk } from "silk-wasm";
import { debugLog, debugError, debugWarn } from "./debug-log.js";
import { detectFfmpeg, isWindows } from "./platform.js";
/** Detect whether a file contains SILK audio payloads. */
function isSilkFile(filePath: string): boolean {
try {
const buf = fs.readFileSync(filePath);
return isSilk(new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength));
} catch {
return false;
}
}
/** Wrap PCM s16le bytes in a WAV container. */
function pcmToWav(
pcmData: Uint8Array,

View File

@@ -17,3 +17,6 @@ export function listBundledPluginBuildEntries(
params?: BundledPluginBuildEntryParams,
): Record<string, string>;
export function listBundledPluginPackArtifacts(params?: BundledPluginBuildEntryParams): string[];
export function listBundledPluginRuntimeDependencies(
params?: BundledPluginBuildEntryParams,
): string[];

View File

@@ -17,3 +17,6 @@ export function listBundledPluginBuildEntries(
params?: BundledPluginBuildEntryParams,
): Record<string, string>;
export function listBundledPluginPackArtifacts(params?: BundledPluginBuildEntryParams): string[];
export function listBundledPluginRuntimeDependencies(
params?: BundledPluginBuildEntryParams,
): string[];

View File

@@ -46,6 +46,10 @@ function collectPluginSourceEntries(packageJson) {
return packageEntries.length > 0 ? packageEntries : ["./index.ts"];
}
function shouldStageBundledPluginRuntimeDependencies(packageJson) {
return packageJson?.openclaw?.bundle?.stageRuntimeDependencies === true;
}
function collectTopLevelPublicSurfaceEntries(pluginDir) {
if (!fs.existsSync(pluginDir)) {
return [];
@@ -158,3 +162,23 @@ export function listBundledPluginPackArtifacts(params = {}) {
return [...artifacts].toSorted((left, right) => left.localeCompare(right));
}
export function listBundledPluginRuntimeDependencies(params = {}) {
const runtimeDependencies = new Set();
for (const { packageJson } of collectBundledPluginBuildEntries(params)) {
if (!shouldStageBundledPluginRuntimeDependencies(packageJson)) {
continue;
}
for (const dependencyName of Object.keys(packageJson?.dependencies ?? {})) {
runtimeDependencies.add(dependencyName);
}
for (const dependencyName of Object.keys(packageJson?.optionalDependencies ?? {})) {
runtimeDependencies.add(dependencyName);
}
}
return [...runtimeDependencies].toSorted((left, right) => left.localeCompare(right));
}

View File

@@ -3,6 +3,9 @@ import { bundledPluginRoot } from "../../test/helpers/bundled-plugin-paths.js";
import tsdownConfig from "../../tsdown.config.ts";
type TsdownConfigEntry = {
deps?: {
neverBundle?: string[];
};
entry?: Record<string, string> | string[];
outDir?: string;
};
@@ -69,4 +72,11 @@ describe("tsdown config", () => {
),
).toBe(false);
});
it("externalizes staged bundled plugin runtime dependencies", () => {
const configs = asConfigArray(tsdownConfig);
const unifiedGraph = configs.find((config) => entryKeys(config).includes("index"));
expect(unifiedGraph?.deps?.neverBundle).toEqual(expect.arrayContaining(["silk-wasm", "ws"]));
});
});

View File

@@ -1,7 +1,10 @@
import fs from "node:fs";
import path from "node:path";
import { defineConfig, type UserConfig } from "tsdown";
import { listBundledPluginBuildEntries } from "./scripts/lib/bundled-plugin-build-entries.mjs";
import {
listBundledPluginBuildEntries,
listBundledPluginRuntimeDependencies,
} from "./scripts/lib/bundled-plugin-build-entries.mjs";
import { buildPluginSdkEntrySources } from "./scripts/lib/plugin-sdk-entries.mjs";
type InputOptionsFactory = Extract<NonNullable<UserConfig["inputOptions"]>, Function>;
@@ -81,6 +84,7 @@ function nodeBuildConfig(config: UserConfig): UserConfig {
}
const bundledPluginBuildEntries = listBundledPluginBuildEntries();
const bundledPluginRuntimeDependencies = listBundledPluginRuntimeDependencies();
function buildBundledHookEntries(): Record<string, string> {
const hooksRoot = path.join(process.cwd(), "src", "hooks", "bundled");
@@ -160,7 +164,12 @@ export default defineConfig([
// and bundled hooks in one graph so runtime singletons are emitted once.
entry: buildUnifiedDistEntries(),
deps: {
neverBundle: ["@lancedb/lancedb", "@matrix-org/matrix-sdk-crypto-nodejs", "matrix-js-sdk"],
neverBundle: [
"@lancedb/lancedb",
"@matrix-org/matrix-sdk-crypto-nodejs",
"matrix-js-sdk",
...bundledPluginRuntimeDependencies,
],
},
}),
]);