mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 00:30:21 +00:00
feat(memory-wiki): restore llm wiki stack
This commit is contained in:
123
extensions/memory-wiki/src/source-sync-state.ts
Normal file
123
extensions/memory-wiki/src/source-sync-state.ts
Normal file
@@ -0,0 +1,123 @@
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
|
||||
export type MemoryWikiImportedSourceGroup = "bridge" | "unsafe-local";
|
||||
|
||||
export type MemoryWikiImportedSourceStateEntry = {
|
||||
group: MemoryWikiImportedSourceGroup;
|
||||
pagePath: string;
|
||||
sourcePath: string;
|
||||
sourceUpdatedAtMs: number;
|
||||
sourceSize: number;
|
||||
renderFingerprint: string;
|
||||
};
|
||||
|
||||
type MemoryWikiImportedSourceState = {
|
||||
version: 1;
|
||||
entries: Record<string, MemoryWikiImportedSourceStateEntry>;
|
||||
};
|
||||
|
||||
const EMPTY_STATE: MemoryWikiImportedSourceState = {
|
||||
version: 1,
|
||||
entries: {},
|
||||
};
|
||||
|
||||
export function resolveMemoryWikiSourceSyncStatePath(vaultRoot: string): string {
|
||||
return path.join(vaultRoot, ".openclaw-wiki", "source-sync.json");
|
||||
}
|
||||
|
||||
export async function readMemoryWikiSourceSyncState(
|
||||
vaultRoot: string,
|
||||
): Promise<MemoryWikiImportedSourceState> {
|
||||
const statePath = resolveMemoryWikiSourceSyncStatePath(vaultRoot);
|
||||
const raw = await fs.readFile(statePath, "utf8").catch((err: unknown) => {
|
||||
if ((err as NodeJS.ErrnoException)?.code === "ENOENT") {
|
||||
return "";
|
||||
}
|
||||
throw err;
|
||||
});
|
||||
if (!raw.trim()) {
|
||||
return {
|
||||
version: EMPTY_STATE.version,
|
||||
entries: {},
|
||||
};
|
||||
}
|
||||
try {
|
||||
const parsed = JSON.parse(raw) as Partial<MemoryWikiImportedSourceState>;
|
||||
return {
|
||||
version: 1,
|
||||
entries: { ...(parsed.entries ?? {}) },
|
||||
};
|
||||
} catch {
|
||||
return {
|
||||
version: EMPTY_STATE.version,
|
||||
entries: {},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function writeMemoryWikiSourceSyncState(
|
||||
vaultRoot: string,
|
||||
state: MemoryWikiImportedSourceState,
|
||||
): Promise<void> {
|
||||
const statePath = resolveMemoryWikiSourceSyncStatePath(vaultRoot);
|
||||
await fs.mkdir(path.dirname(statePath), { recursive: true });
|
||||
await fs.writeFile(statePath, `${JSON.stringify(state, null, 2)}\n`, "utf8");
|
||||
}
|
||||
|
||||
export async function shouldSkipImportedSourceWrite(params: {
|
||||
vaultRoot: string;
|
||||
syncKey: string;
|
||||
expectedPagePath: string;
|
||||
expectedSourcePath: string;
|
||||
sourceUpdatedAtMs: number;
|
||||
sourceSize: number;
|
||||
renderFingerprint: string;
|
||||
state: MemoryWikiImportedSourceState;
|
||||
}): Promise<boolean> {
|
||||
const entry = params.state.entries[params.syncKey];
|
||||
if (!entry) {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
entry.pagePath !== params.expectedPagePath ||
|
||||
entry.sourcePath !== params.expectedSourcePath ||
|
||||
entry.sourceUpdatedAtMs !== params.sourceUpdatedAtMs ||
|
||||
entry.sourceSize !== params.sourceSize ||
|
||||
entry.renderFingerprint !== params.renderFingerprint
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
const pagePath = path.join(params.vaultRoot, params.expectedPagePath);
|
||||
return await fs
|
||||
.access(pagePath)
|
||||
.then(() => true)
|
||||
.catch(() => false);
|
||||
}
|
||||
|
||||
export async function pruneImportedSourceEntries(params: {
|
||||
vaultRoot: string;
|
||||
group: MemoryWikiImportedSourceGroup;
|
||||
activeKeys: Set<string>;
|
||||
state: MemoryWikiImportedSourceState;
|
||||
}): Promise<number> {
|
||||
let removedCount = 0;
|
||||
for (const [syncKey, entry] of Object.entries(params.state.entries)) {
|
||||
if (entry.group !== params.group || params.activeKeys.has(syncKey)) {
|
||||
continue;
|
||||
}
|
||||
const pageAbsPath = path.join(params.vaultRoot, entry.pagePath);
|
||||
await fs.rm(pageAbsPath, { force: true }).catch(() => undefined);
|
||||
delete params.state.entries[syncKey];
|
||||
removedCount += 1;
|
||||
}
|
||||
return removedCount;
|
||||
}
|
||||
|
||||
export function setImportedSourceEntry(params: {
|
||||
syncKey: string;
|
||||
entry: MemoryWikiImportedSourceStateEntry;
|
||||
state: MemoryWikiImportedSourceState;
|
||||
}): void {
|
||||
params.state.entries[params.syncKey] = params.entry;
|
||||
}
|
||||
Reference in New Issue
Block a user