Files
openclaw/src/plugins/bundled-sources.ts
scoootscooob da8a17d8de fix(plugins): fall back to bundled plugin when npm spec resolves to non-OpenClaw package (#32019)
When `openclaw plugins install diffs` downloads the unrelated npm
package `diffs@0.1.1` (which lacks `openclaw.extensions`), the install
fails without trying the bundled `@openclaw/diffs` plugin.

Two fixes:
1. Broaden the bundled-fallback trigger to also fire on
   "missing openclaw.extensions" errors (not just npm 404s)
2. Match bundled plugins by pluginId in addition to npmSpec so
   unscoped names like "diffs" resolve to `@openclaw/diffs`

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 20:49:50 +00:00

67 lines
1.8 KiB
TypeScript

import { discoverOpenClawPlugins } from "./discovery.js";
import { loadPluginManifest } from "./manifest.js";
export type BundledPluginSource = {
pluginId: string;
localPath: string;
npmSpec?: string;
};
export function resolveBundledPluginSources(params: {
workspaceDir?: string;
}): Map<string, BundledPluginSource> {
const discovery = discoverOpenClawPlugins({ workspaceDir: params.workspaceDir });
const bundled = new Map<string, BundledPluginSource>();
for (const candidate of discovery.candidates) {
if (candidate.origin !== "bundled") {
continue;
}
const manifest = loadPluginManifest(candidate.rootDir);
if (!manifest.ok) {
continue;
}
const pluginId = manifest.manifest.id;
if (bundled.has(pluginId)) {
continue;
}
const npmSpec =
candidate.packageManifest?.install?.npmSpec?.trim() ||
candidate.packageName?.trim() ||
undefined;
bundled.set(pluginId, {
pluginId,
localPath: candidate.rootDir,
npmSpec,
});
}
return bundled;
}
export function findBundledPluginByNpmSpec(params: {
spec: string;
workspaceDir?: string;
}): BundledPluginSource | undefined {
const targetSpec = params.spec.trim();
if (!targetSpec) {
return undefined;
}
const bundled = resolveBundledPluginSources({ workspaceDir: params.workspaceDir });
for (const source of bundled.values()) {
if (source.npmSpec === targetSpec) {
return source;
}
// Also match by plugin id so that e.g. `openclaw plugins install diffs`
// resolves to the bundled @openclaw/diffs plugin when the unscoped npm
// package `diffs` is not a valid OpenClaw plugin.
// See: https://github.com/openclaw/openclaw/issues/32019
if (source.pluginId === targetSpec) {
return source;
}
}
return undefined;
}