Skip to content

Native memory import ignores USER.md (Hermes adapter reads only MEMORY.md) #2306

Description

@hxyinan

Bug Description

GET /api/v1/import/hermes-native/scan and the paged import endpoints read only MEMORY.md from the Hermes memories directory. USER.md (the user-profile store that Hermes maintains next to MEMORY.md) is never imported, so user-profile content silently never reaches the MemOS L1/L2 layers on a native-memory import.

Affected code (2.0.17)

dist/server/routes/import-export.jsreadHermesNativeMemories(path, opts):

async function readHermesNativeMemories(path, opts = {}) {
    const info = await stat(path);
    ...
    const raw = await readFile(path, "utf8");
    const source = {
        memories: splitHermesNativeMemories(raw),   // <-- MEMORY.md only
        bytes: info.size,
        mtimeMs: info.mtimeMs,
    };
    ...
}

Both consumers (scan at line ~315, paged import at line ~126) go through this single function, so one fix covers both. Cache correctness requires the bytes/mtimeMs fingerprint to cover USER.md too, otherwise edits to USER.md won't invalidate the cache.

Suggested fix

Read the sibling USER.md (optional, skip silently when missing) and include its entries in the same source structure:

const memories = [];
const memoryMtime = info.mtimeMs;
for (const text of splitHermesNativeMemories(await readFile(path, "utf8"))) {
    memories.push({ text, file: "MEMORY.md", mtimeMs: memoryMtime });
}
let bytes = info.size;
let mtimeMs = memoryMtime;
try {
    const userPath = join(dirname(path), "USER.md");
    const userInfo = await stat(userPath);
    const userRaw = await readFile(userPath, "utf8");
    for (const text of splitHermesNativeMemories(userRaw)) {
        memories.push({ text, file: "USER.md", mtimeMs: userInfo.mtimeMs });
    }
    bytes += userInfo.size;
    mtimeMs = Math.max(mtimeMs, userInfo.mtimeMs);
} catch { /* USER.md is optional */ }
const source = { memories, bytes, mtimeMs };

Note: this also requires dirname to be imported from node:path (2.0.17 currently imports only join).

Entries carry a file tag so the UI/dedup layer can distinguish MEMORY.md vs USER.md entries. A local patch running this exact body on 2.0.17 has been verified end-to-end (import + viewer display).

Environment

  • Plugin: @memtensor/memos-local-plugin 2.0.17
  • Agent: Hermes (Windows native)

Metadata

Metadata

Labels

area:pluginOpenClaw & Hermesstatus:needs-triageNeeds initial triage | 需要初步判断 & 问题复现

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions