fix(update): polish stale bundled shadow cleanup

This commit is contained in:
scoootscooob
2026-05-21 00:32:32 -07:00
parent 6b0361cdef
commit 8bcbf681ec
3 changed files with 15 additions and 11 deletions

View File

@@ -13,6 +13,7 @@ Docs: https://docs.openclaw.ai
- fix(config): validate browser sandbox bind sources [AI]. (#84799) Thanks @pgondhi987.
- doctor: constrain legacy plugin cleanup paths [AI]. (#84801) Thanks @pgondhi987.
- Update/doctor: prune stale local bundled plugin install records that point at old compiled bundled output so current bundled plugin schemas win after upgrade. (#84863) Thanks @fuller-stack-dev.
- Media/audio: skip empty structured sherpa-onnx transcripts instead of treating the raw JSON payload as spoken text. (#84667) Thanks @TurboTheTurtle.
- Node/Linux: keep `OPENCLAW_GATEWAY_TOKEN` out of generated systemd unit files by writing node service token values to a node-specific env file. (#84408)
- Memory-core/dreaming: reuse stable narrative subagent session keys per workspace and phase while keeping per-run idempotency and bounded cleanup, so stale `dreaming-narrative-*` sessions do not accumulate. Fixes #68252, #69187, and #70402. (#70464) Thanks @chiyouYCH.

View File

@@ -112,7 +112,9 @@ function listStaleManagedNpmBundledPlugins(
const dependencies = readStringMap(readJsonObject(npmPackageJsonPath)?.dependencies);
const stale: StaleManagedNpmBundledPlugin[] = [];
for (const packageName of Object.keys(dependencies).toSorted()) {
for (const packageName of Object.keys(dependencies).toSorted((left, right) =>
left.localeCompare(right),
)) {
if (!packageName.startsWith("@openclaw/")) {
continue;
}

View File

@@ -12,10 +12,6 @@ export type StaleLocalBundledPluginInstallRecord = {
bundledPath: string;
};
function escapeRegExp(input: string): string {
return input.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
function normalizePathForCompare(rawPath: string, env?: NodeJS.ProcessEnv): string {
return path.resolve(normalizeBundledLookupPath(resolveUserPath(rawPath, env)));
}
@@ -34,11 +30,14 @@ function primaryInstallRecordPath(record: PluginInstallRecord): {
}
function looksLikeCompiledBundledPluginPath(targetPath: string, pluginId: string): boolean {
const normalized = normalizeBundledLookupPath(targetPath).split(path.sep).join("/");
const escapedPluginId = escapeRegExp(pluginId);
return new RegExp(`(?:^|/)(?:dist|dist-runtime)/extensions/${escapedPluginId}(?:$|/)`).test(
normalized,
);
const segments = normalizeBundledLookupPath(targetPath).split(/[\\/]+/u);
return segments.some((segment, index) => {
return (
(segment === "dist" || segment === "dist-runtime") &&
segments[index + 1] === "extensions" &&
segments[index + 2] === pluginId
);
});
}
function hasStaleBundledVersion(
@@ -64,7 +63,9 @@ export function listStaleLocalBundledPluginInstallRecords(params: {
});
const stale: StaleLocalBundledPluginInstallRecord[] = [];
for (const [pluginId, record] of Object.entries(params.installRecords).toSorted()) {
for (const [pluginId, record] of Object.entries(params.installRecords).toSorted(
([left], [right]) => left.localeCompare(right),
)) {
if (record.source !== "path") {
continue;
}