# Mnemosyne memory provider for Hermes on mars — packaged for real (Nix). # # Why derivations instead of a runtime side-venv: the official Hermes image # vendors its own Python and stays off-limits to pip (no pip module, PEP 668), # and a runtime venv built host-side breaks twice over inside the container: # the venv's pyvenv.cfg records a /nix/store python home the container never # mounts, and a plugins symlink with an absolute host path points nowhere # from /opt/data. Building here means nothing is fetched at boot, nothing # under the provider's control is writable from inside the container, and # the closure is as reproducible as the rest of the host. # # Package set (one shared site-packages — the plugin wrapper imports its # sibling `mnemosyne` core package, so withPackages, not separate envs): # # mnemosyne-memory core engine: SQLite/FTS5 storage, recall, tools. # Base deps only (PyYAML); the optional extras (llm, # embeddings via fastembed/onnxruntime, mcp, sync) are # deliberately NOT pulled — recall uses the bundled FTS5 # lexical path, and the heavyweight ML stack (~hundreds of # MB, live network on first vector use) buys nothing for # a first deployment. Adding the embeddings extra later # is pinning fastembed + sqlite-vec here. # mnemosyne-hermes the wrapper Hermes discovers under $HERMES_HOME/plugins # (installs itself as package `hermes_memory_provider`). # Hard dependency: mnemosyne-memory, PyYAML. # # Platform note: both sdists are pure Python (build no C extensions), so # nothing here constrains the host arch beyond the interpreter itself. { python3, fetchPypi, }: let python = python3; mnemosyneMemory = python.pkgs.buildPythonPackage rec { pname = "mnemosyne-memory"; version = "3.15.1"; pyproject = true; src = fetchPypi { inherit pname version; sha256 = "sha256-lspUMxc0pUSkhSUrNdiiO5OJ1NMC/S853EYSanXtXKM="; }; build-system = with python.pkgs; [ setuptools ]; # Base dependency set — everything else in the upstream metadata is an # optional extra (llm / embeddings / mcp / sync / test / dev) and is not # installed; see the file-level comment. dependencies = with python.pkgs; [ pyyaml ]; doCheck = false; # upstream tests want a live Hermes + LLM key present pythonImportsCheck = [ "mnemosyne" ]; }; mnemosyneHermes = python.pkgs.buildPythonPackage rec { pname = "mnemosyne-hermes"; version = "0.5.0"; pyproject = true; src = fetchPypi { inherit pname version; sha256 = "sha256-CzEvnUw5oPFtT5bHQQ/GBdy2C/E7qShQn32irIRYKqw="; }; build-system = with python.pkgs; [ setuptools ]; # The wrapper declares `mnemosyne-memory[embeddings]>=3.11.1` on PyPI, but # the embeddings extra is only consulted when vector recall is enabled # (see above) — pass the core dependency explicitly rather than dragging # in onnxruntime for nothing. dependencies = [ mnemosyneMemory ] ++ (with python.pkgs; [ pyyaml ]); doCheck = false; pythonImportsCheck = [ "hermes_memory_provider" ]; }; # The exposed value is the python env itself (a store path mounted :ro). # Hermes only needs the site-packages dir inside it; `sitePackages` is a # passthru the python interpreter derivation (and hence withPackages envs) # exposes, so the caller uses `${env.sitePackages}` instead of guessing # the python version in a path literal. in python.withPackages (_: [ mnemosyneMemory mnemosyneHermes ])