mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 16:20:43 +00:00
fix(plugins): exempt dreaming engine from memory slot fast-path in loader (#65411)
* fix(plugins): exempt dreaming engine from memory slot fast-path in loader * fix(plugins): handle dreaming engine as slot + add tests for slot coexistence * fix(plugins): narrow dreaming sidecar loading * Update CHANGELOG.md * Update CHANGELOG.md --------- Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
This commit is contained in:
@@ -14,7 +14,15 @@ import type { PluginInstallRecord } from "../config/types.plugins.js";
|
||||
import type { GatewayRequestHandler } from "../gateway/server-methods/types.js";
|
||||
import { openBoundaryFileSync } from "../infra/boundary-file-read.js";
|
||||
import { createSubsystemLogger } from "../logging/subsystem.js";
|
||||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
import {
|
||||
DEFAULT_MEMORY_DREAMING_PLUGIN_ID,
|
||||
resolveMemoryDreamingConfig,
|
||||
resolveMemoryDreamingPluginConfig,
|
||||
} from "../memory-host-sdk/dreaming.js";
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalString,
|
||||
} from "../shared/string-coerce.js";
|
||||
import { resolveUserPath } from "../utils.js";
|
||||
import { buildPluginApi } from "./api-builder.js";
|
||||
import { inspectBundleMcpRuntimeSupport } from "./bundle-mcp.js";
|
||||
@@ -127,6 +135,25 @@ const CLI_METADATA_ENTRY_BASENAMES = [
|
||||
"cli-metadata.cjs",
|
||||
] as const;
|
||||
|
||||
function resolveDreamingSidecarEngineId(params: {
|
||||
cfg: OpenClawConfig;
|
||||
memorySlot: string | null | undefined;
|
||||
}): string | null {
|
||||
const normalizedMemorySlot = normalizeLowercaseStringOrEmpty(params.memorySlot);
|
||||
if (
|
||||
!normalizedMemorySlot ||
|
||||
normalizedMemorySlot === "none" ||
|
||||
normalizedMemorySlot === DEFAULT_MEMORY_DREAMING_PLUGIN_ID
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
const dreamingConfig = resolveMemoryDreamingConfig({
|
||||
pluginConfig: resolveMemoryDreamingPluginConfig(params.cfg),
|
||||
cfg: params.cfg,
|
||||
});
|
||||
return dreamingConfig.enabled ? DEFAULT_MEMORY_DREAMING_PLUGIN_ID : null;
|
||||
}
|
||||
|
||||
export class PluginLoadFailureError extends Error {
|
||||
readonly pluginIds: string[];
|
||||
readonly registry: PluginRegistry;
|
||||
@@ -1286,6 +1313,7 @@ export function loadOpenClawPlugins(options: PluginLoadOptions = {}): PluginRegi
|
||||
const memorySlot = normalized.slots.memory;
|
||||
let selectedMemoryPluginId: string | null = null;
|
||||
let memorySlotMatched = false;
|
||||
const dreamingEngineId = resolveDreamingSidecarEngineId({ cfg, memorySlot });
|
||||
|
||||
for (const candidate of orderedCandidates) {
|
||||
const manifestRecord = manifestByRoot.get(candidate.rootDir);
|
||||
@@ -1477,25 +1505,29 @@ export function loadOpenClawPlugins(options: PluginLoadOptions = {}): PluginRegi
|
||||
}
|
||||
// Fast-path bundled memory plugins that are guaranteed disabled by slot policy.
|
||||
// This avoids opening/importing heavy memory plugin modules that will never register.
|
||||
// Exception: the dreaming engine (memory-core by default) must load alongside the
|
||||
// selected memory slot plugin so dreaming can run even when lancedb holds the slot.
|
||||
if (
|
||||
registrationMode === "full" &&
|
||||
candidate.origin === "bundled" &&
|
||||
hasKind(manifestRecord.kind, "memory")
|
||||
) {
|
||||
const earlyMemoryDecision = resolveMemorySlotDecision({
|
||||
id: record.id,
|
||||
kind: manifestRecord.kind,
|
||||
slot: memorySlot,
|
||||
selectedId: selectedMemoryPluginId,
|
||||
});
|
||||
if (!earlyMemoryDecision.enabled) {
|
||||
record.enabled = false;
|
||||
record.status = "disabled";
|
||||
record.error = earlyMemoryDecision.reason;
|
||||
markPluginActivationDisabled(record, earlyMemoryDecision.reason);
|
||||
registry.plugins.push(record);
|
||||
seenIds.set(pluginId, candidate.origin);
|
||||
continue;
|
||||
if (pluginId !== dreamingEngineId) {
|
||||
const earlyMemoryDecision = resolveMemorySlotDecision({
|
||||
id: record.id,
|
||||
kind: manifestRecord.kind,
|
||||
slot: memorySlot,
|
||||
selectedId: selectedMemoryPluginId,
|
||||
});
|
||||
if (!earlyMemoryDecision.enabled) {
|
||||
record.enabled = false;
|
||||
record.status = "disabled";
|
||||
record.error = earlyMemoryDecision.reason;
|
||||
markPluginActivationDisabled(record, earlyMemoryDecision.reason);
|
||||
registry.plugins.push(record);
|
||||
seenIds.set(pluginId, candidate.origin);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1512,7 +1544,7 @@ export function loadOpenClawPlugins(options: PluginLoadOptions = {}): PluginRegi
|
||||
selectedId: selectedMemoryPluginId,
|
||||
});
|
||||
|
||||
if (!memoryDecision.enabled) {
|
||||
if (!memoryDecision.enabled && pluginId !== dreamingEngineId) {
|
||||
record.enabled = false;
|
||||
record.status = "disabled";
|
||||
record.error = memoryDecision.reason;
|
||||
@@ -1653,26 +1685,28 @@ export function loadOpenClawPlugins(options: PluginLoadOptions = {}): PluginRegi
|
||||
}
|
||||
|
||||
if (registrationMode === "full") {
|
||||
const memoryDecision = resolveMemorySlotDecision({
|
||||
id: record.id,
|
||||
kind: record.kind,
|
||||
slot: memorySlot,
|
||||
selectedId: selectedMemoryPluginId,
|
||||
});
|
||||
if (pluginId !== dreamingEngineId) {
|
||||
const memoryDecision = resolveMemorySlotDecision({
|
||||
id: record.id,
|
||||
kind: record.kind,
|
||||
slot: memorySlot,
|
||||
selectedId: selectedMemoryPluginId,
|
||||
});
|
||||
|
||||
if (!memoryDecision.enabled) {
|
||||
record.enabled = false;
|
||||
record.status = "disabled";
|
||||
record.error = memoryDecision.reason;
|
||||
markPluginActivationDisabled(record, memoryDecision.reason);
|
||||
registry.plugins.push(record);
|
||||
seenIds.set(pluginId, candidate.origin);
|
||||
continue;
|
||||
}
|
||||
if (!memoryDecision.enabled) {
|
||||
record.enabled = false;
|
||||
record.status = "disabled";
|
||||
record.error = memoryDecision.reason;
|
||||
markPluginActivationDisabled(record, memoryDecision.reason);
|
||||
registry.plugins.push(record);
|
||||
seenIds.set(pluginId, candidate.origin);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (memoryDecision.selected && hasKind(record.kind, "memory")) {
|
||||
selectedMemoryPluginId = record.id;
|
||||
record.memorySlotSelected = true;
|
||||
if (memoryDecision.selected && hasKind(record.kind, "memory")) {
|
||||
selectedMemoryPluginId = record.id;
|
||||
record.memorySlotSelected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1889,6 +1923,7 @@ export async function loadOpenClawPluginCliRegistry(
|
||||
const seenIds = new Map<string, PluginRecord["origin"]>();
|
||||
const memorySlot = normalized.slots.memory;
|
||||
let selectedMemoryPluginId: string | null = null;
|
||||
const dreamingEngineId = resolveDreamingSidecarEngineId({ cfg, memorySlot });
|
||||
|
||||
for (const candidate of orderedCandidates) {
|
||||
const manifestRecord = manifestByRoot.get(candidate.rootDir);
|
||||
@@ -2089,24 +2124,26 @@ export async function loadOpenClawPluginCliRegistry(
|
||||
}
|
||||
record.kind = definition?.kind ?? record.kind;
|
||||
|
||||
const memoryDecision = resolveMemorySlotDecision({
|
||||
id: record.id,
|
||||
kind: record.kind,
|
||||
slot: memorySlot,
|
||||
selectedId: selectedMemoryPluginId,
|
||||
});
|
||||
if (!memoryDecision.enabled) {
|
||||
record.enabled = false;
|
||||
record.status = "disabled";
|
||||
record.error = memoryDecision.reason;
|
||||
markPluginActivationDisabled(record, memoryDecision.reason);
|
||||
registry.plugins.push(record);
|
||||
seenIds.set(pluginId, candidate.origin);
|
||||
continue;
|
||||
}
|
||||
if (memoryDecision.selected && hasKind(record.kind, "memory")) {
|
||||
selectedMemoryPluginId = record.id;
|
||||
record.memorySlotSelected = true;
|
||||
if (pluginId !== dreamingEngineId) {
|
||||
const memoryDecision = resolveMemorySlotDecision({
|
||||
id: record.id,
|
||||
kind: record.kind,
|
||||
slot: memorySlot,
|
||||
selectedId: selectedMemoryPluginId,
|
||||
});
|
||||
if (!memoryDecision.enabled) {
|
||||
record.enabled = false;
|
||||
record.status = "disabled";
|
||||
record.error = memoryDecision.reason;
|
||||
markPluginActivationDisabled(record, memoryDecision.reason);
|
||||
registry.plugins.push(record);
|
||||
seenIds.set(pluginId, candidate.origin);
|
||||
continue;
|
||||
}
|
||||
if (memoryDecision.selected && hasKind(record.kind, "memory")) {
|
||||
selectedMemoryPluginId = record.id;
|
||||
record.memorySlotSelected = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof register !== "function") {
|
||||
|
||||
Reference in New Issue
Block a user