Skip to content

fix(memory): support Mem0 OSS mode in doctor + setup wizard - #59865

Open
lunalunaa wants to merge 2 commits into
NousResearch:mainfrom
lunalunaa:fix/mem0-doctor-oss-mode
Open

fix(memory): support Mem0 OSS mode in doctor + setup wizard#59865
lunalunaa wants to merge 2 commits into
NousResearch:mainfrom
lunalunaa:fix/mem0-doctor-oss-mode

Conversation

@lunalunaa

@lunalunaa lunalunaa commented Jul 6, 2026

Copy link
Copy Markdown

Fixes #57931

Three bugs in the Mem0 memory provider integration:

1. hermes doctor — Mem0 OSS mode falsely reports "API key not set"

doctor.py:2308 only looked for a top-level api_key from _load_config(). In OSS mode there is no top-level api_key — credentials are nested in oss.llm.config.api_key and oss.embedder.config.api_key in mem0.json. The check now branches on mode:

  • OSS mode: validates oss.llm.config.api_key, oss.embedder.config.api_key, and oss.vector_store.provider are present. Reports mode, user_id, agent_id, llm model, embedder model, and vector store.
  • Platform mode: unchanged — checks top-level api_key.

2. hermes memory setup — picker defaults to "Built-in only" even when a provider is active

memory_setup.py:271 hardcoded the picker default to builtin_idx (the last item, "Built-in only"). If the user pressed Enter without moving the cursor, it silently overwrote memory.provider: mem0"". The fix reads the current config and defaults the cursor to the active provider.

3. hermes memory setup — mode picker always defaults to Platform, ignoring existing config

plugins/memory/mem0/_setup.py:post_setup() showed an interactive 3-option picker (Platform / Self-hosted / Open Source) with the cursor hardcoded to index 0 (Platform), ignoring the existing mem0.json mode. A user running hermes memory setup on an OSS setup would silently switch to Platform mode by pressing Enter. The fix:

  • Reads the current mode from mem0.json and defaults the cursor to the active mode.
  • Adds a "← current" label to the active mode option so the user can see their existing setup at a glance.

Changes

File Change
hermes_cli/doctor.py Branch Mem0 check on mode — OSS path validates nested config fields
hermes_cli/memory_setup.py Default picker cursor to currently active provider
plugins/memory/mem0/_setup.py Default mode picker to current config mode; add "← current" label

Testing

$ hermes doctor
◆ Memory Provider
  ✓ Mem0 OSS configured
    → mode=oss  user_id=luna  agent_id=hermes  llm=z-ai/glm-5.2  embedder=openai/text-embedding-3-small  vector_store=qdrant

All checks passed! 🎉

Platform mode behavior is unchanged (same code path, just wrapped in else).

Supersedes #57932 (reopened with a clean, fast-forwardable history — the previous branch had an accidental merge commit).

@alt-glitch alt-glitch added type/bug Something isn't working comp/cli CLI entry point, hermes_cli/, setup wizard tool/memory Memory tool and memory providers P3 Low — cosmetic, nice to have labels Jul 6, 2026
@lunalunaa
lunalunaa force-pushed the fix/mem0-doctor-oss-mode branch from b20b49c to 73c9c09 Compare July 8, 2026 22:09
- doctor.py: branch Mem0 health check on mode — OSS validates
  oss.llm.config.api_key, oss.embedder.config.api_key, and
  oss.vector_store.provider; Platform mode unchanged (checks
  top-level api_key). Reports full config for both modes.
- memory_setup.py: pass provider instance to status display so
  is_available() reflects OSS mode correctly.
- _setup.py: default mode picker cursor to the currently
  configured mode (from mem0.json) instead of always defaulting
  to Platform. Adds '← current' label to the active mode option
  so users can see their existing setup at a glance.

Closes NousResearch#57931
Supersedes NousResearch#57932
@teknium1

Copy link
Copy Markdown
Contributor

Thanks for addressing three real state-preservation issues in the Mem0 setup flow. The two picker-default changes match current main's behavior, but the doctor branch needs correction before it is safe to salvage.

Problems

  • The added OSS check expects oss.llm.config.api_key and oss.embedder.config.api_key. The shipped wizard instead writes provider keys to .env and stores only provider/model configuration in mem0.json (plugins/memory/mem0/_setup.py:172-185, 466-468, 814-818), so wizard-created OpenAI OSS setups still fail doctor.
  • The check requires both keys even though supported Ollama LLM and embedder entries declare needs_key=False (plugins/memory/mem0/_oss_providers.py:15-20, 32-38).
  • Moving load_config() before selection invalidates the existing cancellation contract in tests/hermes_cli/test_memory_setup.py:64-76; the PR includes no test updates.

