


























@@ -2698,6 +2698,80 @@ describe("QmdMemoryManager", () => {
26982698await manager.close();
26992699});
270027002701+it("keeps hyphenated tokens in lexical QMD searches while normalizing semantic searches", async () => {
2702+cfg = {
2703+ ...cfg,
2704+memory: {
2705+backend: "qmd",
2706+qmd: {
2707+includeDefaultMemory: false,
2708+searchMode: "query",
2709+update: { interval: "0s", debounceMs: 60_000, onBoot: false },
2710+paths: [{ path: workspaceDir, pattern: "**/*.md", name: "workspace" }],
2711+mcporter: { enabled: true, serverName: "qmd", startDaemon: false },
2712+},
2713+},
2714+} as OpenClawConfig;
2715+2716+spawnMock.mockImplementation((cmd: string, args: string[]) => {
2717+const child = createMockChild({ autoClose: false });
2718+if (isMcporterCommand(cmd) && args[0] === "call") {
2719+expect(args[1]).toBe("qmd.query");
2720+const callArgs = JSON.parse(args[args.indexOf("--args") + 1]);
2721+expect(callArgs.searches).toEqual([
2722+{ type: "lex", query: "sqlite-vec-qmd backend health 2026-05-04 multi-agent" },
2723+{ type: "vec", query: "sqlite vec qmd backend health 2026 05 04 multi agent" },
2724+{ type: "hyde", query: "sqlite vec qmd backend health 2026 05 04 multi agent" },
2725+]);
2726+emitAndClose(child, "stdout", JSON.stringify({ results: [] }));
2727+return child;
2728+}
2729+emitAndClose(child, "stdout", "[]");
2730+return child;
2731+});
2732+2733+const { manager } = await createManager();
2734+await manager.search("sqlite-vec-qmd backend health 2026-05-04 multi-agent", {
2735+sessionKey: "agent:main:slack:dm:u123",
2736+});
2737+await manager.close();
2738+});
2739+2740+it("normalizes hyphenated tokens for vector-only QMD searches", async () => {
2741+cfg = {
2742+ ...cfg,
2743+memory: {
2744+backend: "qmd",
2745+qmd: {
2746+includeDefaultMemory: false,
2747+searchMode: "vsearch",
2748+update: { interval: "0s", debounceMs: 60_000, onBoot: false },
2749+paths: [{ path: workspaceDir, pattern: "**/*.md", name: "workspace" }],
2750+mcporter: { enabled: true, serverName: "qmd", startDaemon: false },
2751+},
2752+},
2753+} as OpenClawConfig;
2754+2755+spawnMock.mockImplementation((cmd: string, args: string[]) => {
2756+const child = createMockChild({ autoClose: false });
2757+if (isMcporterCommand(cmd) && args[0] === "call") {
2758+expect(args[1]).toBe("qmd.query");
2759+const callArgs = JSON.parse(args[args.indexOf("--args") + 1]);
2760+expect(callArgs.searches).toEqual([{ type: "vec", query: "sqlite vec backend health" }]);
2761+emitAndClose(child, "stdout", JSON.stringify({ results: [] }));
2762+return child;
2763+}
2764+emitAndClose(child, "stdout", "[]");
2765+return child;
2766+});
2767+2768+const { manager } = await createManager();
2769+await manager.search("sqlite-vec backend health", {
2770+sessionKey: "agent:main:slack:dm:u123",
2771+});
2772+await manager.close();
2773+});
2774+27012775it("falls back to QMD <1.1 tool names when query tool is not found", async () => {
27022776// qmdMcpToolVersion is an instance field — each createManager() starts fresh.
27032777此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。