Files
openclaw/src/memory/sync-session-files.ts
2026-02-15 01:15:43 +00:00

102 lines
2.9 KiB
TypeScript

import type { DatabaseSync } from "node:sqlite";
import type { SessionFileEntry } from "./session-files.js";
import { createSubsystemLogger } from "../logging/subsystem.js";
import {
buildSessionEntry,
listSessionFilesForAgent,
sessionPathForFile,
} from "./session-files.js";
import { indexFileEntryIfChanged } from "./sync-index.js";
import { deleteStaleIndexedPaths } from "./sync-stale.js";
const log = createSubsystemLogger("memory");
type ProgressState = {
completed: number;
total: number;
label?: string;
report: (update: { completed: number; total: number; label?: string }) => void;
};
export async function syncSessionFiles(params: {
agentId: string;
db: DatabaseSync;
needsFullReindex: boolean;
progress?: ProgressState;
batchEnabled: boolean;
concurrency: number;
runWithConcurrency: <T>(tasks: Array<() => Promise<T>>, concurrency: number) => Promise<T[]>;
indexFile: (entry: SessionFileEntry) => Promise<void>;
vectorTable: string;
ftsTable: string;
ftsEnabled: boolean;
ftsAvailable: boolean;
model: string;
dirtyFiles: Set<string>;
}) {
const files = await listSessionFilesForAgent(params.agentId);
const activePaths = new Set(files.map((file) => sessionPathForFile(file)));
const indexAll = params.needsFullReindex || params.dirtyFiles.size === 0;
log.debug("memory sync: indexing session files", {
files: files.length,
indexAll,
dirtyFiles: params.dirtyFiles.size,
batch: params.batchEnabled,
concurrency: params.concurrency,
});
if (params.progress) {
params.progress.total += files.length;
params.progress.report({
completed: params.progress.completed,
total: params.progress.total,
label: params.batchEnabled ? "Indexing session files (batch)..." : "Indexing session files…",
});
}
const tasks = files.map((absPath) => async () => {
if (!indexAll && !params.dirtyFiles.has(absPath)) {
if (params.progress) {
params.progress.completed += 1;
params.progress.report({
completed: params.progress.completed,
total: params.progress.total,
});
}
return;
}
const entry = await buildSessionEntry(absPath);
if (!entry) {
if (params.progress) {
params.progress.completed += 1;
params.progress.report({
completed: params.progress.completed,
total: params.progress.total,
});
}
return;
}
await indexFileEntryIfChanged({
db: params.db,
source: "sessions",
needsFullReindex: params.needsFullReindex,
entry,
indexFile: params.indexFile,
progress: params.progress,
});
});
await params.runWithConcurrency(tasks, params.concurrency);
deleteStaleIndexedPaths({
db: params.db,
source: "sessions",
activePaths,
vectorTable: params.vectorTable,
ftsTable: params.ftsTable,
ftsEnabled: params.ftsEnabled,
ftsAvailable: params.ftsAvailable,
model: params.model,
});
}