Suggested changes

  • Make doctor resolve required credentials according to the configured OSS providers and their existing .env mechanism, while allowing fully local Ollama OSS configurations.
  • Add doctor and picker-default regression coverage, including the cancellation-flow test update.

Automated hermes-sweeper review.

@teknium1 teknium1 added sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform area/memory Memory subsystem: store, providers, sync, background reviews area/install-update Installer, updater, packaging, wheels, doctor labels Jul 15, 2026
The Mem0 OSS doctor check expected api_key fields inside mem0.json's
oss.llm.config / oss.embedder.config, but the setup wizard writes
provider keys to ~/.hermes/.env (keyed by each provider's env_var) and
only stores provider/model in mem0.json.  Wizard-created OpenAI OSS
setups therefore still failed doctor.

Fix: resolve credentials per the provider registry
(_oss_providers.LLM/EMBEDDER_PROVIDERS), which is the same source of
truth the wizard uses.  A provider with needs_key=False (Ollama) needs
no credential; otherwise the key is satisfied if present in mem0.json
*or* loaded into os.environ by load_hermes_dotenv() from .env.

Also relax the cmd_setup cancellation test: load_config() is now called
before the picker to compute the default cursor position, so the old
'load_config.assert_not_called()' contract is invalid.  The invariant
that matters — no config written on cancel — is preserved.

Add regression coverage:
- doctor: OSS + OpenAI keys in .env → ok
- doctor: OSS + Ollama (needs_key=False), no keys → ok
- doctor: OSS + OpenAI, no key → fail, naming OPENAI_API_KEY
- picker: active mem0 provider → default cursor on mem0 row
- picker: no provider → default on 'Built-in only'
- picker: existing mem0.json mode=oss → default idx 2 + '← current'
- picker: no mem0.json → default idx 0, no markers

Addresses hermes-sweeper review on PR NousResearch#59865.
@lunalunaa

Copy link
Copy Markdown
Author

Addressed all three points from the review in a6070f4.

1. Doctor resolves OSS creds via provider registry + .env
The OSS check now imports LLM_PROVIDERS / EMBEDDER_PROVIDERS from plugins/memory/mem0/_oss_providers.py (the same registry the wizard uses) and resolves credentials the same way the runtime does:

  • needs_key=False providers (Ollama) require no credential.
  • needs_key=True providers pass if the key is in mem0.json or loaded into os.environ by load_hermes_dotenv() from ~/.hermes/.env — the wizard's actual write path.

So wizard-created OpenAI OSS setups (keys only in .env) now pass doctor, and fully-local Ollama configs are no longer falsely rejected.

2. Relaxed cancellation test contract
load_config() is now called before the picker to compute the default cursor position, so the old load_config.assert_not_called() assertion was invalid. Updated test_cmd_setup_top_level_cancel_writes_nothing to allow load_config while keeping the invariant that actually matters: save_config.assert_not_called().

3. Added regression coverage

  • test_oss_openai_keys_in_env_passes — keys only in .envcheck_ok (the reported bug)
  • test_oss_ollama_no_keys_anywhere_passesneeds_key=False, no keys → check_ok
  • test_oss_openai_missing_key_fails_with_env_var_hint — no key → fail, message names OPENAI_API_KEY
  • test_cmd_setup_picker_defaults_to_active_provider — active mem0 provider → cursor defaults to mem0 row
  • test_cmd_setup_picker_falls_back_to_builtin_when_no_active_provider — no provider → cursor on "Built-in only"
  • test_mem0_post_setup_picker_defaults_to_current_oss_mode — existing mem0.json with mode=oss → default idx 2 + "← current" marker
  • test_mem0_post_setup_picker_defaults_to_platform_without_existing_config — no mem0.json → default idx 0, no markers

All 82 tests in the two test files pass; ruff clean.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/install-update Installer, updater, packaging, wheels, doctor area/memory Memory subsystem: store, providers, sync, background reviews comp/cli CLI entry point, hermes_cli/, setup wizard P3 Low — cosmetic, nice to have sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades tool/memory Memory tool and memory providers type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

hermes doctor: Mem0 OSS mode falsely reports "API key not set" + setup wizard defaults to built-in

3 participants