mirror of https://github.com/openclaw/openclaw.git
fix(memory): preserve session indexing during full reindex (#39732)
Merged via squash.
Prepared head SHA: 0dbaf5fffb
Co-authored-by: upupc <12829489+upupc@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
This commit is contained in:
parent
1654c3a851
commit
d766bfc6b2
|
|
@ -43,6 +43,7 @@ Docs: https://docs.openclaw.ai
|
|||
- 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.
|
||||
- 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.
|
||||
- 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.
|
||||
- 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
|
||||
|
||||
## 2026.3.31
|
||||
|
||||
|
|
|
|||
|
|
@ -680,13 +680,13 @@ export abstract class MemoryManagerSyncOps {
|
|||
if (params?.force) {
|
||||
return true;
|
||||
}
|
||||
if (needsFullReindex) {
|
||||
return true;
|
||||
}
|
||||
const reason = params?.reason;
|
||||
if (reason === "session-start" || reason === "watch") {
|
||||
return false;
|
||||
}
|
||||
if (needsFullReindex) {
|
||||
return true;
|
||||
}
|
||||
return this.sessionsDirty && this.sessionsDirtyFiles.size > 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,78 @@
|
|||
import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import type { OpenClawConfig } from "openclaw/plugin-sdk/memory-core-host-engine-foundation";
|
||||
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
||||
import type { MemoryIndexManager } from "./index.js";
|
||||
import { getRequiredMemoryIndexManager } from "./test-manager-helpers.js";
|
||||
|
||||
describe("memory manager session reindex gating", () => {
|
||||
let fixtureRoot = "";
|
||||
let caseId = 0;
|
||||
let workspaceDir: string;
|
||||
let indexPath: string;
|
||||
let manager: MemoryIndexManager | null = null;
|
||||
|
||||
beforeAll(async () => {
|
||||
fixtureRoot = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-mem-session-reindex-"));
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
workspaceDir = path.join(fixtureRoot, `case-${caseId++}`);
|
||||
await fs.mkdir(path.join(workspaceDir, "memory"), { recursive: true });
|
||||
await fs.writeFile(path.join(workspaceDir, "MEMORY.md"), "Hello memory.");
|
||||
indexPath = path.join(workspaceDir, "index.sqlite");
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
if (manager) {
|
||||
await manager.close();
|
||||
manager = null;
|
||||
}
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
if (!fixtureRoot) {
|
||||
return;
|
||||
}
|
||||
await fs.rm(fixtureRoot, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
it("keeps session syncing enabled for full reindexes triggered from session-start/watch", async () => {
|
||||
const cfg = {
|
||||
agents: {
|
||||
defaults: {
|
||||
workspace: workspaceDir,
|
||||
memorySearch: {
|
||||
provider: "openai",
|
||||
model: "mock-embed",
|
||||
store: { path: indexPath, vector: { enabled: false } },
|
||||
cache: { enabled: false },
|
||||
query: { minScore: 0, hybrid: { enabled: false } },
|
||||
chunking: { tokens: 4000, overlap: 0 },
|
||||
experimental: { sessionMemory: true },
|
||||
sources: ["memory", "sessions"],
|
||||
sync: { watch: false, onSessionStart: false, onSearch: false },
|
||||
},
|
||||
},
|
||||
list: [{ id: "main", default: true }],
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
|
||||
manager = await getRequiredMemoryIndexManager({ cfg, agentId: "main" });
|
||||
|
||||
const shouldSyncSessions = (
|
||||
manager as unknown as {
|
||||
shouldSyncSessions: (
|
||||
params?: { reason?: string; force?: boolean },
|
||||
needsFullReindex?: boolean,
|
||||
) => boolean;
|
||||
}
|
||||
).shouldSyncSessions.bind(manager);
|
||||
|
||||
expect(shouldSyncSessions({ reason: "session-start" }, true)).toBe(true);
|
||||
expect(shouldSyncSessions({ reason: "watch" }, true)).toBe(true);
|
||||
expect(shouldSyncSessions({ reason: "session-start" }, false)).toBe(false);
|
||||
expect(shouldSyncSessions({ reason: "watch" }, false)).toBe(false);
|
||||
});
|
||||
});
|
||||
Loading…
Reference in New Issue