Skip to content

Commit d766bfc

Browse files
upupcaltaywtf
andauthored
fix(memory): preserve session indexing during full reindex (#39732)
Merged via squash. Prepared head SHA: 0dbaf5f Co-authored-by: upupc <12829489+upupc@users.noreply.github.com> Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com> Reviewed-by: @altaywtf
1 parent 1654c3a commit d766bfc

3 files changed

Lines changed: 82 additions & 3 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ Docs: https://docs.openclaw.ai
4343
- WebChat/exec approvals: use native approval UI guidance in agent system prompts instead of telling agents to paste manual `/approve` commands in webchat sessions. Thanks @vincentkoc.
4444
- Plugins/install: forward `--dangerously-force-unsafe-install` through archive and npm-spec plugin installs so the documented override reaches the security scanner on those install paths. (#58879) Thanks @ryanlee-gemini.
4545
- Chat/error replies: stop leaking raw provider/runtime failures into external chat channels, return a friendly retry message instead, and add a specific `/new` hint for Bedrock toolResult/toolUse session mismatches. (#58831) Thanks @ImLukeF.
46+
- Memory/session indexing: keep full reindexes from skipping session transcripts when sync is triggered by `session-start` or `watch`, so restart-driven reindexes preserve session memory (#39732) thanks @upupc
4647

4748
## 2026.3.31
4849

extensions/memory-core/src/memory/manager-sync-ops.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -680,13 +680,13 @@ export abstract class MemoryManagerSyncOps {
680680
if (params?.force) {
681681
return true;
682682
}
683+
if (needsFullReindex) {
684+
return true;
685+
}
683686
const reason = params?.reason;
684687
if (reason === "session-start" || reason === "watch") {
685688
return false;
686689
}
687-
if (needsFullReindex) {
688-
return true;
689-
}
690690
return this.sessionsDirty && this.sessionsDirtyFiles.size > 0;
691691
}
692692

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import fs from "node:fs/promises";
2+
import os from "node:os";
3+
import path from "node:path";
4+
import type { OpenClawConfig } from "openclaw/plugin-sdk/memory-core-host-engine-foundation";
5+
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
6+
import type { MemoryIndexManager } from "./index.js";
7+
import { getRequiredMemoryIndexManager } from "./test-manager-helpers.js";
8+
9+
describe("memory manager session reindex gating", () => {
10+
let fixtureRoot = "";
11+
let caseId = 0;
12+
let workspaceDir: string;
13+
let indexPath: string;
14+
let manager: MemoryIndexManager | null = null;
15+
16+
beforeAll(async () => {
17+
fixtureRoot = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-mem-session-reindex-"));
18+
});
19+
20+
beforeEach(async () => {
21+
workspaceDir = path.join(fixtureRoot, `case-${caseId++}`);
22+
await fs.mkdir(path.join(workspaceDir, "memory"), { recursive: true });
23+
await fs.writeFile(path.join(workspaceDir, "MEMORY.md"), "Hello memory.");
24+
indexPath = path.join(workspaceDir, "index.sqlite");
25+
});
26+
27+
afterEach(async () => {
28+
if (manager) {
29+
await manager.close();
30+
manager = null;
31+
}
32+
});
33+
34+
afterAll(async () => {
35+
if (!fixtureRoot) {
36+
return;
37+
}
38+
await fs.rm(fixtureRoot, { recursive: true, force: true });
39+
});
40+
41+
it("keeps session syncing enabled for full reindexes triggered from session-start/watch", async () => {
42+
const cfg = {
43+
agents: {
44+
defaults: {
45+
workspace: workspaceDir,
46+
memorySearch: {
47+
provider: "openai",
48+
model: "mock-embed",
49+
store: { path: indexPath, vector: { enabled: false } },
50+
cache: { enabled: false },
51+
query: { minScore: 0, hybrid: { enabled: false } },
52+
chunking: { tokens: 4000, overlap: 0 },
53+
experimental: { sessionMemory: true },
54+
sources: ["memory", "sessions"],
55+
sync: { watch: false, onSessionStart: false, onSearch: false },
56+
},
57+
},
58+
list: [{ id: "main", default: true }],
59+
},
60+
} as OpenClawConfig;
61+
62+
manager = await getRequiredMemoryIndexManager({ cfg, agentId: "main" });
63+
64+
const shouldSyncSessions = (
65+
manager as unknown as {
66+
shouldSyncSessions: (
67+
params?: { reason?: string; force?: boolean },
68+
needsFullReindex?: boolean,
69+
) => boolean;
70+
}
71+
).shouldSyncSessions.bind(manager);
72+
73+
expect(shouldSyncSessions({ reason: "session-start" }, true)).toBe(true);
74+
expect(shouldSyncSessions({ reason: "watch" }, true)).toBe(true);
75+
expect(shouldSyncSessions({ reason: "session-start" }, false)).toBe(false);
76+
expect(shouldSyncSessions({ reason: "watch" }, false)).toBe(false);
77+
});
78+
});

0 commit comments

Comments
 (0)