




















@@ -63,6 +63,8 @@ const BUNDLED_RUNTIME_DEPS_LOCK_STALE_MS = 10 * 60_000;
6363const BUNDLED_RUNTIME_DEPS_OWNERLESS_LOCK_STALE_MS = 30_000;
6464const BUNDLED_RUNTIME_MIRROR_MATERIALIZED_EXTENSIONS = new Set([".cjs", ".js", ".mjs"]);
6565const BUNDLED_RUNTIME_MIRROR_PLUGIN_REGION_RE = /(?:^|\n)\/\/#region extensions\/[^/\s]+(?:\/|$)/u;
66+const MIRRORED_PACKAGE_RUNTIME_DEP_NAMES = ["tslog"] as const;
67+const MIRRORED_PACKAGE_RUNTIME_DEP_PLUGIN_ID = "openclaw-core";
66686769const registeredBundledRuntimeDepNodePaths = new Set<string>();
6870@@ -456,6 +458,56 @@ function collectRuntimeDeps(packageJson: JsonObject): Record<string, unknown> {
456458};
457459}
458460461+function collectMirroredPackageRuntimeDeps(packageRoot: string | null): {
462+name: string;
463+version: string;
464+}[] {
465+if (!packageRoot) {
466+return [];
467+}
468+const packageJson = readJsonObject(path.join(packageRoot, "package.json"));
469+if (!packageJson) {
470+return [];
471+}
472+const runtimeDeps = collectRuntimeDeps(packageJson);
473+return MIRRORED_PACKAGE_RUNTIME_DEP_NAMES.flatMap((name) => {
474+const dep = parseInstallableRuntimeDep(name, runtimeDeps[name]);
475+return dep ? [dep] : [];
476+});
477+}
478+479+function mergeInstallableRuntimeDeps(
480+deps: readonly { name: string; version: string }[],
481+): { name: string; version: string }[] {
482+const bySpec = new Map<string, { name: string; version: string }>();
483+for (const dep of deps) {
484+bySpec.set(`${dep.name}@${dep.version}`, dep);
485+}
486+return [...bySpec.values()].toSorted((left, right) => {
487+const nameOrder = left.name.localeCompare(right.name);
488+return nameOrder === 0 ? left.version.localeCompare(right.version) : nameOrder;
489+});
490+}
491+492+function mergeRuntimeDepEntries(deps: readonly RuntimeDepEntry[]): RuntimeDepEntry[] {
493+const bySpec = new Map<string, RuntimeDepEntry>();
494+for (const dep of deps) {
495+const spec = `${dep.name}@${dep.version}`;
496+const existing = bySpec.get(spec);
497+if (!existing) {
498+bySpec.set(spec, { ...dep, pluginIds: [...dep.pluginIds] });
499+continue;
500+}
501+existing.pluginIds = [...new Set([...existing.pluginIds, ...dep.pluginIds])].toSorted(
502+(left, right) => left.localeCompare(right),
503+);
504+}
505+return [...bySpec.values()].toSorted((left, right) => {
506+const nameOrder = left.name.localeCompare(right.name);
507+return nameOrder === 0 ? left.version.localeCompare(right.version) : nameOrder;
508+});
509+}
510+459511function isSourceCheckoutRoot(packageRoot: string): boolean {
460512return (
461513(fs.existsSync(path.join(packageRoot, ".git")) ||
@@ -1083,9 +1135,11 @@ function collectBundledPluginRuntimeDeps(params: {
10831135}): {
10841136deps: RuntimeDepEntry[];
10851137conflicts: RuntimeDepConflict[];
1138+pluginIds: string[];
10861139} {
10871140const versionMap = new Map<string, Map<string, Set<string>>>();
10881141const manifestCache: BundledPluginRuntimeDepsManifestCache = new Map();
1142+const includedPluginIds = new Set<string>();
1089114310901144for (const entry of fs.readdirSync(params.extensionsDir, { withFileTypes: true })) {
10911145if (!entry.isDirectory()) {
@@ -1106,6 +1160,7 @@ function collectBundledPluginRuntimeDeps(params: {
11061160) {
11071161continue;
11081162}
1163+includedPluginIds.add(pluginId);
11091164const packageJson = readJsonObject(path.join(pluginDir, "package.json"));
11101165if (!packageJson) {
11111166continue;
@@ -1155,6 +1210,7 @@ function collectBundledPluginRuntimeDeps(params: {
11551210return {
11561211deps: deps.toSorted((a, b) => a.name.localeCompare(b.name)),
11571212conflicts: conflicts.toSorted((a, b) => a.name.localeCompare(b.name)),
1213+pluginIds: [...includedPluginIds].toSorted((a, b) => a.localeCompare(b)),
11581214};
11591215}
11601216@@ -1189,29 +1245,42 @@ export function scanBundledPluginRuntimeDeps(params: {
11891245if (!fs.existsSync(extensionsDir)) {
11901246return { deps: [], missing: [], conflicts: [] };
11911247}
1192-const { deps, conflicts } = collectBundledPluginRuntimeDeps({
1248+const { deps, conflicts, pluginIds } = collectBundledPluginRuntimeDeps({
11931249 extensionsDir,
11941250config: params.config,
11951251pluginIds: normalizePluginIdSet(params.pluginIds),
11961252selectedPluginIds: normalizePluginIdSet(params.selectedPluginIds),
11971253includeConfiguredChannels: params.includeConfiguredChannels,
11981254});
1255+const packageRuntimeDeps =
1256+pluginIds.length > 0
1257+ ? collectMirroredPackageRuntimeDeps(params.packageRoot).map((dep) => ({
1258+name: dep.name,
1259+version: dep.version,
1260+pluginIds: [MIRRORED_PACKAGE_RUNTIME_DEP_PLUGIN_ID],
1261+}))
1262+ : [];
1263+const allDeps = mergeRuntimeDepEntries([...deps, ...packageRuntimeDeps]);
11991264const packageInstallRoot = resolveBundledRuntimeDependencyPackageInstallRoot(params.packageRoot, {
12001265env: params.env,
12011266});
12021267const packageSearchRoots = [packageInstallRoot];
1203-const missing = deps.filter(
1204-(dep) =>
1205-!hasDependencySentinel(packageSearchRoots, dep) &&
1206-dep.pluginIds.every((pluginId) => {
1207-const pluginRoot = path.join(extensionsDir, pluginId);
1208-const installRoot = resolveBundledRuntimeDependencyInstallRoot(pluginRoot, {
1209-env: params.env,
1210-});
1211-return !hasDependencySentinel([installRoot], dep);
1212-}),
1213-);
1214-return { deps, missing, conflicts };
1268+const missing = allDeps.filter((dep) => {
1269+if (hasDependencySentinel(packageSearchRoots, dep)) {
1270+return false;
1271+}
1272+if (dep.pluginIds.includes(MIRRORED_PACKAGE_RUNTIME_DEP_PLUGIN_ID)) {
1273+return true;
1274+}
1275+return dep.pluginIds.every((pluginId) => {
1276+const pluginRoot = path.join(extensionsDir, pluginId);
1277+const installRoot = resolveBundledRuntimeDependencyInstallRoot(pluginRoot, {
1278+env: params.env,
1279+});
1280+return !hasDependencySentinel([installRoot], dep);
1281+});
1282+});
1283+return { deps: allDeps, missing, conflicts };
12151284}
1216128512171286export function resolveBundledRuntimeDependencyPackageInstallRoot(
@@ -1654,16 +1723,22 @@ export function ensureBundledPluginRuntimeDeps(params: {
16541723if (!packageJson) {
16551724return { installedSpecs: [], retainSpecs: [] };
16561725}
1657-const deps = Object.entries(collectRuntimeDeps(packageJson))
1726+const pluginDeps = Object.entries(collectRuntimeDeps(packageJson))
16581727.map(([name, rawVersion]) => parseInstallableRuntimeDep(name, rawVersion))
16591728.filter((entry): entry is { name: string; version: string } => Boolean(entry));
1660-if (deps.length === 0) {
1661-return { installedSpecs: [], retainSpecs: [] };
1662-}
1663172916641730const installRoot = resolveBundledRuntimeDependencyInstallRoot(params.pluginRoot, {
16651731env: params.env,
16661732});
1733+const packageRoot = resolveBundledRuntimeDependencyPackageRoot(params.pluginRoot);
1734+const packageRuntimeDeps =
1735+packageRoot && path.resolve(installRoot) !== path.resolve(params.pluginRoot)
1736+ ? collectMirroredPackageRuntimeDeps(packageRoot)
1737+ : [];
1738+const deps = mergeInstallableRuntimeDeps([...pluginDeps, ...packageRuntimeDeps]);
1739+if (deps.length === 0) {
1740+return { installedSpecs: [], retainSpecs: [] };
1741+}
16671742return withBundledRuntimeDepsInstallRootLock(installRoot, () => {
16681743const persistRetainedManifest = shouldPersistRetainedRuntimeDepsManifest({
16691744pluginRoot: params.pluginRoot,
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。