mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 07:10:43 +00:00
fix(memory): parse qmd vector status variants
This commit is contained in:
@@ -68,6 +68,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Ollama/onboarding: de-dupe suggested bare local models against installed `:latest` tags and skip redundant pulls, so setup shows the installed model once and no longer says it is downloading an already available model. Fixes #68952. Thanks @tleyden.
|
||||
- Memory-core/doctor: keep `doctor.memory.status` on the cached path by default and only run live embedding pings for explicit deep probes, preventing slow local embedding backends from blocking Gateway status checks. Fixes #71568. Thanks @apex-system.
|
||||
- Memory/QMD: group same-source collections into one QMD search invocation when the installed QMD supports multiple `-c` filters, while keeping older QMD builds on the per-collection fallback. Fixes #72484; supersedes #72485 and #69583. Thanks @BsnizND and @zeroaltitude.
|
||||
- Memory/QMD: accept QMD status vector-count variants such as `Vectors = 42`, `Vectors:42`, and `Vectors: 42 embedded`, so `memory status --deep` no longer reports embeddings unavailable for healthy QMD wrappers. Fixes #63652; carries forward #63678. Thanks @apoapostolov and @WarrenJones.
|
||||
- Memory/QMD: skip QMD vector status probes and embedding maintenance in lexical `searchMode: "search"`, so BM25-only QMD setups on ARM do not trigger llama.cpp/Vulkan builds during status checks or embed cycles. Fixes #59234 and #67113. Thanks @PrinceOfEgypt, @Vksh07, @Snipe76, @NomLom, @t4r3e2q1-commits, and @dmak.
|
||||
- Memory/QMD: report the live watcher dirty state in memory status, so changed QMD-backed memory files show as dirty until the queued sync finishes. Fixes #60244. Thanks @xinzf.
|
||||
- Compaction: skip oversized pre-compaction checkpoint snapshots and prune duplicate long user turns from compaction input and rotated successor transcripts, preventing retry storms from being preserved across checkpoint cycles. Fixes #72780. Thanks @SweetSophia.
|
||||
|
||||
@@ -4798,6 +4798,64 @@ describe("QmdMemoryManager", () => {
|
||||
await manager.close();
|
||||
});
|
||||
|
||||
it.each([
|
||||
["equals separator", "Documents: 12\nVectors = 42\n"],
|
||||
["tab separator", "Documents: 12\nVectors:\t42\n"],
|
||||
["compact separator", "Documents: 12\nVectors:42\n"],
|
||||
["embedded suffix", "Documents: 12\nVectors: 42 embedded\n"],
|
||||
])("reports vector availability as ready for qmd status %s", async (_name, statusOutput) => {
|
||||
spawnMock.mockImplementation((_cmd: string, args: string[]) => {
|
||||
if (args[0] === "status") {
|
||||
const child = createMockChild({ autoClose: false });
|
||||
emitAndClose(child, "stdout", statusOutput);
|
||||
return child;
|
||||
}
|
||||
return createMockChild();
|
||||
});
|
||||
|
||||
const { manager } = await createManager({
|
||||
cfg: {
|
||||
...cfg,
|
||||
memory: {
|
||||
...cfg.memory,
|
||||
qmd: { ...cfg.memory?.qmd, searchMode: "query" },
|
||||
},
|
||||
} as OpenClawConfig,
|
||||
});
|
||||
|
||||
await expect(manager.probeVectorAvailability()).resolves.toBe(true);
|
||||
await manager.close();
|
||||
});
|
||||
|
||||
it("does not parse unrelated qmd status vector-like fields", async () => {
|
||||
spawnMock.mockImplementation((_cmd: string, args: string[]) => {
|
||||
if (args[0] === "status") {
|
||||
const child = createMockChild({ autoClose: false });
|
||||
emitAndClose(child, "stdout", "Documents: 12\nMaxVectors: 42\nVector index: yes\n");
|
||||
return child;
|
||||
}
|
||||
return createMockChild();
|
||||
});
|
||||
|
||||
const { manager } = await createManager({
|
||||
cfg: {
|
||||
...cfg,
|
||||
memory: {
|
||||
...cfg.memory,
|
||||
qmd: { ...cfg.memory?.qmd, searchMode: "query" },
|
||||
},
|
||||
} as OpenClawConfig,
|
||||
});
|
||||
|
||||
await expect(manager.probeVectorAvailability()).resolves.toBe(false);
|
||||
expect(manager.status().vector).toEqual({
|
||||
enabled: true,
|
||||
available: false,
|
||||
loadError: "Could not determine QMD vector status from `qmd status`",
|
||||
});
|
||||
await manager.close();
|
||||
});
|
||||
|
||||
it("skips qmd status vector probes for lexical search mode", async () => {
|
||||
const { manager } = await createManager({
|
||||
cfg: {
|
||||
|
||||
@@ -154,12 +154,16 @@ function normalizeHanBm25Query(query: string): string {
|
||||
}
|
||||
|
||||
function parseQmdStatusVectorCount(raw: string): number | null {
|
||||
const match = raw.match(/(?:^|\n)\s*Vectors:\s*(\d+)\b/i);
|
||||
if (!match) {
|
||||
return null;
|
||||
for (const line of raw.split(/\r?\n/)) {
|
||||
const match = line.match(/^\s*Vectors(?:\s*[:=]\s*|\s+)(\d+)\b/i);
|
||||
if (match?.[1]) {
|
||||
const count = Number.parseInt(match[1], 10);
|
||||
if (Number.isFinite(count)) {
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
||||
const count = Number.parseInt(match[1] ?? "", 10);
|
||||
return Number.isFinite(count) ? count : null;
|
||||
return null;
|
||||
}
|
||||
|
||||
function resolveStableJitterMs(params: { seed: string; windowMs: number }): number {
|
||||
|
||||
Reference in New Issue
Block a user