feat: add user_mapper.py for cross-channel memory unification - #19163
feat: add user_mapper.py for cross-channel memory unification#19163Cyrene963 wants to merge 1 commit into
Conversation
1231b79 to
500d2b0
Compare
1 similar comment
|
Thanks for pointing out #9308! You're right that both address cross-channel identity, but they solve it at different scopes: #9308 (Honcho gateway layer):
#19163 (filesystem layer):
The gap in #9308: if a non-owner user (e.g., a classmate sharing the bot) uses both Telegram and CLI, their memories are still split. #9308's Proposed approach:
I'll update #19163 to also support automatic owner detection (symlink the global MEMORY.md/USER.md to the owner's user directory on first setup), reducing the manual config burden. |
500d2b0 to
9ea7ce0
Compare
|
The Questions before merge:
The core logic looks solid. The file is well-structured with clear docstrings. Resolving the location and persistence questions would unblock merge. |
|
Thanks for the thorough review, @ether-btc! Good questions. Here's the breakdown: 1. Location:
|
9ea7ce0 to
4cf1e75
Compare
…cation Adds command that: 1. Reads config.yaml to find Telegram home channel chat_id 2. Falls back to largest memory directory detection 3. Automatically migrates data and creates symlinks 4. Sets up global MEMORY.md/USER.md for CLI access Addresses feedback on NousResearch#9308 overlap: - NousResearch#9308 auto-detects owner at gateway layer (Honcho only) - This provides auto-setup for owner + manual mapping for any user - Works with all memory providers, not just Honcho Commands: auto-setup, map, unmap, list, resolve, migrate
4cf1e75 to
eba9d52
Compare
teknium1
left a comment
There was a problem hiding this comment.
Thanks for tackling cross-channel continuity. Current main shows that this implementation needs a redesign before it can provide the stated behavior.
Problems
scripts/user_mapper.py:61assumes Hermes readsmemories/<chat_id>/; built-in memory instead always reads rootMEMORY.mdandUSER.mdfromget_hermes_home() / "memories"(tools/memory_tool.py:55-57,:185-189). The per-chat links are inert, while the global links redirect all built-in-memory sessions in the profile.- Provider memory is identity-based:
agent/agent_init.py:1384-1410forwards runtime user IDs and chat metadata. Filesystem links cannot unify those providers. Honcho already documents many-to-oneuserPeerAliasesmapping (plugins/memory/honcho/README.md:145-167). - The script hardcodes
Path.home() / ".hermes"(scripts/user_mapper.py:79-81), bypassing HERMES_HOME/profile isolation (hermes_constants.py:55-110). scripts/user_mapper.py:414-427skips colliding files then deletes the source directory, which can lose skipped data.
Suggested changes
- Re-scope this around provider-consumable canonical identity mapping, using the existing Honcho mapping where applicable, and add hermetic HERMES_HOME tests for migration/conflict cases.
Automated hermes-sweeper review.
| """Get the directory Hermes expects for a chat_id.""" | ||
| return MEMORIES_DIR / chat_id | ||
|
|
||
|
|
There was a problem hiding this comment.
This bypasses get_hermes_home(), so it targets the wrong state for named profiles and custom HERMES_HOME deployments. Use the profile-aware resolver rather than hardcoding Path.home() / '.hermes'.
| print(__doc__) | ||
| sys.exit(1) | ||
|
|
||
| cmd = sys.argv[1] |
There was a problem hiding this comment.
A destination collision is skipped here, but the source directory is unconditionally removed at line 427. That silently deletes every skipped source item; require an explicit conflict policy that preserves or aborts on conflicting data.
The github-filing-registry.json was carrying 4 entries pointing at PRs that no longer exist (404 Not Found from GitHub API) or that the token could no longer access (401 Bad credentials). These were filed in April-May 2026 against: - ch0udry/hermes-rtk-optimizer#1 - NousResearch/hermes-agent#19163 (and 2 others) - wysie/hermes-omni-plugin#1 Sync now correctly reports them as 'unknown' and they're removed from the registry. Also: skills/github-filing-registry/filing-registry cmd_sync() now captures gh CLI exit code separately so 'unknown' is set when the API fails (not just when the jq parse fails). Co-authored-by: housekeeping-session-2026-07-26
Summary
Addresses community feedback on multi-user isolation design: same user on different channels (CLI, Telegram, Discord) gets separate memory banks.
Solution
user_mapper.py— a filesystem utility that unifies a user's memories across channels via symlinks:MEMORY.md/USER.mdsymlinked to user's directorymemories/{chat_id}/symlinked to user's directoryCommands
Relationship to PR #17989
Complementary, not competing. #17989 is the foundation; this builds on it.
How It Works
memories/user_{username}/as the real data directorymemories/{chat_id}/→user_{username}/MEMORY.md/USER.md→user_{username}/(for CLI)Limitations
MEMORY.mdsymlink means all non-Telegram sessions (CLI, cron) share the same user's memory. Fine for single-user setups; multi-user CLI needs code-level user_id support.Test Results
All 5 tests pass locally: