mirror of
https://github.com/openclaw/openclaw.git
synced 2026-02-19 18:39:20 -05:00
fix (memory/qmd): verify qmd index artifact after manual reindex
This commit is contained in:
@@ -1,4 +1,7 @@
|
||||
import { Command } from "commander";
|
||||
import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const getMemorySearchManager = vi.fn();
|
||||
@@ -273,6 +276,70 @@ describe("memory cli", () => {
|
||||
expect(log).toHaveBeenCalledWith("Memory index updated (main).");
|
||||
});
|
||||
|
||||
it("logs qmd index file path and size after index", async () => {
|
||||
const { registerMemoryCli } = await import("./memory-cli.js");
|
||||
const { defaultRuntime } = await import("../runtime.js");
|
||||
const close = vi.fn(async () => {});
|
||||
const sync = vi.fn(async () => {});
|
||||
const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "memory-cli-qmd-index-"));
|
||||
const dbPath = path.join(tmpDir, "index.sqlite");
|
||||
await fs.writeFile(dbPath, "sqlite-bytes", "utf-8");
|
||||
getMemorySearchManager.mockResolvedValueOnce({
|
||||
manager: {
|
||||
sync,
|
||||
status: () => ({ backend: "qmd", dbPath }),
|
||||
close,
|
||||
},
|
||||
});
|
||||
|
||||
const log = vi.spyOn(defaultRuntime, "log").mockImplementation(() => {});
|
||||
const program = new Command();
|
||||
program.name("test");
|
||||
registerMemoryCli(program);
|
||||
await program.parseAsync(["memory", "index"], { from: "user" });
|
||||
|
||||
expect(sync).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ reason: "cli", force: false, progress: expect.any(Function) }),
|
||||
);
|
||||
expect(log).toHaveBeenCalledWith(expect.stringContaining("QMD index: "));
|
||||
expect(log).toHaveBeenCalledWith("Memory index updated (main).");
|
||||
expect(close).toHaveBeenCalled();
|
||||
await fs.rm(tmpDir, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
it("fails index when qmd db file is empty", async () => {
|
||||
const { registerMemoryCli } = await import("./memory-cli.js");
|
||||
const { defaultRuntime } = await import("../runtime.js");
|
||||
const close = vi.fn(async () => {});
|
||||
const sync = vi.fn(async () => {});
|
||||
const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "memory-cli-qmd-index-"));
|
||||
const dbPath = path.join(tmpDir, "index.sqlite");
|
||||
await fs.writeFile(dbPath, "", "utf-8");
|
||||
getMemorySearchManager.mockResolvedValueOnce({
|
||||
manager: {
|
||||
sync,
|
||||
status: () => ({ backend: "qmd", dbPath }),
|
||||
close,
|
||||
},
|
||||
});
|
||||
|
||||
const error = vi.spyOn(defaultRuntime, "error").mockImplementation(() => {});
|
||||
const program = new Command();
|
||||
program.name("test");
|
||||
registerMemoryCli(program);
|
||||
await program.parseAsync(["memory", "index"], { from: "user" });
|
||||
|
||||
expect(sync).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ reason: "cli", force: false, progress: expect.any(Function) }),
|
||||
);
|
||||
expect(error).toHaveBeenCalledWith(
|
||||
expect.stringContaining("Memory index failed (main): QMD index file is empty"),
|
||||
);
|
||||
expect(close).toHaveBeenCalled();
|
||||
expect(process.exitCode).toBe(1);
|
||||
await fs.rm(tmpDir, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
it("logs close failures without failing the command", async () => {
|
||||
const { registerMemoryCli } = await import("./memory-cli.js");
|
||||
const { defaultRuntime } = await import("../runtime.js");
|
||||
|
||||
@@ -215,6 +215,34 @@ async function scanMemoryFiles(
|
||||
return { source: "memory", totalFiles, issues };
|
||||
}
|
||||
|
||||
async function summarizeQmdIndexArtifact(manager: MemoryManager): Promise<string | null> {
|
||||
const status = manager.status?.();
|
||||
if (!status || status.backend !== "qmd") {
|
||||
return null;
|
||||
}
|
||||
const dbPath = status.dbPath?.trim();
|
||||
if (!dbPath) {
|
||||
return null;
|
||||
}
|
||||
let stat: fsSync.Stats;
|
||||
try {
|
||||
stat = await fs.stat(dbPath);
|
||||
} catch (err) {
|
||||
const code = (err as NodeJS.ErrnoException).code;
|
||||
if (code === "ENOENT") {
|
||||
throw new Error(`QMD index file not found: ${shortenHomePath(dbPath)}`, { cause: err });
|
||||
}
|
||||
throw new Error(
|
||||
`QMD index file check failed: ${shortenHomePath(dbPath)} (${code ?? "error"})`,
|
||||
{ cause: err },
|
||||
);
|
||||
}
|
||||
if (!stat.isFile() || stat.size <= 0) {
|
||||
throw new Error(`QMD index file is empty: ${shortenHomePath(dbPath)}`);
|
||||
}
|
||||
return `QMD index: ${shortenHomePath(dbPath)} (${stat.size} bytes)`;
|
||||
}
|
||||
|
||||
async function scanMemorySources(params: {
|
||||
workspaceDir: string;
|
||||
agentId: string;
|
||||
@@ -633,6 +661,10 @@ export function registerMemoryCli(program: Command) {
|
||||
}
|
||||
},
|
||||
);
|
||||
const qmdIndexSummary = await summarizeQmdIndexArtifact(manager);
|
||||
if (qmdIndexSummary) {
|
||||
defaultRuntime.log(qmdIndexSummary);
|
||||
}
|
||||
defaultRuntime.log(`Memory index updated (${agentId}).`);
|
||||
} catch (err) {
|
||||
const message = formatErrorMessage(err);
|
||||
|
||||
Reference in New Issue
Block a user