mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 10:40:43 +00:00
perf(plugins): memoize packaged runtime dist mirrors
This commit is contained in:
@@ -18,6 +18,7 @@ Docs: https://docs.openclaw.ai
|
||||
|
||||
### Fixes
|
||||
|
||||
- Plugins/runtime-deps: memoize packaged bundled runtime dist-mirror preparation after the first successful pass while keeping source-checkout mirrors refreshable, so constrained Docker/VPS installs avoid repeated root scans before chat turns. Refs #73428, #73421, #73532, and #73477. Thanks @Dimaoggg, @oromeis, @oadiazp, @jmfraga, @bstanbury, @antoniusfelix, and @jkobject.
|
||||
- Channels/Discord: treat bare numeric outbound targets that match the effective Discord DM allowlist as user DMs while preserving account-specific legacy `dm.allowFrom` precedence over inherited root `allowFrom`. (#74303) Thanks @Squirbie.
|
||||
- Control UI: make the chat sidebar split divider focusable, keyboard-resizable, ARIA-described, and pointer-event based so sidebar resizing works without a mouse. Thanks @BunsDev.
|
||||
- Agents/auth: keep OAuth auth profiles inherited from the main agent read-through instead of copying refresh tokens into secondary agents, and refresh Codex app-server tokens against the owning store so multi-agent swarms avoid reused refresh-token failures. Fixes #74055. Thanks @ClarityInvest.
|
||||
|
||||
52
src/plugins/bundled-runtime-dist-mirror-cache.ts
Normal file
52
src/plugins/bundled-runtime-dist-mirror-cache.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
const preparedBundledRuntimeDistMirrors = new Set<string>();
|
||||
|
||||
export function clearBundledRuntimeDistMirrorPreparationCache(): void {
|
||||
preparedBundledRuntimeDistMirrors.clear();
|
||||
}
|
||||
|
||||
export function shouldReusePreparedBundledRuntimeDistMirror(params: {
|
||||
sourceDistRoot: string;
|
||||
mirrorDistRoot: string;
|
||||
}): boolean {
|
||||
if (isSourceCheckoutDistRoot(params.sourceDistRoot)) {
|
||||
return false;
|
||||
}
|
||||
if (!preparedBundledRuntimeDistMirrors.has(bundledRuntimeDistMirrorCacheKey(params))) {
|
||||
return false;
|
||||
}
|
||||
return (
|
||||
fs.existsSync(params.mirrorDistRoot) &&
|
||||
fs.existsSync(path.join(params.mirrorDistRoot, "extensions")) &&
|
||||
fs.existsSync(path.join(params.mirrorDistRoot, "package.json"))
|
||||
);
|
||||
}
|
||||
|
||||
export function markBundledRuntimeDistMirrorPrepared(params: {
|
||||
sourceDistRoot: string;
|
||||
mirrorDistRoot: string;
|
||||
}): void {
|
||||
if (isSourceCheckoutDistRoot(params.sourceDistRoot)) {
|
||||
return;
|
||||
}
|
||||
preparedBundledRuntimeDistMirrors.add(bundledRuntimeDistMirrorCacheKey(params));
|
||||
}
|
||||
|
||||
function bundledRuntimeDistMirrorCacheKey(params: {
|
||||
sourceDistRoot: string;
|
||||
mirrorDistRoot: string;
|
||||
}): string {
|
||||
return `${path.resolve(params.sourceDistRoot)}\0${path.resolve(params.mirrorDistRoot)}`;
|
||||
}
|
||||
|
||||
function isSourceCheckoutDistRoot(sourceDistRoot: string): boolean {
|
||||
const packageRoot = path.dirname(sourceDistRoot);
|
||||
return (
|
||||
(fs.existsSync(path.join(packageRoot, ".git")) ||
|
||||
fs.existsSync(path.join(packageRoot, "pnpm-workspace.yaml"))) &&
|
||||
fs.existsSync(path.join(packageRoot, "src")) &&
|
||||
fs.existsSync(path.join(packageRoot, "extensions"))
|
||||
);
|
||||
}
|
||||
@@ -198,7 +198,9 @@ describe("prepareBundledPluginRuntimeRoot", () => {
|
||||
}
|
||||
|
||||
const realReadFileSync = fs.readFileSync.bind(fs);
|
||||
const realReaddirSync = fs.readdirSync.bind(fs);
|
||||
const readPaths: string[] = [];
|
||||
const readdirPaths: string[] = [];
|
||||
vi.spyOn(fs, "readFileSync").mockImplementation(((target, options) => {
|
||||
const targetPath = target.toString();
|
||||
if (targetPath === rootChunk || targetPath === externalChunk) {
|
||||
@@ -206,6 +208,16 @@ describe("prepareBundledPluginRuntimeRoot", () => {
|
||||
}
|
||||
return realReadFileSync(target, options as never);
|
||||
}) as typeof fs.readFileSync);
|
||||
vi.spyOn(fs, "readdirSync").mockImplementation(((target, options) => {
|
||||
const targetPath = target.toString();
|
||||
if (
|
||||
targetPath === path.join(packageRoot, "dist") &&
|
||||
new Error().stack?.includes("mirrorBundledRuntimeDistRootEntries")
|
||||
) {
|
||||
readdirPaths.push(targetPath);
|
||||
}
|
||||
return realReaddirSync(target, options as never);
|
||||
}) as typeof fs.readdirSync);
|
||||
|
||||
for (const pluginId of ["alpha", "beta"]) {
|
||||
const pluginRoot = path.join(packageRoot, "dist", "extensions", pluginId);
|
||||
@@ -219,6 +231,75 @@ describe("prepareBundledPluginRuntimeRoot", () => {
|
||||
|
||||
expect(readPaths.filter((entry) => entry === rootChunk)).toHaveLength(1);
|
||||
expect(readPaths.filter((entry) => entry === externalChunk)).toHaveLength(1);
|
||||
expect(readdirPaths).toHaveLength(1);
|
||||
});
|
||||
|
||||
it("does not memoize source-checkout dist mirrors", () => {
|
||||
const packageRoot = makeTempRoot();
|
||||
const stageDir = makeTempRoot();
|
||||
const env = { ...process.env, OPENCLAW_PLUGIN_STAGE_DIR: stageDir };
|
||||
fs.mkdirSync(path.join(packageRoot, ".git"), { recursive: true });
|
||||
fs.mkdirSync(path.join(packageRoot, "src"), { recursive: true });
|
||||
fs.mkdirSync(path.join(packageRoot, "extensions"), { recursive: true });
|
||||
const pluginRoot = path.join(packageRoot, "dist", "extensions", "alpha");
|
||||
fs.mkdirSync(pluginRoot, { recursive: true });
|
||||
fs.writeFileSync(
|
||||
path.join(packageRoot, "package.json"),
|
||||
JSON.stringify({ name: "openclaw", version: "2026.4.27", type: "module" }),
|
||||
"utf8",
|
||||
);
|
||||
fs.writeFileSync(path.join(packageRoot, "dist", "shared-runtime.js"), "export {};\n", "utf8");
|
||||
fs.writeFileSync(
|
||||
path.join(pluginRoot, "index.js"),
|
||||
`import "../../shared-runtime.js"; export default { id: "alpha" };\n`,
|
||||
"utf8",
|
||||
);
|
||||
fs.writeFileSync(
|
||||
path.join(pluginRoot, "package.json"),
|
||||
JSON.stringify(
|
||||
{
|
||||
name: "@openclaw/alpha",
|
||||
version: "1.0.0",
|
||||
type: "module",
|
||||
dependencies: { "alpha-runtime": "1.0.0" },
|
||||
openclaw: { extensions: ["./index.js"] },
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
"utf8",
|
||||
);
|
||||
const installRoot = resolveBundledRuntimeDependencyInstallRoot(pluginRoot, { env });
|
||||
fs.mkdirSync(path.join(installRoot, "node_modules", "alpha-runtime"), { recursive: true });
|
||||
fs.writeFileSync(
|
||||
path.join(installRoot, "node_modules", "alpha-runtime", "package.json"),
|
||||
JSON.stringify({ name: "alpha-runtime", version: "1.0.0", type: "module" }),
|
||||
"utf8",
|
||||
);
|
||||
|
||||
const realReaddirSync = fs.readdirSync.bind(fs);
|
||||
const readdirPaths: string[] = [];
|
||||
vi.spyOn(fs, "readdirSync").mockImplementation(((target, options) => {
|
||||
const targetPath = target.toString();
|
||||
if (
|
||||
targetPath === path.join(packageRoot, "dist") &&
|
||||
new Error().stack?.includes("mirrorBundledRuntimeDistRootEntries")
|
||||
) {
|
||||
readdirPaths.push(targetPath);
|
||||
}
|
||||
return realReaddirSync(target, options as never);
|
||||
}) as typeof fs.readdirSync);
|
||||
|
||||
for (let index = 0; index < 2; index += 1) {
|
||||
prepareBundledPluginRuntimeRoot({
|
||||
pluginId: "alpha",
|
||||
pluginRoot,
|
||||
modulePath: path.join(pluginRoot, "index.js"),
|
||||
env,
|
||||
});
|
||||
}
|
||||
|
||||
expect(readdirPaths).toHaveLength(2);
|
||||
});
|
||||
|
||||
it("does not copy staged runtime mirror dist files onto themselves", () => {
|
||||
|
||||
@@ -9,6 +9,10 @@ import {
|
||||
shouldMaterializeBundledRuntimeMirrorDistFile,
|
||||
withBundledRuntimeDepsFilesystemLock,
|
||||
} from "./bundled-runtime-deps.js";
|
||||
import {
|
||||
markBundledRuntimeDistMirrorPrepared,
|
||||
shouldReusePreparedBundledRuntimeDistMirror,
|
||||
} from "./bundled-runtime-dist-mirror-cache.js";
|
||||
import {
|
||||
copyBundledPluginRuntimeRoot,
|
||||
precomputeBundledRuntimeMirrorMetadata,
|
||||
@@ -162,10 +166,13 @@ function prepareBundledPluginRuntimeDistMirror(params: {
|
||||
ensureBundledRuntimeMirrorDirectory(mirrorDistRoot);
|
||||
fs.mkdirSync(mirrorExtensionsRoot, { recursive: true, mode: 0o755 });
|
||||
ensureBundledRuntimeDistPackageJson(mirrorDistRoot);
|
||||
mirrorBundledRuntimeDistRootEntries({
|
||||
sourceDistRoot,
|
||||
mirrorDistRoot,
|
||||
});
|
||||
if (!shouldReusePreparedBundledRuntimeDistMirror({ sourceDistRoot, mirrorDistRoot })) {
|
||||
mirrorBundledRuntimeDistRootEntries({
|
||||
sourceDistRoot,
|
||||
mirrorDistRoot,
|
||||
});
|
||||
markBundledRuntimeDistMirrorPrepared({ sourceDistRoot, mirrorDistRoot });
|
||||
}
|
||||
if (sourceDistRootName === "dist-runtime") {
|
||||
mirrorCanonicalBundledRuntimeDistRoot({
|
||||
installRoot: params.installRoot,
|
||||
@@ -242,10 +249,21 @@ function mirrorCanonicalBundledRuntimeDistRoot(params: {
|
||||
ensureBundledRuntimeMirrorDirectory(targetCanonicalDistRoot);
|
||||
fs.mkdirSync(path.join(targetCanonicalDistRoot, "extensions"), { recursive: true, mode: 0o755 });
|
||||
ensureBundledRuntimeDistPackageJson(targetCanonicalDistRoot);
|
||||
mirrorBundledRuntimeDistRootEntries({
|
||||
sourceDistRoot: sourceCanonicalDistRoot,
|
||||
mirrorDistRoot: targetCanonicalDistRoot,
|
||||
});
|
||||
if (
|
||||
!shouldReusePreparedBundledRuntimeDistMirror({
|
||||
sourceDistRoot: sourceCanonicalDistRoot,
|
||||
mirrorDistRoot: targetCanonicalDistRoot,
|
||||
})
|
||||
) {
|
||||
mirrorBundledRuntimeDistRootEntries({
|
||||
sourceDistRoot: sourceCanonicalDistRoot,
|
||||
mirrorDistRoot: targetCanonicalDistRoot,
|
||||
});
|
||||
markBundledRuntimeDistMirrorPrepared({
|
||||
sourceDistRoot: sourceCanonicalDistRoot,
|
||||
mirrorDistRoot: targetCanonicalDistRoot,
|
||||
});
|
||||
}
|
||||
ensureOpenClawPluginSdkAlias(targetCanonicalDistRoot);
|
||||
|
||||
const pluginId = path.basename(params.pluginRoot);
|
||||
|
||||
@@ -43,6 +43,11 @@ import {
|
||||
withBundledRuntimeDepsFilesystemLock,
|
||||
type BundledRuntimeDepsInstallParams,
|
||||
} from "./bundled-runtime-deps.js";
|
||||
import {
|
||||
clearBundledRuntimeDistMirrorPreparationCache,
|
||||
markBundledRuntimeDistMirrorPrepared,
|
||||
shouldReusePreparedBundledRuntimeDistMirror,
|
||||
} from "./bundled-runtime-dist-mirror-cache.js";
|
||||
import {
|
||||
copyBundledPluginRuntimeRoot,
|
||||
precomputeBundledRuntimeMirrorMetadata,
|
||||
@@ -114,8 +119,8 @@ import {
|
||||
normalizePluginIdScope,
|
||||
serializePluginIdScope,
|
||||
} from "./plugin-scope.js";
|
||||
import { createPluginRegistry, type PluginRecord, type PluginRegistry } from "./registry.js";
|
||||
import { createEmptyPluginRegistry } from "./registry-empty.js";
|
||||
import { createPluginRegistry, type PluginRecord, type PluginRegistry } from "./registry.js";
|
||||
import { resolvePluginCacheInputs } from "./roots.js";
|
||||
import {
|
||||
getActivePluginRegistry,
|
||||
@@ -280,6 +285,7 @@ function createPluginCandidatesFromManifestRegistry(
|
||||
export function clearPluginLoaderCache(): void {
|
||||
pluginLoaderCacheState.clear();
|
||||
clearBundledRuntimeDependencyNodePaths();
|
||||
clearBundledRuntimeDistMirrorPreparationCache();
|
||||
bundledRuntimeDependencyJitiAliases.clear();
|
||||
clearAgentHarnesses();
|
||||
clearPluginCommands();
|
||||
@@ -770,10 +776,13 @@ function prepareBundledPluginRuntimeDistMirror(params: {
|
||||
ensureBundledRuntimeMirrorDirectory(mirrorDistRoot);
|
||||
fs.mkdirSync(mirrorExtensionsRoot, { recursive: true, mode: 0o755 });
|
||||
ensureBundledRuntimeDistPackageJson(mirrorDistRoot);
|
||||
mirrorBundledRuntimeDistRootEntries({
|
||||
sourceDistRoot,
|
||||
mirrorDistRoot,
|
||||
});
|
||||
if (!shouldReusePreparedBundledRuntimeDistMirror({ sourceDistRoot, mirrorDistRoot })) {
|
||||
mirrorBundledRuntimeDistRootEntries({
|
||||
sourceDistRoot,
|
||||
mirrorDistRoot,
|
||||
});
|
||||
markBundledRuntimeDistMirrorPrepared({ sourceDistRoot, mirrorDistRoot });
|
||||
}
|
||||
if (sourceDistRootName === "dist-runtime") {
|
||||
mirrorCanonicalBundledRuntimeDistRoot({
|
||||
installRoot: params.installRoot,
|
||||
@@ -850,10 +859,21 @@ function mirrorCanonicalBundledRuntimeDistRoot(params: {
|
||||
ensureBundledRuntimeMirrorDirectory(targetCanonicalDistRoot);
|
||||
fs.mkdirSync(path.join(targetCanonicalDistRoot, "extensions"), { recursive: true, mode: 0o755 });
|
||||
ensureBundledRuntimeDistPackageJson(targetCanonicalDistRoot);
|
||||
mirrorBundledRuntimeDistRootEntries({
|
||||
sourceDistRoot: sourceCanonicalDistRoot,
|
||||
mirrorDistRoot: targetCanonicalDistRoot,
|
||||
});
|
||||
if (
|
||||
!shouldReusePreparedBundledRuntimeDistMirror({
|
||||
sourceDistRoot: sourceCanonicalDistRoot,
|
||||
mirrorDistRoot: targetCanonicalDistRoot,
|
||||
})
|
||||
) {
|
||||
mirrorBundledRuntimeDistRootEntries({
|
||||
sourceDistRoot: sourceCanonicalDistRoot,
|
||||
mirrorDistRoot: targetCanonicalDistRoot,
|
||||
});
|
||||
markBundledRuntimeDistMirrorPrepared({
|
||||
sourceDistRoot: sourceCanonicalDistRoot,
|
||||
mirrorDistRoot: targetCanonicalDistRoot,
|
||||
});
|
||||
}
|
||||
ensureOpenClawPluginSdkAlias(targetCanonicalDistRoot);
|
||||
|
||||
const pluginId = path.basename(params.pluginRoot);
|
||||
@@ -2243,12 +2263,7 @@ export function loadOpenClawPlugins(options: PluginLoadOptions = {}): PluginRegi
|
||||
clearPluginInteractiveHandlers();
|
||||
clearDetachedTaskLifecycleRuntimeRegistration();
|
||||
clearMemoryPluginState();
|
||||
activatePluginRegistry(
|
||||
emptyRegistry,
|
||||
cacheKey,
|
||||
runtimeSubagentMode,
|
||||
options.workspaceDir,
|
||||
);
|
||||
activatePluginRegistry(emptyRegistry, cacheKey, runtimeSubagentMode, options.workspaceDir);
|
||||
}
|
||||
return emptyRegistry;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user