fix(doctor): suppress memory plugin false alarm

Fixes #76792.

- Trust a checked-ready gateway memory probe when CLI-local memory runtime resolution is unavailable.
- Keep the no-active-plugin warning for skipped, unavailable, or not-ready gateway probes.
- Add regression coverage for ready, skipped, and not-ready probe cases.

Thanks @som-686.
This commit is contained in:
clawsweeper[bot]
2026-05-03 17:54:39 +01:00
committed by GitHub
parent c5b559d4ee
commit 1bc97aee4e
3 changed files with 61 additions and 0 deletions

View File

@@ -29,6 +29,7 @@ Docs: https://docs.openclaw.ai
- Google Meet: route stateful CLI session commands through the gateway-owned runtime so joined realtime sessions survive after the starting CLI process exits. Fixes #76344. Thanks @coltonharris-wq.
- Memory/status: split builtin sqlite-vec store readiness from embedding-provider readiness in `memory status --deep` and `openclaw status`, so local vector-store failures no longer look like provider failures and provider failures no longer hide a healthy local vector store.
- CLI/doctor: trust a ready gateway memory probe when CLI-side active memory backend resolution is unavailable, preventing false "No active memory plugin is registered" warnings for healthy runtime setups. Fixes #76792. Thanks @som-686.
- Memory/status: keep plain `openclaw memory status` and `openclaw memory status --json` on the cheap read-only path by reserving vector and embedding provider probes for `--deep` or `--index`. Fixes #76769. Thanks @daruire.
- Telegram: suppress stale same-session replies when a newer accepted message arrives before an older in-flight Telegram dispatch finalizes. Fixes #76642. Thanks @chinar-amrutkar.
- Control UI/Sessions: avoid full `sessions.list` reloads for chat-turn `sessions.changed` payloads, so large session stores no longer add multi-second delays while chat responses are being delivered. (#76676) Thanks @VACInc.

View File

@@ -276,6 +276,63 @@ describe("noteMemorySearchHealth", () => {
);
});
it("does not warn when CLI backend resolution is missing but gateway memory probe is ready", async () => {
resolveActiveMemoryBackendConfig.mockReturnValue(null);
resolveMemorySearchConfig.mockReturnValue({
provider: "auto",
local: {},
remote: {},
});
await noteMemorySearchHealth(cfg, {
gatewayMemoryProbe: { checked: true, ready: true },
});
expect(resolveApiKeyForProvider).not.toHaveBeenCalled();
expect(checkQmdBinaryAvailability).not.toHaveBeenCalled();
expect(note).not.toHaveBeenCalled();
});
it("warns when CLI backend resolution is missing and gateway memory probe was skipped", async () => {
resolveActiveMemoryBackendConfig.mockReturnValue(null);
resolveMemorySearchConfig.mockReturnValue({
provider: "auto",
local: {},
remote: {},
});
await noteMemorySearchHealth(cfg, {
gatewayMemoryProbe: { checked: false, ready: false, skipped: true },
});
expect(resolveApiKeyForProvider).not.toHaveBeenCalled();
expect(checkQmdBinaryAvailability).not.toHaveBeenCalled();
expect(note).toHaveBeenCalledTimes(1);
expect(String(note.mock.calls[0]?.[0] ?? "")).toContain(
"No active memory plugin is registered",
);
});
it("warns when CLI backend resolution is missing and gateway memory probe is not ready", async () => {
resolveActiveMemoryBackendConfig.mockReturnValue(null);
resolveMemorySearchConfig.mockReturnValue({
provider: "auto",
local: {},
remote: {},
});
await noteMemorySearchHealth(cfg, {
gatewayMemoryProbe: { checked: true, ready: false, error: "memory search unavailable" },
});
expect(resolveApiKeyForProvider).not.toHaveBeenCalled();
expect(checkQmdBinaryAvailability).not.toHaveBeenCalled();
expect(note).toHaveBeenCalledTimes(1);
expect(String(note.mock.calls[0]?.[0] ?? "")).toContain(
"No active memory plugin is registered",
);
});
it("does not warn when QMD backend is active", async () => {
const qmdCfg = { memory: { backend: "qmd", qmd: { command: "qmd" } } } as OpenClawConfig;
resolveMemorySearchConfig.mockReturnValue({

View File

@@ -336,6 +336,9 @@ export async function noteMemorySearchHealth(
// separate embedding provider is needed. Skip the provider check entirely.
const backendConfig = resolveActiveMemoryBackendConfig({ cfg, agentId });
if (!backendConfig) {
if (opts?.gatewayMemoryProbe?.checked && opts.gatewayMemoryProbe.ready) {
return;
}
note("No active memory plugin is registered for the current config.", "Memory search");
return;
}