mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-24 11:25:50 -06:00
fix(memory): detect shipped status indexes
This commit is contained in:
@@ -573,6 +573,66 @@ describe("resolveSharedMemoryStatusSnapshot", () => {
|
||||
expect(getMemorySearchManager).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("recognizes shipped memory tables before the manager migrates them", async () => {
|
||||
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-status-memory-"));
|
||||
const databasePath = path.join(tempDir, "openclaw-agent.sqlite");
|
||||
const db = new DatabaseSync(databasePath);
|
||||
db.exec(`
|
||||
CREATE TABLE meta (key TEXT PRIMARY KEY, value TEXT NOT NULL);
|
||||
CREATE TABLE files (
|
||||
path TEXT PRIMARY KEY,
|
||||
source TEXT NOT NULL DEFAULT 'memory',
|
||||
hash TEXT NOT NULL,
|
||||
mtime INTEGER NOT NULL,
|
||||
size INTEGER NOT NULL
|
||||
);
|
||||
CREATE TABLE chunks (
|
||||
id TEXT PRIMARY KEY,
|
||||
path TEXT NOT NULL,
|
||||
source TEXT NOT NULL DEFAULT 'memory',
|
||||
start_line INTEGER NOT NULL,
|
||||
end_line INTEGER NOT NULL,
|
||||
hash TEXT NOT NULL,
|
||||
model TEXT NOT NULL,
|
||||
text TEXT NOT NULL,
|
||||
embedding TEXT NOT NULL,
|
||||
updated_at INTEGER NOT NULL
|
||||
);
|
||||
INSERT INTO files VALUES ('MEMORY.md', 'memory', 'file-hash', 10, 20);
|
||||
`);
|
||||
db.close();
|
||||
const manager = {
|
||||
probeVectorStoreAvailability: vi.fn(async () => true),
|
||||
probeVectorAvailability: vi.fn(async () => true),
|
||||
status: vi.fn(() => ({
|
||||
backend: "builtin" as const,
|
||||
provider: "openai",
|
||||
files: 1,
|
||||
chunks: 0,
|
||||
vector: { enabled: true, available: true },
|
||||
fts: { enabled: true, available: true },
|
||||
})),
|
||||
close: vi.fn(async () => {}),
|
||||
};
|
||||
const getMemorySearchManager = vi.fn(async () => ({ manager }));
|
||||
|
||||
try {
|
||||
const result = await resolveSharedMemoryStatusSnapshot({
|
||||
cfg: {},
|
||||
agentStatus: { defaultId: "main" },
|
||||
memoryPlugin: { enabled: true, slot: "memory-core" },
|
||||
resolveMemoryConfig: vi.fn(() => ({ store: { databasePath } })),
|
||||
getMemorySearchManager,
|
||||
requireDefaultDatabasePath: () => databasePath,
|
||||
});
|
||||
|
||||
expect(getMemorySearchManager).toHaveBeenCalledOnce();
|
||||
expect(result?.files).toBe(1);
|
||||
} finally {
|
||||
fs.rmSync(tempDir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
it("does not initialize memory status for an agent database owned by another feature", async () => {
|
||||
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-status-memory-"));
|
||||
const databasePath = path.join(tempDir, "openclaw-agent.sqlite");
|
||||
|
||||
@@ -56,35 +56,51 @@ function hasBuiltInMemoryState(databasePath: string): boolean {
|
||||
let db: DatabaseSync | undefined;
|
||||
try {
|
||||
db = new DatabaseSync(databasePath, { readOnly: true });
|
||||
const builtInMemoryTables = [
|
||||
MEMORY_INDEX_META_TABLE,
|
||||
MEMORY_INDEX_SOURCES_TABLE,
|
||||
MEMORY_INDEX_CHUNKS_TABLE,
|
||||
const builtInMemoryTableSets = [
|
||||
{
|
||||
meta: MEMORY_INDEX_META_TABLE,
|
||||
sources: MEMORY_INDEX_SOURCES_TABLE,
|
||||
chunks: MEMORY_INDEX_CHUNKS_TABLE,
|
||||
},
|
||||
{
|
||||
meta: "meta",
|
||||
sources: "files",
|
||||
chunks: "chunks",
|
||||
},
|
||||
] as const;
|
||||
const builtInMemoryTables = builtInMemoryTableSets.flatMap(({ meta, sources, chunks }) => [
|
||||
meta,
|
||||
sources,
|
||||
chunks,
|
||||
]);
|
||||
const tableNames = new Set(
|
||||
(
|
||||
db
|
||||
.prepare(`SELECT name FROM sqlite_master WHERE type = 'table' AND name IN (?, ?, ?)`)
|
||||
.prepare(
|
||||
`SELECT name FROM sqlite_master WHERE type = 'table' AND name IN (${builtInMemoryTables.map(() => "?").join(", ")})`,
|
||||
)
|
||||
.all(...builtInMemoryTables) as Array<{ name?: unknown }>
|
||||
)
|
||||
.map((row) => row.name)
|
||||
.filter((name): name is string => typeof name === "string"),
|
||||
);
|
||||
if (
|
||||
tableNames.has(MEMORY_INDEX_META_TABLE) &&
|
||||
db
|
||||
.prepare(`SELECT 1 AS ok FROM ${MEMORY_INDEX_META_TABLE} WHERE key = ? LIMIT 1`)
|
||||
.get(MEMORY_INDEX_META_KEY)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
for (const tableName of [MEMORY_INDEX_SOURCES_TABLE, MEMORY_INDEX_CHUNKS_TABLE] as const) {
|
||||
for (const tables of builtInMemoryTableSets) {
|
||||
if (
|
||||
tableNames.has(tableName) &&
|
||||
db.prepare(`SELECT 1 AS ok FROM ${tableName} LIMIT 1`).get()
|
||||
tableNames.has(tables.meta) &&
|
||||
db
|
||||
.prepare(`SELECT 1 AS ok FROM ${tables.meta} WHERE key = ? LIMIT 1`)
|
||||
.get(MEMORY_INDEX_META_KEY)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
for (const tableName of [tables.sources, tables.chunks]) {
|
||||
if (
|
||||
tableNames.has(tableName) &&
|
||||
db.prepare(`SELECT 1 AS ok FROM ${tableName} LIMIT 1`).get()
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} catch {
|
||||
|
||||
Reference in New Issue
Block a user