mirror of
https://github.com/farcasclaudiu/openclaw.git
synced 2026-06-29 03:01:50 +03:00
Gateway: eager-init QMD backend on startup
This commit is contained in:
committed by
Vignesh
parent
ef4a0e92b7
commit
efc79f69a2
@@ -60,6 +60,7 @@ Docs: https://docs.openclaw.ai
|
|||||||
- Memory: disable async batch embeddings by default for memory indexing (opt-in via `agents.defaults.memorySearch.remote.batch.enabled`). (#13069) Thanks @mcinteerj.
|
- Memory: disable async batch embeddings by default for memory indexing (opt-in via `agents.defaults.memorySearch.remote.batch.enabled`). (#13069) Thanks @mcinteerj.
|
||||||
- Memory/QMD: reuse default model cache across agents instead of re-downloading per agent. (#12114) Thanks @tyler6204.
|
- Memory/QMD: reuse default model cache across agents instead of re-downloading per agent. (#12114) Thanks @tyler6204.
|
||||||
- Memory/QMD: run boot refresh in background by default, add configurable QMD maintenance timeouts, retry QMD after fallback failures, and scope QMD queries to OpenClaw-managed collections. (#9690, #9705, #10042) Thanks @vignesh07.
|
- Memory/QMD: run boot refresh in background by default, add configurable QMD maintenance timeouts, retry QMD after fallback failures, and scope QMD queries to OpenClaw-managed collections. (#9690, #9705, #10042) Thanks @vignesh07.
|
||||||
|
- Memory/QMD: initialize QMD backend on gateway startup so background update timers restart after process reloads. (#10797) Thanks @vignesh07.
|
||||||
- Media understanding: recognize `.caf` audio attachments for transcription. (#10982) Thanks @succ985.
|
- Media understanding: recognize `.caf` audio attachments for transcription. (#10982) Thanks @succ985.
|
||||||
- State dir: honor `OPENCLAW_STATE_DIR` for default device identity and canvas storage paths. (#4824) Thanks @kossoy.
|
- State dir: honor `OPENCLAW_STATE_DIR` for default device identity and canvas storage paths. (#4824) Thanks @kossoy.
|
||||||
|
|
||||||
|
|||||||
@@ -132,6 +132,8 @@ out to QMD for retrieval. Key points:
|
|||||||
(plus default workspace memory files), then `qmd update` + `qmd embed` run
|
(plus default workspace memory files), then `qmd update` + `qmd embed` run
|
||||||
on boot and on a configurable interval (`memory.qmd.update.interval`,
|
on boot and on a configurable interval (`memory.qmd.update.interval`,
|
||||||
default 5 m).
|
default 5 m).
|
||||||
|
- The gateway now initializes the QMD manager on startup, so periodic update
|
||||||
|
timers are armed even before the first `memory_search` call.
|
||||||
- Boot refresh now runs in the background by default so chat startup is not
|
- Boot refresh now runs in the background by default so chat startup is not
|
||||||
blocked; set `memory.qmd.update.waitForBootSync = true` to keep the previous
|
blocked; set `memory.qmd.update.waitForBootSync = true` to keep the previous
|
||||||
blocking behavior.
|
blocking behavior.
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
|
import type { OpenClawConfig } from "../config/config.js";
|
||||||
|
|
||||||
|
const { getMemorySearchManagerMock } = vi.hoisted(() => ({
|
||||||
|
getMemorySearchManagerMock: vi.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock("../memory/index.js", () => ({
|
||||||
|
getMemorySearchManager: getMemorySearchManagerMock,
|
||||||
|
}));
|
||||||
|
|
||||||
|
import { startGatewayMemoryBackend } from "./server-startup-memory.js";
|
||||||
|
|
||||||
|
describe("startGatewayMemoryBackend", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
getMemorySearchManagerMock.mockReset();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("skips initialization when memory backend is not qmd", async () => {
|
||||||
|
const cfg = {
|
||||||
|
agents: { list: [{ id: "main", default: true }] },
|
||||||
|
memory: { backend: "builtin" },
|
||||||
|
} as OpenClawConfig;
|
||||||
|
const log = { info: vi.fn(), warn: vi.fn() };
|
||||||
|
|
||||||
|
await startGatewayMemoryBackend({ cfg, log });
|
||||||
|
|
||||||
|
expect(getMemorySearchManagerMock).not.toHaveBeenCalled();
|
||||||
|
expect(log.info).not.toHaveBeenCalled();
|
||||||
|
expect(log.warn).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("initializes qmd backend for the default agent", async () => {
|
||||||
|
const cfg = {
|
||||||
|
agents: { list: [{ id: "ops", default: true }, { id: "main" }] },
|
||||||
|
memory: { backend: "qmd", qmd: {} },
|
||||||
|
} as OpenClawConfig;
|
||||||
|
const log = { info: vi.fn(), warn: vi.fn() };
|
||||||
|
getMemorySearchManagerMock.mockResolvedValue({ manager: { search: vi.fn() } });
|
||||||
|
|
||||||
|
await startGatewayMemoryBackend({ cfg, log });
|
||||||
|
|
||||||
|
expect(getMemorySearchManagerMock).toHaveBeenCalledWith({ cfg, agentId: "ops" });
|
||||||
|
expect(log.info).toHaveBeenCalledWith(
|
||||||
|
'qmd memory startup initialization armed for agent "ops"',
|
||||||
|
);
|
||||||
|
expect(log.warn).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("logs a warning when qmd manager init fails", async () => {
|
||||||
|
const cfg = {
|
||||||
|
agents: { list: [{ id: "main", default: true }] },
|
||||||
|
memory: { backend: "qmd", qmd: {} },
|
||||||
|
} as OpenClawConfig;
|
||||||
|
const log = { info: vi.fn(), warn: vi.fn() };
|
||||||
|
getMemorySearchManagerMock.mockResolvedValue({ manager: null, error: "qmd missing" });
|
||||||
|
|
||||||
|
await startGatewayMemoryBackend({ cfg, log });
|
||||||
|
|
||||||
|
expect(log.warn).toHaveBeenCalledWith(
|
||||||
|
'qmd memory startup initialization failed for agent "main": qmd missing',
|
||||||
|
);
|
||||||
|
expect(log.info).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import type { OpenClawConfig } from "../config/config.js";
|
||||||
|
import { resolveDefaultAgentId } from "../agents/agent-scope.js";
|
||||||
|
import { resolveMemoryBackendConfig } from "../memory/backend-config.js";
|
||||||
|
import { getMemorySearchManager } from "../memory/index.js";
|
||||||
|
|
||||||
|
export async function startGatewayMemoryBackend(params: {
|
||||||
|
cfg: OpenClawConfig;
|
||||||
|
log: { info?: (msg: string) => void; warn: (msg: string) => void };
|
||||||
|
}): Promise<void> {
|
||||||
|
const agentId = resolveDefaultAgentId(params.cfg);
|
||||||
|
const resolved = resolveMemoryBackendConfig({ cfg: params.cfg, agentId });
|
||||||
|
if (resolved.backend !== "qmd" || !resolved.qmd) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { manager, error } = await getMemorySearchManager({ cfg: params.cfg, agentId });
|
||||||
|
if (!manager) {
|
||||||
|
params.log.warn(
|
||||||
|
`qmd memory startup initialization failed for agent "${agentId}": ${error ?? "unknown error"}`,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
params.log.info?.(`qmd memory startup initialization armed for agent "${agentId}"`);
|
||||||
|
}
|
||||||
@@ -22,6 +22,7 @@ import {
|
|||||||
scheduleRestartSentinelWake,
|
scheduleRestartSentinelWake,
|
||||||
shouldWakeFromRestartSentinel,
|
shouldWakeFromRestartSentinel,
|
||||||
} from "./server-restart-sentinel.js";
|
} from "./server-restart-sentinel.js";
|
||||||
|
import { startGatewayMemoryBackend } from "./server-startup-memory.js";
|
||||||
|
|
||||||
export async function startGatewaySidecars(params: {
|
export async function startGatewaySidecars(params: {
|
||||||
cfg: ReturnType<typeof loadConfig>;
|
cfg: ReturnType<typeof loadConfig>;
|
||||||
@@ -150,6 +151,10 @@ export async function startGatewaySidecars(params: {
|
|||||||
params.log.warn(`plugin services failed to start: ${String(err)}`);
|
params.log.warn(`plugin services failed to start: ${String(err)}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void startGatewayMemoryBackend({ cfg: params.cfg, log: params.log }).catch((err) => {
|
||||||
|
params.log.warn(`qmd memory startup initialization failed: ${String(err)}`);
|
||||||
|
});
|
||||||
|
|
||||||
if (shouldWakeFromRestartSentinel()) {
|
if (shouldWakeFromRestartSentinel()) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
void scheduleRestartSentinelWake({ deps: params.deps });
|
void scheduleRestartSentinelWake({ deps: params.deps });
|
||||||
|
|||||||
Reference in New Issue
Block a user