




















@@ -2305,6 +2305,100 @@ describe("ensureBundledPluginRuntimeDeps", () => {
23052305expect(result).toEqual({ installedSpecs: [] });
23062306});
230723072308+it("does not scan every bundled manifest when the requested package-level deps are already materialized", () => {
2309+const packageRoot = makeTempDir();
2310+const stageDir = makeTempDir();
2311+fs.writeFileSync(
2312+path.join(packageRoot, "package.json"),
2313+JSON.stringify({ name: "openclaw", version: "2026.4.29" }),
2314+);
2315+const alphaRoot = writeBundledPluginPackage({
2316+ packageRoot,
2317+pluginId: "alpha",
2318+deps: { "alpha-runtime": "1.0.0" },
2319+enabledByDefault: true,
2320+});
2321+const betaRoot = writeBundledPluginPackage({
2322+ packageRoot,
2323+pluginId: "beta",
2324+deps: { "beta-runtime": "2.0.0" },
2325+enabledByDefault: true,
2326+});
2327+const betaManifestPath = path.join(betaRoot, "openclaw.plugin.json");
2328+const env = { OPENCLAW_PLUGIN_STAGE_DIR: stageDir };
2329+const installRoot = resolveBundledRuntimeDependencyInstallRoot(alphaRoot, { env });
2330+writeInstalledPackage(installRoot, "alpha-runtime", "1.0.0");
2331+writeInstalledPackage(installRoot, "beta-runtime", "2.0.0");
2332+writeGeneratedRuntimeDepsManifest(installRoot, ["alpha-runtime@1.0.0", "beta-runtime@2.0.0"]);
2333+const readFileSyncSpy = vi.spyOn(fs, "readFileSync");
2334+2335+const result = ensureBundledPluginRuntimeDeps({
2336+ env,
2337+pluginId: "alpha",
2338+pluginRoot: alphaRoot,
2339+installDeps: () => {
2340+throw new Error("already materialized package-level deps should not reinstall");
2341+},
2342+});
2343+2344+expect(result).toEqual({ installedSpecs: [] });
2345+expect(
2346+readFileSyncSpy.mock.calls.filter(
2347+(call) => path.resolve(String(call[0])) === betaManifestPath,
2348+),
2349+).toHaveLength(0);
2350+});
2351+2352+it("does not skip missing manifest runtime deps when package deps are materialized", () => {
2353+const packageRoot = makeTempDir();
2354+const stageDir = makeTempDir();
2355+fs.writeFileSync(
2356+path.join(packageRoot, "package.json"),
2357+JSON.stringify({ name: "openclaw", version: "2026.4.29" }),
2358+);
2359+const pluginRoot = writeBundledPluginPackage({
2360+ packageRoot,
2361+pluginId: "memory-core",
2362+deps: { chokidar: "5.0.0", typebox: "1.1.34" },
2363+runtimeDependencies: {
2364+localMemoryEmbedding: ["node-llama-cpp@3.18.1"],
2365+},
2366+});
2367+const env = { OPENCLAW_PLUGIN_STAGE_DIR: stageDir };
2368+const installRoot = resolveBundledRuntimeDependencyInstallRoot(pluginRoot, { env });
2369+writeInstalledPackage(installRoot, "chokidar", "5.0.0");
2370+writeInstalledPackage(installRoot, "typebox", "1.1.34");
2371+writeGeneratedRuntimeDepsManifest(installRoot, ["chokidar@5.0.0", "typebox@1.1.34"]);
2372+const calls: BundledRuntimeDepsInstallParams[] = [];
2373+2374+const result = ensureBundledPluginRuntimeDeps({
2375+ env,
2376+config: {
2377+agents: {
2378+defaults: {
2379+memorySearch: { provider: "local" },
2380+},
2381+},
2382+},
2383+installDeps: (params) => {
2384+calls.push(params);
2385+},
2386+pluginId: "memory-core",
2387+ pluginRoot,
2388+});
2389+2390+expect(result).toEqual({
2391+installedSpecs: ["chokidar@5.0.0", "node-llama-cpp@3.18.1", "typebox@1.1.34"],
2392+});
2393+expect(calls).toEqual([
2394+{
2395+ installRoot,
2396+missingSpecs: ["chokidar@5.0.0", "node-llama-cpp@3.18.1", "typebox@1.1.34"],
2397+installSpecs: ["chokidar@5.0.0", "node-llama-cpp@3.18.1", "typebox@1.1.34"],
2398+},
2399+]);
2400+});
2401+23082402it("accepts generated package-level runtime-deps supersets without reinstalling", () => {
23092403const packageRoot = makeTempDir();
23102404const stageDir = makeTempDir();
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。