Files
openclaw/src/memory/root-memory-files.ts
2026-05-02 00:21:49 +01:00

64 lines
2.0 KiB
TypeScript

import fs from "node:fs/promises";
import path from "node:path";
export const CANONICAL_ROOT_MEMORY_FILENAME = "MEMORY.md";
export const LEGACY_ROOT_MEMORY_FILENAME = "memory.md";
const ROOT_MEMORY_REPAIR_RELATIVE_DIR = ".openclaw-repair/root-memory";
export function resolveCanonicalRootMemoryPath(workspaceDir: string): string {
return path.join(workspaceDir, CANONICAL_ROOT_MEMORY_FILENAME);
}
export function resolveLegacyRootMemoryPath(workspaceDir: string): string {
return path.join(workspaceDir, LEGACY_ROOT_MEMORY_FILENAME);
}
export function resolveRootMemoryRepairDir(workspaceDir: string): string {
return path.join(workspaceDir, ".openclaw-repair", "root-memory");
}
function normalizeWorkspaceRelativePath(value: string): string {
return value.trim().replace(/\\/g, "/").replace(/^\.\//, "");
}
export async function exactWorkspaceEntryExists(dir: string, name: string): Promise<boolean> {
try {
const entries = await fs.readdir(dir);
return entries.includes(name);
} catch {
return false;
}
}
export async function resolveCanonicalRootMemoryFile(workspaceDir: string): Promise<string | null> {
try {
const entries = await fs.readdir(workspaceDir, { withFileTypes: true });
for (const entry of entries) {
if (
entry.name === CANONICAL_ROOT_MEMORY_FILENAME &&
entry.isFile() &&
!entry.isSymbolicLink()
) {
return path.join(workspaceDir, entry.name);
}
}
} catch {}
return null;
}
export function shouldSkipRootMemoryAuxiliaryPath(params: {
workspaceDir: string;
absPath: string;
}): boolean {
const relative = path.relative(params.workspaceDir, params.absPath);
if (relative.startsWith("..") || path.isAbsolute(relative)) {
return false;
}
const normalized = normalizeWorkspaceRelativePath(relative);
return (
normalized === LEGACY_ROOT_MEMORY_FILENAME ||
normalized === ROOT_MEMORY_REPAIR_RELATIVE_DIR ||
normalized.startsWith(`${ROOT_MEMORY_REPAIR_RELATIVE_DIR}/`)
);
}