mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 18:50:42 +00:00
@@ -530,17 +530,12 @@ async function scanMemoryFiles(
|
||||
): Promise<SourceScan> {
|
||||
const issues: string[] = [];
|
||||
const memoryFile = path.join(workspaceDir, "MEMORY.md");
|
||||
const altMemoryFile = path.join(workspaceDir, "memory.md");
|
||||
const memoryDir = path.join(workspaceDir, "memory");
|
||||
|
||||
const primary = await checkReadableFile(memoryFile);
|
||||
const alt = await checkReadableFile(altMemoryFile);
|
||||
if (primary.issue) {
|
||||
issues.push(primary.issue);
|
||||
}
|
||||
if (alt.issue) {
|
||||
issues.push(alt.issue);
|
||||
}
|
||||
|
||||
const resolvedExtraPaths = normalizeExtraMemoryPaths(workspaceDir, extraPaths);
|
||||
for (const extraPath of resolvedExtraPaths) {
|
||||
@@ -606,9 +601,6 @@ async function scanMemoryFiles(
|
||||
if (primary.exists) {
|
||||
files.add(memoryFile);
|
||||
}
|
||||
if (alt.exists) {
|
||||
files.add(altMemoryFile);
|
||||
}
|
||||
}
|
||||
totalFiles = files.size;
|
||||
}
|
||||
|
||||
@@ -370,7 +370,6 @@ export abstract class MemoryManagerSyncOps {
|
||||
}
|
||||
const watchPaths = new Set<string>([
|
||||
path.join(this.workspaceDir, "MEMORY.md"),
|
||||
path.join(this.workspaceDir, "memory.md"),
|
||||
path.join(this.workspaceDir, "memory"),
|
||||
]);
|
||||
const additionalPaths = normalizeExtraMemoryPaths(this.workspaceDir, this.settings.extraPaths);
|
||||
|
||||
@@ -139,7 +139,6 @@ describe("memory watcher config", () => {
|
||||
expect(watchedPaths).toEqual(
|
||||
expect.arrayContaining([
|
||||
path.join(workspaceDir, "MEMORY.md"),
|
||||
path.join(workspaceDir, "memory.md"),
|
||||
path.join(workspaceDir, "memory"),
|
||||
path.join(extraDir, "**", "*.md"),
|
||||
]),
|
||||
|
||||
@@ -878,7 +878,7 @@ describe("QmdMemoryManager", () => {
|
||||
expect(logWarnMock).toHaveBeenCalledWith(expect.stringContaining("rebinding"));
|
||||
});
|
||||
|
||||
it("rebinds legacy memory-alt when it still owns the root slot for MEMORY.md", async () => {
|
||||
it("adds canonical memory-root without treating legacy memory-alt as equivalent", async () => {
|
||||
await fs.writeFile(path.join(workspaceDir, "MEMORY.md"), "# canonical root");
|
||||
cfg = {
|
||||
...cfg,
|
||||
@@ -930,15 +930,10 @@ describe("QmdMemoryManager", () => {
|
||||
const pathArg = args[2] ?? "";
|
||||
const name = args[args.indexOf("--name") + 1] ?? "";
|
||||
const pattern = args[args.indexOf("--glob") + 1] ?? args[args.indexOf("--mask") + 1] ?? "";
|
||||
const hasConflict = [...listedCollections.entries()].some(([existingName, info]) => {
|
||||
if (existingName === name || info.path !== pathArg) {
|
||||
return false;
|
||||
}
|
||||
const isRootPatternPair =
|
||||
(info.pattern === "MEMORY.md" || info.pattern === "memory.md") &&
|
||||
(pattern === "MEMORY.md" || pattern === "memory.md");
|
||||
return info.pattern === pattern || isRootPatternPair;
|
||||
});
|
||||
const hasConflict = [...listedCollections.entries()].some(
|
||||
([existingName, info]) =>
|
||||
existingName !== name && info.path === pathArg && info.pattern === pattern,
|
||||
);
|
||||
if (hasConflict) {
|
||||
emitAndClose(child, "stderr", "A collection already exists for this path and pattern", 1);
|
||||
return child;
|
||||
@@ -953,10 +948,10 @@ describe("QmdMemoryManager", () => {
|
||||
const { manager } = await createManager({ mode: "full" });
|
||||
await manager.close();
|
||||
|
||||
expect(removeCalls).toContain("memory-alt");
|
||||
expect(removeCalls).not.toContain("memory-alt");
|
||||
expect(listedCollections.has("memory-root-main")).toBe(true);
|
||||
expect(listedCollections.has("memory-alt")).toBe(false);
|
||||
expect(logWarnMock).toHaveBeenCalledWith(expect.stringContaining("rebinding"));
|
||||
expect(listedCollections.has("memory-alt")).toBe(true);
|
||||
expect(logWarnMock).not.toHaveBeenCalledWith(expect.stringContaining("rebinding"));
|
||||
});
|
||||
|
||||
it("warns instead of silently succeeding when add conflict metadata is unavailable", async () => {
|
||||
|
||||
@@ -92,12 +92,7 @@ function isDefaultMemoryPath(relPath: string): boolean {
|
||||
if (!normalized) {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
normalized === "MEMORY.md" ||
|
||||
normalized === "memory.md" ||
|
||||
normalized === "DREAMS.md" ||
|
||||
normalized === "dreams.md"
|
||||
) {
|
||||
if (normalized === "MEMORY.md" || normalized === "DREAMS.md" || normalized === "dreams.md") {
|
||||
return true;
|
||||
}
|
||||
return normalized.startsWith("memory/");
|
||||
@@ -894,29 +889,22 @@ export class QmdMemoryManager implements MemorySearchManager {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
let sawCanonical = false;
|
||||
let sawLegacyFallback = false;
|
||||
for (const entry of fsSync.readdirSync(collectionPath, { withFileTypes: true })) {
|
||||
if (entry.isSymbolicLink() || !entry.isFile()) {
|
||||
continue;
|
||||
}
|
||||
if (entry.name === "MEMORY.md") {
|
||||
sawCanonical = true;
|
||||
} else if (entry.name === "memory.md") {
|
||||
sawLegacyFallback = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (sawCanonical && sawLegacyFallback) {
|
||||
return false;
|
||||
}
|
||||
return sawCanonical || sawLegacyFallback;
|
||||
return false;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private isDefaultMemoryRootPattern(pattern: string): boolean {
|
||||
return pattern === "MEMORY.md" || pattern === "memory.md";
|
||||
return pattern === "MEMORY.md";
|
||||
}
|
||||
|
||||
private pathsMatch(left: string, right: string): boolean {
|
||||
|
||||
@@ -70,7 +70,7 @@ function parseMemoryDateFromPath(filePath: string): Date | null {
|
||||
|
||||
function isEvergreenMemoryPath(filePath: string): boolean {
|
||||
const normalized = filePath.replaceAll("\\", "/").replace(/^\.\//, "");
|
||||
if (normalized === "MEMORY.md" || normalized === "memory.md") {
|
||||
if (normalized === "MEMORY.md") {
|
||||
return true;
|
||||
}
|
||||
if (!normalized.startsWith("memory/")) {
|
||||
|
||||
@@ -87,7 +87,7 @@ describe("listMemoryCorePublicArtifacts", () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it("lists lowercase memory root when only the legacy filename exists", async () => {
|
||||
it("ignores lowercase memory root when only the legacy filename exists", async () => {
|
||||
const workspaceDir = path.join(fixtureRoot, "workspace-lowercase-root");
|
||||
await fs.mkdir(workspaceDir, { recursive: true });
|
||||
await fs.writeFile(path.join(workspaceDir, "memory.md"), "# Legacy Durable Memory\n", "utf8");
|
||||
@@ -98,15 +98,6 @@ describe("listMemoryCorePublicArtifacts", () => {
|
||||
},
|
||||
};
|
||||
|
||||
await expect(listMemoryCorePublicArtifacts({ cfg })).resolves.toEqual([
|
||||
{
|
||||
kind: "memory-root",
|
||||
workspaceDir,
|
||||
relativePath: "memory.md",
|
||||
absolutePath: path.join(workspaceDir, "memory.md"),
|
||||
agentIds: ["main"],
|
||||
contentType: "markdown",
|
||||
},
|
||||
]);
|
||||
await expect(listMemoryCorePublicArtifacts({ cfg })).resolves.toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -40,7 +40,7 @@ async function collectWorkspaceArtifacts(params: {
|
||||
.filter((entry) => entry.isFile())
|
||||
.map((entry) => entry.name),
|
||||
);
|
||||
for (const relativePath of ["MEMORY.md", "memory.md"]) {
|
||||
for (const relativePath of ["MEMORY.md"]) {
|
||||
if (!workspaceEntries.has(relativePath)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user