mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 13:00:44 +00:00
fix: guard memory doctor on active runtime
This commit is contained in:
@@ -12,6 +12,7 @@ const resolveMemorySearchConfig = vi.hoisted(() => vi.fn());
|
||||
const resolveApiKeyForProvider = vi.hoisted(() => vi.fn());
|
||||
const hasAnyAuthProfileStoreSource = vi.hoisted(() => vi.fn(() => true));
|
||||
const getActiveMemorySearchManager = vi.hoisted(() => vi.fn());
|
||||
const resolveActiveMemoryBackendConfig = vi.hoisted(() => vi.fn());
|
||||
type CheckQmdBinaryAvailability = typeof checkQmdBinaryAvailabilityFn;
|
||||
const checkQmdBinaryAvailability = vi.hoisted(() =>
|
||||
vi.fn<CheckQmdBinaryAvailability>(async () => ({ available: true })),
|
||||
@@ -47,6 +48,7 @@ vi.mock("../agents/auth-profiles.js", () => ({
|
||||
|
||||
vi.mock("../plugins/memory-runtime.js", () => ({
|
||||
getActiveMemorySearchManager,
|
||||
resolveActiveMemoryBackendConfig,
|
||||
}));
|
||||
|
||||
vi.mock("../memory-host-sdk/engine-qmd.js", () => ({
|
||||
@@ -153,6 +155,12 @@ describe("noteMemorySearchHealth", () => {
|
||||
hasAnyAuthProfileStoreSource.mockReset();
|
||||
hasAnyAuthProfileStoreSource.mockReturnValue(true);
|
||||
getActiveMemorySearchManager.mockReset();
|
||||
resolveActiveMemoryBackendConfig.mockReset();
|
||||
resolveActiveMemoryBackendConfig.mockImplementation(({ cfg }: { cfg: OpenClawConfig }) =>
|
||||
cfg.memory?.backend === "qmd"
|
||||
? { backend: "qmd", qmd: cfg.memory.qmd ?? {} }
|
||||
: { backend: "builtin" },
|
||||
);
|
||||
getActiveMemorySearchManager.mockResolvedValue({
|
||||
manager: {
|
||||
status: () => ({ workspaceDir: "/tmp/agent-default/workspace", backend: "builtin" }),
|
||||
@@ -219,6 +227,24 @@ describe("noteMemorySearchHealth", () => {
|
||||
expect(note).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("does not emit provider guidance when no memory runtime is active", async () => {
|
||||
resolveActiveMemoryBackendConfig.mockReturnValue(null);
|
||||
resolveMemorySearchConfig.mockReturnValue({
|
||||
provider: "auto",
|
||||
local: {},
|
||||
remote: {},
|
||||
});
|
||||
|
||||
await noteMemorySearchHealth(cfg, {});
|
||||
|
||||
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({
|
||||
|
||||
@@ -25,7 +25,10 @@ import {
|
||||
type DreamingArtifactsAuditSummary,
|
||||
type ShortTermAuditSummary,
|
||||
} from "../plugin-sdk/memory-core-engine-runtime.js";
|
||||
import { getActiveMemorySearchManager } from "../plugins/memory-runtime.js";
|
||||
import {
|
||||
getActiveMemorySearchManager,
|
||||
resolveActiveMemoryBackendConfig,
|
||||
} from "../plugins/memory-runtime.js";
|
||||
import { getProviderEnvVars } from "../secrets/provider-env-vars.js";
|
||||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
import { note } from "../terminal/note.js";
|
||||
@@ -124,10 +127,6 @@ function resolveSuggestedRemoteMemoryProvider(): string | undefined {
|
||||
)?.providerId;
|
||||
}
|
||||
|
||||
function resolveConfiguredQmdBackendConfig(cfg: OpenClawConfig): OpenClawConfig["memory"] | null {
|
||||
return cfg.memory?.backend === "qmd" ? cfg.memory : null;
|
||||
}
|
||||
|
||||
async function resolveRuntimeMemoryAuditContext(
|
||||
cfg: OpenClawConfig,
|
||||
): Promise<RuntimeMemoryAuditContext | null> {
|
||||
@@ -325,17 +324,21 @@ export async function noteMemorySearchHealth(
|
||||
|
||||
// QMD backend handles embeddings internally (e.g. embeddinggemma) — no
|
||||
// separate embedding provider is needed. Skip the provider check entirely.
|
||||
const qmdBackendConfig = resolveConfiguredQmdBackendConfig(cfg);
|
||||
if (qmdBackendConfig) {
|
||||
const backendConfig = resolveActiveMemoryBackendConfig({ cfg, agentId });
|
||||
if (!backendConfig) {
|
||||
note("No active memory plugin is registered for the current config.", "Memory search");
|
||||
return;
|
||||
}
|
||||
if (backendConfig.backend === "qmd") {
|
||||
const qmdCheck = await checkQmdBinaryAvailability({
|
||||
command: qmdBackendConfig.qmd?.command ?? "qmd",
|
||||
command: backendConfig.qmd?.command ?? "qmd",
|
||||
env: process.env,
|
||||
cwd: resolveAgentWorkspaceDir(cfg, agentId),
|
||||
});
|
||||
if (!qmdCheck.available) {
|
||||
note(
|
||||
[
|
||||
`QMD memory backend is configured, but the qmd binary could not be started (${qmdBackendConfig.qmd?.command ?? "qmd"}).`,
|
||||
`QMD memory backend is configured, but the qmd binary could not be started (${backendConfig.qmd?.command ?? "qmd"}).`,
|
||||
qmdCheck.error ? `Probe error: ${qmdCheck.error}` : null,
|
||||
"",
|
||||
"Fix (pick one):",
|
||||
|
||||
Reference in New Issue
Block a user