mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 05:50:43 +00:00
fix(plugins): stop runtime deps reinstall loops
This commit is contained in:
@@ -11,6 +11,7 @@ Docs: https://docs.openclaw.ai
|
||||
|
||||
### Fixes
|
||||
|
||||
- Plugins/runtime-deps: accept already materialized package-level runtime-deps supersets as converged, so later lazy plugin activation no longer prunes and relaunches `pnpm install` after gateway startup pre-staging. Fixes #75283. Thanks @brokemac79.
|
||||
- TTS/providers: keep bundled speech-provider compat fallback available when plugins are globally disabled, so cold gateway and CLI startup can still resolve fallback speech providers instead of leaving explicit TTS provider selection with no registered providers. Refs #75265. Thanks @sliekens.
|
||||
- Discord: collapse repeated native slash-command deploy rate-limit startup logs into one non-fatal warning while keeping per-request REST timing in verbose output. Thanks @discord.
|
||||
- Providers/OpenAI Codex: preserve existing wrapped Codex streams during OpenAI attribution so PI OAuth bearer injection reaches ChatGPT/Codex Responses, and strip native Codex-only unsupported payload fields without touching custom compatible endpoints. (#75111) Thanks @keshavbotagent.
|
||||
|
||||
@@ -52,6 +52,14 @@ function sameRuntimeDepSpecs(left: readonly string[], right: readonly string[]):
|
||||
);
|
||||
}
|
||||
|
||||
function runtimeDepSpecsIncludeAll(
|
||||
candidate: readonly string[],
|
||||
required: readonly string[],
|
||||
): boolean {
|
||||
const candidateSet = new Set(normalizeRuntimeDepSpecs(candidate));
|
||||
return normalizeRuntimeDepSpecs(required).every((spec) => candidateSet.has(spec));
|
||||
}
|
||||
|
||||
function readInstalledRuntimeDepPackage(
|
||||
rootDir: string,
|
||||
depName: string,
|
||||
@@ -129,7 +137,7 @@ export function isRuntimeDepsPlanMaterialized(
|
||||
generatedManifestSpecs !== null ? null : readPackageRuntimeDepSpecs(installRoot);
|
||||
return (
|
||||
((generatedManifestSpecs !== null &&
|
||||
sameRuntimeDepSpecs(generatedManifestSpecs, installSpecs)) ||
|
||||
runtimeDepSpecsIncludeAll(generatedManifestSpecs, installSpecs)) ||
|
||||
(packageManifestSpecs !== null && sameRuntimeDepSpecs(packageManifestSpecs, installSpecs))) &&
|
||||
hasSatisfiedInstallSpecPackages(installRoot, installSpecs)
|
||||
);
|
||||
|
||||
@@ -2305,6 +2305,49 @@ describe("ensureBundledPluginRuntimeDeps", () => {
|
||||
expect(result).toEqual({ installedSpecs: [] });
|
||||
});
|
||||
|
||||
it("accepts generated package-level runtime-deps supersets without reinstalling", () => {
|
||||
const packageRoot = makeTempDir();
|
||||
const stageDir = makeTempDir();
|
||||
fs.writeFileSync(
|
||||
path.join(packageRoot, "package.json"),
|
||||
JSON.stringify({ name: "openclaw", version: "2026.4.29" }),
|
||||
);
|
||||
const alphaRoot = writeBundledPluginPackage({
|
||||
packageRoot,
|
||||
pluginId: "alpha",
|
||||
deps: { "alpha-runtime": "1.0.0" },
|
||||
enabledByDefault: true,
|
||||
});
|
||||
writeBundledPluginPackage({
|
||||
packageRoot,
|
||||
pluginId: "tokenjuice",
|
||||
deps: { tokenjuice: "0.7.0" },
|
||||
enabledByDefault: true,
|
||||
});
|
||||
const env = { OPENCLAW_PLUGIN_STAGE_DIR: stageDir };
|
||||
const installRoot = resolveBundledRuntimeDependencyInstallRoot(alphaRoot, { env });
|
||||
writeInstalledPackage(installRoot, "alpha-runtime", "1.0.0");
|
||||
writeInstalledPackage(installRoot, "tokenjuice", "0.7.0");
|
||||
writeGeneratedRuntimeDepsManifest(installRoot, ["alpha-runtime@1.0.0", "tokenjuice@0.7.0"]);
|
||||
|
||||
const result = ensureBundledPluginRuntimeDeps({
|
||||
env,
|
||||
config: {
|
||||
plugins: {
|
||||
allow: ["alpha"],
|
||||
entries: { alpha: { enabled: true } },
|
||||
},
|
||||
},
|
||||
pluginId: "alpha",
|
||||
pluginRoot: alphaRoot,
|
||||
installDeps: () => {
|
||||
throw new Error("compatible runtime deps superset should not reinstall");
|
||||
},
|
||||
});
|
||||
|
||||
expect(result).toEqual({ installedSpecs: [] });
|
||||
});
|
||||
|
||||
it("drops stale package versions from the next package-level plan", () => {
|
||||
const packageRoot = makeTempDir();
|
||||
const stageDir = makeTempDir();
|
||||
|
||||
Reference in New Issue
Block a user