fix: align bundled provider contracts with externalized plugins

This commit is contained in:
Peter Steinberger
2026-05-02 03:45:14 +01:00
parent b813183bfd
commit 78161e1212
5 changed files with 41 additions and 14 deletions

View File

@@ -5,7 +5,13 @@ import {
normalizeBundledPluginStringList,
resolveBundledPluginScanDir,
} from "../../bundled-plugin-scan.js";
import { PLUGIN_MANIFEST_FILENAME, type PluginManifest } from "../../manifest.js";
import {
getPackageManifestMetadata,
isPackageIncludedInCoreBundle,
PLUGIN_MANIFEST_FILENAME,
type PackageManifest,
type PluginManifest,
} from "../../manifest.js";
import { resolveLoaderPackageRoot } from "../../sdk-alias.js";
import { uniqueStrings } from "../shared.js";
@@ -65,17 +71,7 @@ function readJsonRecord(filePath: string): Record<string, unknown> | undefined {
}
function isExplicitlyDownloadablePlugin(packageJson: Record<string, unknown> | undefined): boolean {
const openclaw = packageJson?.openclaw;
if (!openclaw || typeof openclaw !== "object" || Array.isArray(openclaw)) {
return false;
}
const bundle = (openclaw as { bundle?: unknown }).bundle;
return (
bundle !== null &&
typeof bundle === "object" &&
!Array.isArray(bundle) &&
(bundle as { includeInCore?: unknown }).includeInCore === false
);
return !isPackageIncludedInCoreBundle(getPackageManifestMetadata(packageJson as PackageManifest));
}
function readBundledCapabilityManifest(pluginDir: string): BundledCapabilityManifest | undefined {

View File

@@ -1,6 +1,7 @@
import { describe, expect, it } from "vitest";
import { uniqueSortedStrings } from "../../plugin-sdk/test-helpers/string-utils.js";
import { loadPluginManifestRegistry } from "../manifest-registry.js";
import { isPackageIncludedInCoreBundle } from "../manifest.js";
import { resolveManifestContractPluginIds } from "../plugin-registry.js";
import {
pluginRegistrationContractRegistry,
@@ -44,7 +45,11 @@ describe("plugin contract registry", () => {
}) => boolean,
) {
return loadPluginManifestRegistry({})
.plugins.filter(predicate)
.plugins.filter(
(plugin) =>
(plugin.origin !== "bundled" || isPackageIncludedInCoreBundle(plugin.packageManifest)) &&
predicate(plugin),
)
.map((plugin) => plugin.id)
.toSorted((left, right) => left.localeCompare(right));
}

View File

@@ -1530,6 +1530,10 @@ export type OpenClawPackageSetupFeatures = {
legacySessionSurfaces?: boolean;
};
export type OpenClawPackageBundle = {
includeInCore?: boolean;
};
export type OpenClawPackageManifest = {
extensions?: string[];
runtimeExtensions?: string[];
@@ -1538,6 +1542,7 @@ export type OpenClawPackageManifest = {
setupFeatures?: OpenClawPackageSetupFeatures;
channel?: PluginPackageChannel;
install?: PluginPackageInstall;
bundle?: OpenClawPackageBundle;
startup?: OpenClawPackageStartup;
};
@@ -1570,6 +1575,12 @@ export function getPackageManifestMetadata(
return manifest[MANIFEST_KEY];
}
export function isPackageIncludedInCoreBundle(
manifest: OpenClawPackageManifest | undefined,
): boolean {
return manifest?.bundle?.includeInCore !== false;
}
export function resolvePackageExtensionEntries(
manifest: PackageManifest | undefined,
): PackageExtensionResolution {

View File

@@ -12,6 +12,7 @@ import type {
PluginManifestRecord,
PluginManifestRegistry,
} from "./manifest-registry.js";
import { isPackageIncludedInCoreBundle } from "./manifest.js";
import type { PluginOrigin } from "./plugin-origin.types.js";
import {
createPluginRegistryIdNormalizer,
@@ -119,6 +120,10 @@ function sortUnique(values: Iterable<string>): string[] {
);
}
function isCoreBundledManifestSurface(plugin: PluginManifestRecord): boolean {
return plugin.origin !== "bundled" || isPackageIncludedInCoreBundle(plugin.packageManifest);
}
function collectObjectKeys(value: Record<string, unknown> | undefined): readonly string[] {
return value ? Object.keys(value) : [];
}
@@ -415,6 +420,7 @@ export function resolveManifestContractPluginIds(
.plugins.filter(
(plugin) =>
(!params.origin || plugin.origin === params.origin) &&
isCoreBundledManifestSurface(plugin) &&
listManifestContractValues(plugin, params.contract).length > 0,
)
.map((plugin) => plugin.id)
@@ -432,6 +438,7 @@ export function resolveManifestContractPluginIdsByCompatibilityRuntimePath(
.plugins.filter(
(plugin) =>
(!params.origin || plugin.origin === params.origin) &&
isCoreBundledManifestSurface(plugin) &&
listManifestContractValues(plugin, params.contract).length > 0 &&
(plugin.configContracts?.compatibilityRuntimePaths ?? []).includes(normalizedPath),
)

View File

@@ -9,6 +9,7 @@ import {
} from "./manifest-owner-policy.js";
import { loadPluginManifestRegistryForInstalledIndex } from "./manifest-registry-installed.js";
import { type PluginManifestRecord, type PluginManifestRegistry } from "./manifest-registry.js";
import { isPackageIncludedInCoreBundle } from "./manifest.js";
import {
loadPluginRegistrySnapshot,
normalizePluginsConfigWithRegistry,
@@ -71,10 +72,16 @@ function resolveProviderSurfacePluginIdSet(
resolveManifestRegistry({
...params,
includeDisabled: true,
}).plugins.flatMap((plugin) => (plugin.providers.length > 0 ? [plugin.id] : [])),
}).plugins.flatMap((plugin) =>
plugin.providers.length > 0 && isCoreBundledManifestSurface(plugin) ? [plugin.id] : [],
),
);
}
function isCoreBundledManifestSurface(plugin: PluginManifestRecord): boolean {
return plugin.origin !== "bundled" || isPackageIncludedInCoreBundle(plugin.packageManifest);
}
function resolveProviderOwnerPluginIds(
params: ProviderRegistryLoadParams & {
pluginIds: readonly string[];
@@ -139,6 +146,7 @@ export function resolveBundledProviderCompatPluginIds(params: {
.filter(
(plugin) =>
plugin.origin === "bundled" &&
isCoreBundledManifestSurface(plugin) &&
plugin.providers.length > 0 &&
(!onlyPluginIdSet || onlyPluginIdSet.has(plugin.id)),
)