mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 05:50:43 +00:00
fix(plugins): restore cached memory capability on cache hits (#65240)
Merged via squash.
Prepared head SHA: 4209f056a1
Co-authored-by: sercada <24389792+sercada@users.noreply.github.com>
Co-authored-by: vincentkoc <25068+vincentkoc@users.noreply.github.com>
Reviewed-by: @vincentkoc
This commit is contained in:
@@ -15,6 +15,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Agents/Anthropic replay: preserve immutable signed-thinking replay safety across stored and live reruns, keep non-thinking embedded `tool_result` user blocks intact, and drop conflicting preserved tool IDs before validation so retries stop degrading into omitted tool calls. (#65126) Thanks @shakkernerd.
|
||||
- Telegram/direct sessions: keep commentary-only assistant fallback payloads out of visible direct delivery, so Codex planning chatter cannot leak into Telegram DMs when a run has no `final_answer` text. (#65112) Thanks @vincentkoc.
|
||||
- Infra/net: fix multipart FormData fields (including `model`) being silently dropped when a guarded runtime fetch body crosses a FormData implementation boundary, restoring OpenAI audio transcription requests that failed with HTTP 400. (#64349) Thanks @petr-sloup.
|
||||
- Plugins/memory: restore cached memory capability public artifacts on plugin-registry cache hits so memory-backed artifact surfaces stay visible after warm loads. Thanks @sercada and @vincentkoc.
|
||||
|
||||
## 2026.4.11
|
||||
|
||||
|
||||
@@ -39,7 +39,9 @@ import {
|
||||
} from "./memory-embedding-providers.js";
|
||||
import {
|
||||
buildMemoryPromptSection,
|
||||
clearMemoryPluginState,
|
||||
getMemoryRuntime,
|
||||
listActiveMemoryPublicArtifacts,
|
||||
listMemoryCorpusSupplements,
|
||||
registerMemoryCorpusSupplement,
|
||||
registerMemoryFlushPlanResolver,
|
||||
@@ -1809,6 +1811,73 @@ module.exports = { id: "throws-after-import", register() {} };`,
|
||||
expect(listMemoryEmbeddingProviders()).toEqual([]);
|
||||
});
|
||||
|
||||
it("restores cached memory capability public artifacts on cache hits", async () => {
|
||||
useNoBundledPlugins();
|
||||
const workspaceDir = makeTempDir();
|
||||
const absolutePath = path.join(workspaceDir, "MEMORY.md");
|
||||
fs.writeFileSync(absolutePath, "# Memory\n");
|
||||
const plugin = writePlugin({
|
||||
id: "cached-memory-capability",
|
||||
filename: "cached-memory-capability.cjs",
|
||||
body: `module.exports = {
|
||||
id: "cached-memory-capability",
|
||||
kind: "memory",
|
||||
register(api) {
|
||||
api.registerMemoryCapability({
|
||||
publicArtifacts: {
|
||||
async listArtifacts() {
|
||||
return [{
|
||||
kind: "memory-root",
|
||||
workspaceDir: ${JSON.stringify(workspaceDir)},
|
||||
relativePath: "MEMORY.md",
|
||||
absolutePath: ${JSON.stringify(absolutePath)},
|
||||
agentIds: ["main"],
|
||||
contentType: "markdown",
|
||||
}];
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
};`,
|
||||
});
|
||||
|
||||
const options = {
|
||||
workspaceDir: plugin.dir,
|
||||
config: {
|
||||
plugins: {
|
||||
load: { paths: [plugin.file] },
|
||||
allow: ["cached-memory-capability"],
|
||||
slots: { memory: "cached-memory-capability" },
|
||||
},
|
||||
},
|
||||
onlyPluginIds: ["cached-memory-capability"],
|
||||
};
|
||||
|
||||
const expectedArtifacts = [
|
||||
{
|
||||
kind: "memory-root",
|
||||
workspaceDir,
|
||||
relativePath: "MEMORY.md",
|
||||
absolutePath,
|
||||
agentIds: ["main"],
|
||||
contentType: "markdown" as const,
|
||||
},
|
||||
];
|
||||
|
||||
const first = loadOpenClawPlugins(options);
|
||||
await expect(listActiveMemoryPublicArtifacts({ cfg: {} as never })).resolves.toEqual(
|
||||
expectedArtifacts,
|
||||
);
|
||||
|
||||
clearMemoryPluginState();
|
||||
|
||||
const second = loadOpenClawPlugins(options);
|
||||
expect(second).toBe(first);
|
||||
await expect(listActiveMemoryPublicArtifacts({ cfg: {} as never })).resolves.toEqual(
|
||||
expectedArtifacts,
|
||||
);
|
||||
});
|
||||
|
||||
it("throws when activate:false is used without cache:false", () => {
|
||||
expect(() => loadOpenClawPlugins({ activate: false })).toThrow(
|
||||
"activate:false requires cache:false",
|
||||
|
||||
@@ -48,6 +48,7 @@ import {
|
||||
} from "./memory-embedding-providers.js";
|
||||
import {
|
||||
clearMemoryPluginState,
|
||||
getMemoryCapabilityRegistration,
|
||||
getMemoryFlushPlanResolver,
|
||||
getMemoryPromptSectionBuilder,
|
||||
getMemoryRuntime,
|
||||
@@ -148,6 +149,7 @@ export class PluginLoadReentryError extends Error {
|
||||
|
||||
type CachedPluginState = {
|
||||
registry: PluginRegistry;
|
||||
memoryCapability: ReturnType<typeof getMemoryCapabilityRegistration>;
|
||||
memoryCorpusSupplements: ReturnType<typeof listMemoryCorpusSupplements>;
|
||||
agentHarnesses: ReturnType<typeof listRegisteredAgentHarnesses>;
|
||||
compactionProviders: ReturnType<typeof listRegisteredCompactionProviders>;
|
||||
@@ -1104,6 +1106,7 @@ export function loadOpenClawPlugins(options: PluginLoadOptions = {}): PluginRegi
|
||||
restoreRegisteredCompactionProviders(cached.compactionProviders);
|
||||
restoreRegisteredMemoryEmbeddingProviders(cached.memoryEmbeddingProviders);
|
||||
restoreMemoryPluginState({
|
||||
capability: cached.memoryCapability,
|
||||
corpusSupplements: cached.memoryCorpusSupplements,
|
||||
promptBuilder: cached.memoryPromptBuilder,
|
||||
promptSupplements: cached.memoryPromptSupplements,
|
||||
@@ -1799,6 +1802,7 @@ export function loadOpenClawPlugins(options: PluginLoadOptions = {}): PluginRegi
|
||||
|
||||
if (cacheEnabled) {
|
||||
setCachedPluginRegistry(cacheKey, {
|
||||
memoryCapability: getMemoryCapabilityRegistration(),
|
||||
memoryCorpusSupplements: listMemoryCorpusSupplements(),
|
||||
registry,
|
||||
agentHarnesses: listRegisteredAgentHarnesses(),
|
||||
|
||||
Reference in New Issue
Block a user