From c545e4605e75908456223b981f7857007c1f7d4f Mon Sep 17 00:00:00 2001 From: Leonard Sellem Date: Sun, 12 Apr 2026 18:30:54 +0200 Subject: [PATCH] fix(memory-wiki): pass app config into CLI metadata registrar (#65012) * fix(memory-wiki): pass config into cli metadata registrar * fix(memory-wiki): use cli context config for metadata registrar * docs(changelog): note memory-wiki cli metadata fix --------- Co-authored-by: Vincent Koc --- CHANGELOG.md | 1 + extensions/memory-wiki/cli-metadata.test.ts | 74 +++++++++++++++++++++ extensions/memory-wiki/cli-metadata.ts | 10 ++- 3 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 extensions/memory-wiki/cli-metadata.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b3cae8e1b7..b45e70032dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ Docs: https://docs.openclaw.ai - Gateway/cron: preserve requested isolated-agent config across runtime reloads so subagent jobs and heartbeat overrides keep the right workspace and heartbeat settings when the hot-loaded snapshot is stale. Thanks @l0cka and @vincentkoc. - Gateway/plugins: always send a non-empty `idempotencyKey` for plugin subagent runs, so dreaming narrative jobs stop failing gateway schema validation. (#65354) Thanks @CodeForgeNet and @vincentkoc. - Cron/isolated sessions: persist the right transcript path for each isolated run, including fresh session rollovers, so cron runs stop appending to stale session files. Thanks @samrusani and @vincentkoc. +- CLI/memory-wiki: pass the active app config into the metadata registrar so built `openclaw wiki` commands resolve the live wiki plugin config instead of silently falling back to defaults. (#65012) Thanks @leonardsellem and @vincentkoc. - Dreaming/cron: wake managed dreaming jobs immediately instead of waiting for the next heartbeat, so scheduled dreaming runs start when the cron fires. (#65053) Thanks @l0cka and @vincentkoc. - QA/packaging: stop packaged QA helpers from crashing when optional scenario execution config is unavailable, so npm distributions can skip the repo-only scenario pack without breaking completion-cache and startup paths. (#65118) Thanks @EdderTalmor and @vincentkoc. - Media/audio transcription: surface the real provider failure when every audio transcription attempt fails, so status output and the CLI stop collapsing those errors into generic skips. (#65096) Thanks @l0cka and @vincentkoc. diff --git a/extensions/memory-wiki/cli-metadata.test.ts b/extensions/memory-wiki/cli-metadata.test.ts new file mode 100644 index 00000000000..73956d62f35 --- /dev/null +++ b/extensions/memory-wiki/cli-metadata.test.ts @@ -0,0 +1,74 @@ +import { Command } from "commander"; +import { beforeEach, describe, expect, it, vi } from "vitest"; +import { createTestPluginApi } from "../../test/helpers/plugins/plugin-api.js"; + +const mocks = vi.hoisted(() => ({ + loadConfig: vi.fn(() => { + throw new Error("loadConfig should not be called during CLI metadata registration"); + }), + registerWikiCli: vi.fn(), + resolveMemoryWikiConfig: vi.fn(), +})); + +vi.mock("../../src/config/config.js", () => ({ + loadConfig: mocks.loadConfig, +})); + +vi.mock("./src/cli.js", () => ({ + registerWikiCli: mocks.registerWikiCli, +})); + +vi.mock("./src/config.js", () => ({ + resolveMemoryWikiConfig: mocks.resolveMemoryWikiConfig, +})); + +import plugin from "./cli-metadata.js"; + +describe("memory-wiki cli metadata entry", () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + it("uses the registrar context config instead of reloading global config", async () => { + const registerCli = vi.fn(); + const api = createTestPluginApi({ + id: "memory-wiki", + name: "Memory Wiki", + registerCli, + }); + const program = new Command(); + const appConfig = { + plugins: { + entries: { + "memory-wiki": { + config: { + vaultMode: "bridge", + }, + }, + }, + }, + }; + const resolvedConfig = { vaultMode: "bridge", vault: { path: "/vault" } }; + mocks.resolveMemoryWikiConfig.mockReturnValue(resolvedConfig); + + plugin.register(api); + + const register = registerCli.mock.calls[0]?.[0]; + + expect(registerCli).toHaveBeenCalledTimes(1); + expect(typeof register).toBe("function"); + + await register({ + program, + config: appConfig, + workspaceDir: "/tmp/openclaw", + logger: api.logger, + }); + + expect(mocks.loadConfig).not.toHaveBeenCalled(); + expect(mocks.resolveMemoryWikiConfig).toHaveBeenCalledWith( + appConfig.plugins.entries["memory-wiki"].config, + ); + expect(mocks.registerWikiCli).toHaveBeenCalledWith(program, resolvedConfig, appConfig); + }); +}); diff --git a/extensions/memory-wiki/cli-metadata.ts b/extensions/memory-wiki/cli-metadata.ts index ac3f09ae7b9..27ac67e2f33 100644 --- a/extensions/memory-wiki/cli-metadata.ts +++ b/extensions/memory-wiki/cli-metadata.ts @@ -6,9 +6,13 @@ export default definePluginEntry({ description: "Persistent wiki compiler and Obsidian-friendly knowledge vault for OpenClaw.", register(api) { api.registerCli( - async ({ program }) => { - const { registerWikiCli } = await import("./src/cli.js"); - registerWikiCli(program); + async ({ program, config: appConfig }) => { + const [{ registerWikiCli }, { resolveMemoryWikiConfig }] = await Promise.all([ + import("./src/cli.js"), + import("./src/config.js"), + ]); + const pluginConfig = appConfig.plugins?.entries?.["memory-wiki"]?.config; + registerWikiCli(program, resolveMemoryWikiConfig(pluginConfig), appConfig); }, { descriptors: [