Skip to content

/api/sources memory_dir not resolved (mismatches /api/memory-dirs/status — #668 follow-up) #675

@memtomem

Description

@memtomem

What

/api/sources returns each source's memory_dir as the raw configured path, while /api/memory-dirs/status returns the resolved path (after Path.resolve()).

Repro on macOS with a memory_dir registered under /tmp (which symlinks to /private/tmp):

$ curl -s http://127.0.0.1:8090/api/sources?limit=1 | jq -r '.sources[0].memory_dir'
/tmp/mm-cold-load-home/.claude/projects/.../memory

$ curl -s http://127.0.0.1:8090/api/memory-dirs/status | jq -r '.dirs[0].path'
/private/tmp/mm-cold-load-home/.claude/projects/.../memory

The two prefixes (/tmp vs /private/tmp) come from the same on-disk directory but read as distinct strings, breaking client-side dictionary lookups.

Where it bites

packages/memtomem/src/memtomem/web/static/app.js builds STATE.memoryStatusByPath keyed off /api/memory-dirs/status path values, then looks up STATE.memoryStatusByPath[source.memory_dir] to derive the vendor (status.provider) for a given source. With the prefix mismatch the lookup misses, so vendor inference fails — fallbacks downstream end up rendering the source under whatever sub-tab is currently active.

This was caught in #674's verification fixture (which uses /tmp/ as the isolated HOME); switching the fixture to /private/tmp/ made every test pass. The typical real-HOME deployment (/Users/<name>/... on macOS, /home/<name>/... on Linux) doesn't trigger any symlink resolution, so the bug stays invisible — but a user who registers a memory_dir under any symlinked prefix would hit it silently.

Why this is a #668 follow-up

#668 normalized /api/memory-dirs/status to resolve path. The same treatment never reached /api/sources. This issue tracks bringing the two endpoints into agreement so both surfaces use post-resolve paths.

Suggested fix

Apply the same path.resolve() (or the equivalent helper #668 introduced) to the memory_dir field in the /api/sources response. Add a parity test: take a memory_dir under a symlinked prefix and assert the two endpoints' paths match.

Severity

Low — invisible on the dominant real-HOME deployments. Surfaces in CI fixtures, Docker mounts, or any user who registers a memory_dir via a symlinked path. Not blocking — listed as out-of-scope in #674's PR body.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions