`memory.provider: builtin` (also `default`, `built-in`, `none`) selects the built-in
store, yet doctor short-circuited only on an empty name and printed
"⚠ builtin plugin not found run: hermes memory setup", and the provider migration
(`hermes update`, agent init) printed "⚠ Memory provider 'builtin' is configured but
not installed and not in the plugin catalog". update_cmd_deps and web_server_memory
each carried their own (differing) inline sentinel set.
One predicate, `agent.memory_provider.is_core_memory_provider`, now owns the sentinel
set next to the MemoryProvider ABC; doctor_state, memory_provider_migration,
update_cmd_deps, web_server_memory and agent_init's provider activation all use it.
Fixes#75647Fixes#115113
credit: @Christopher-Schulze #75679
credit: @Luna161 #83317
credit: @kokhlo #115117
credit: @KnowBotDev #115302
- voice_mode: `_import_audio` asks `pm.ensure_import("audio-io")` before importing
sounddevice, so `/voice on` turns the feature on (or reports exactly why PM
refused: lazy installs off, platform gate, restart needed) instead of printing a
`python -c "from pm import sync_venv…"` one-liner for the user to run.
- pm.plugins_state: `read_home_selection` and `dependency_homes` are the public
readers; memory_provider_migration and plugins_cmd stop importing underscored names.
- pm.store: the `sha256_file` shim is gone; the authority test asserts the Store has no
file hash of its own rather than patching one.
- tests/pm/conftest: `isolated_machine_home` is autouse (Path.home, HOME, USERPROFILE,
HERMES_HOME all under tmp_path); `@pytest.mark.real_machine_home` opts a module out
— the four suites that spawn children with a home they build themselves.
- activate / activate.ps1 / Dockerfile followed hermes_cli.runtime_paths to
pm.environments (the earlier sweep only covered .py).
- pm.registry loads builtins through importlib so a test patching `pm.packages` in
sys.modules still registers the security packages.
`import pm.ensure` bound the submodule onto the package, shadowing the facade's
`pm.ensure()` function for every later caller in the process (photon's sidecar
start hit `'module' object is not callable`). The module is pm.install now; the
function keeps its name. The facade resolves through `__import__` rather than
`importlib.import_module` so a test that patches import_module globally does not
break attribute access on pm.
tools/lazy_deps.py returns to the 16-line stop_for_relaunch shim the branch wrote
(an origin/main merge had replaced it with main's 775-line implementation); the
project-metadata tests follow. update_cmd re-exports the four old_updater_deps
names the shim tests resolve through hermes_cli.update_cmd.
Merges from origin/main resolved several files by taking main's side, which
re-inlined code paths this branch had already moved to PM. At HEAD that left:
- plugins/memory/hindsight: ImportError at module load (`_export_port_health_
grace_timeout` and `_MIN_CLIENT_VERSION` no longer exist) — the whole plugin
failed to import. Restored the side-env daemon client, folded main's
fail-closed profile-env rewrite guard into it, and dropped the version
auto-upgrade dance (the extra is pinned).
- mem0 / honcho / google_chat / memory_provider_migration / plugins_cmd_catalog:
imported the deleted tools.lazy_deps and hermes_cli.plugin_python_deps
modules; routed through pm.ensure_import / pm.sync_venv / pm.plugins_state.
scripts/ci/check_lazy_deps_imports.py exits 0 again.
- tools/skills_hub: the PLUGIN-COMPAT __getattr__ had been moved above
`_plugin_compat_prev_getattr = __getattr__`, so `SKILLS_DIR` recursed forever.
- tools/tirith_security: `import time` dropped; the circuit breaker NameError'd.
- hermes_cli/local_runtime/binaries: json/platform/os used without imports;
the manifest.json scan was for a layout PM no longer writes — the boot gate
now asks PM for an installed engine.
Built-in memory providers are moving to their maintainers' repos and the plugin catalog. Their
name, memory.<name> config section, data directory and tool names stay the same, so the only
thing a user on the built-in form loses is the code path. Two hooks now fetch it:
- hermes update: every profile home sharing the venv whose memory.provider resolves nowhere gets
the catalog plugin installed at its reviewed pin (kill list, dependency constraints, enable).
- agent init: when the provider resolves nowhere, one attempt per process (Desktop users never
run `hermes update` by hand); honours security.allow_lazy_installs.
Offline / not in the catalog: a warning with the exact one-liner instead of DEBUG-only silence.
Also accepts `owner/repo#subdir` for plugin installs (the catalog's spelling; honcho ships its
plugin in a subdirectory of its main repo).
Live: bundled honcho removed, memory.provider=honcho, catalog entry staged → AIAgent() installs
plugins/honcho from plastic-labs/honcho#hermes-plugin-honcho with deps and loads it; config kept.