mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-13 11:00:50 +00:00
* fix: prefer bundled channel plugins over npm duplicates * fix: tighten bundled plugin review follow-ups * fix: address check gate follow-ups * docs: add changelog for bundled plugin install fix * fix: align lifecycle test formatting with CI oxfmt
85 lines
2.5 KiB
TypeScript
85 lines
2.5 KiB
TypeScript
import type { BundledPluginSource } from "../plugins/bundled-sources.js";
|
|
import { PLUGIN_INSTALL_ERROR_CODE } from "../plugins/install.js";
|
|
import { shortenHomePath } from "../utils.js";
|
|
|
|
type BundledLookup = (params: {
|
|
kind: "pluginId" | "npmSpec";
|
|
value: string;
|
|
}) => BundledPluginSource | undefined;
|
|
|
|
function isBareNpmPackageName(spec: string): boolean {
|
|
const trimmed = spec.trim();
|
|
return /^[a-z0-9][a-z0-9-._~]*$/.test(trimmed);
|
|
}
|
|
|
|
export function resolveBundledInstallPlanForCatalogEntry(params: {
|
|
pluginId: string;
|
|
npmSpec: string;
|
|
findBundledSource: BundledLookup;
|
|
}): { bundledSource: BundledPluginSource } | null {
|
|
const pluginId = params.pluginId.trim();
|
|
const npmSpec = params.npmSpec.trim();
|
|
if (!pluginId || !npmSpec) {
|
|
return null;
|
|
}
|
|
|
|
const bundledById = params.findBundledSource({
|
|
kind: "pluginId",
|
|
value: pluginId,
|
|
});
|
|
if (bundledById?.pluginId === pluginId) {
|
|
return { bundledSource: bundledById };
|
|
}
|
|
|
|
const bundledBySpec = params.findBundledSource({
|
|
kind: "npmSpec",
|
|
value: npmSpec,
|
|
});
|
|
if (bundledBySpec?.pluginId === pluginId) {
|
|
return { bundledSource: bundledBySpec };
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
export function resolveBundledInstallPlanBeforeNpm(params: {
|
|
rawSpec: string;
|
|
findBundledSource: BundledLookup;
|
|
}): { bundledSource: BundledPluginSource; warning: string } | null {
|
|
if (!isBareNpmPackageName(params.rawSpec)) {
|
|
return null;
|
|
}
|
|
const bundledSource = params.findBundledSource({
|
|
kind: "pluginId",
|
|
value: params.rawSpec,
|
|
});
|
|
if (!bundledSource) {
|
|
return null;
|
|
}
|
|
return {
|
|
bundledSource,
|
|
warning: `Using bundled plugin "${bundledSource.pluginId}" from ${shortenHomePath(bundledSource.localPath)} for bare install spec "${params.rawSpec}". To install an npm package with the same name, use a scoped package name (for example @scope/${params.rawSpec}).`,
|
|
};
|
|
}
|
|
|
|
export function resolveBundledInstallPlanForNpmFailure(params: {
|
|
rawSpec: string;
|
|
code?: string;
|
|
findBundledSource: BundledLookup;
|
|
}): { bundledSource: BundledPluginSource; warning: string } | null {
|
|
if (params.code !== PLUGIN_INSTALL_ERROR_CODE.NPM_PACKAGE_NOT_FOUND) {
|
|
return null;
|
|
}
|
|
const bundledSource = params.findBundledSource({
|
|
kind: "npmSpec",
|
|
value: params.rawSpec,
|
|
});
|
|
if (!bundledSource) {
|
|
return null;
|
|
}
|
|
return {
|
|
bundledSource,
|
|
warning: `npm package unavailable for ${params.rawSpec}; using bundled plugin at ${shortenHomePath(bundledSource.localPath)}.`,
|
|
};
|
|
}
|