diff --git a/website/docs/getting-started/nix-setup.md b/website/docs/getting-started/nix-setup.md index e2bcd9dd68..4b3ec74918 100644 --- a/website/docs/getting-started/nix-setup.md +++ b/website/docs/getting-started/nix-setup.md @@ -599,6 +599,93 @@ The `preStart` script creates a GC root at `${stateDir}/.gc-root` pointing to th --- +## Plugins + +The NixOS module supports declarative plugin installation — no imperative `hermes plugins install` needed. + +### Directory Plugins (`extraPlugins`) + +For plugins that are just a source tree with `plugin.yaml` + `__init__.py` (e.g., [hermes-lcm](https://github.com/stephenschoettler/hermes-lcm)): + +```nix +services.hermes-agent.extraPlugins = [ + (pkgs.fetchFromGitHub { + owner = "stephenschoettler"; + repo = "hermes-lcm"; + rev = "v0.7.0"; + hash = "sha256-..."; + }) +]; +``` + +Plugins are symlinked into `$HERMES_HOME/plugins/` at activation time. Hermes discovers them via its normal directory scan. Removing a plugin from the list and running `nixos-rebuild switch` removes the symlink. + +### Entry-Point Plugins (`extraPythonPackages`) + +For pip-packaged plugins that register via `[project.entry-points."hermes_agent.plugins"]` (e.g., [rtk-hermes](https://github.com/ogallotti/rtk-hermes)): + +```nix +services.hermes-agent.extraPythonPackages = [ + (pkgs.python312Packages.buildPythonPackage { + pname = "rtk-hermes"; + version = "1.0.0"; + src = pkgs.fetchFromGitHub { + owner = "ogallotti"; + repo = "rtk-hermes"; + rev = "v1.0.0"; + hash = "sha256-..."; + }; + format = "pyproject"; + build-system = [ pkgs.python312Packages.setuptools ]; + }) +]; +``` + +The package's `site-packages` is added to PYTHONPATH in the hermes wrapper. `importlib.metadata` discovers the entry point at session start. + +### Combining Both + +A directory plugin with third-party Python dependencies needs both options: + +```nix +services.hermes-agent = { + extraPlugins = [ my-plugin-src ]; # plugin source + extraPythonPackages = [ pkgs.python312Packages.redis ]; # its Python dep + extraPackages = [ pkgs.redis ]; # system binary it needs +}; +``` + +### Using the Overlay + +External flakes can override the package directly: + +```nix +{ + inputs.hermes-agent.url = "github:NousResearch/hermes-agent"; + outputs = { hermes-agent, nixpkgs, ... }: { + nixpkgs.overlays = [ hermes-agent.overlays.default ]; + # Then: pkgs.hermes-agent.override { extraPythonPackages = [...]; } + }; +} +``` + +### Plugin Configuration + +Plugins still need to be enabled in `config.yaml`. Add them via the declarative settings: + +```nix +services.hermes-agent.settings.plugins.enabled = [ + "hermes-lcm" + "rtk-rewrite" +]; +``` + +:::note +A build-time collision check prevents plugin packages from shadowing core hermes dependencies. If a plugin provides a package already in the sealed venv, `nixos-rebuild` fails with a clear error. +::: + +--- + ## Development ### Dev Shell @@ -721,6 +808,8 @@ nix build .#checks.x86_64-linux.config-roundtrip # merge script preserves use |---|---|---|---| | `extraArgs` | `listOf str` | `[]` | Extra args for `hermes gateway` | | `extraPackages` | `listOf package` | `[]` | Extra packages on service PATH (native mode only) | +| `extraPlugins` | `listOf package` | `[]` | Directory plugin packages to symlink into `$HERMES_HOME/plugins/`. Each must contain `plugin.yaml` | +| `extraPythonPackages` | `listOf package` | `[]` | Python packages added to PYTHONPATH for entry-point plugin discovery. Build with `python312Packages` | | `restart` | `str` | `"always"` | systemd `Restart=` policy | | `restartSec` | `int` | `5` | systemd `RestartSec=` value | diff --git a/website/docs/guides/build-a-hermes-plugin.md b/website/docs/guides/build-a-hermes-plugin.md index 4e2ee5cf26..3d6524af50 100644 --- a/website/docs/guides/build-a-hermes-plugin.md +++ b/website/docs/guides/build-a-hermes-plugin.md @@ -633,6 +633,43 @@ pip install hermes-plugin-calculator # Plugin auto-discovered on next hermes startup ``` +### Distribute for NixOS + +NixOS users can install your plugin declaratively if you provide a `pyproject.toml` with entry points: + +**Entry-point plugins** (recommended for distribution): +```nix +# User's configuration.nix +services.hermes-agent.extraPythonPackages = [ + (pkgs.python312Packages.buildPythonPackage { + pname = "my-plugin"; + version = "1.0.0"; + src = pkgs.fetchFromGitHub { + owner = "you"; + repo = "hermes-my-plugin"; + rev = "v1.0.0"; + hash = "sha256-..."; # nix-prefetch-url --unpack + }; + format = "pyproject"; + build-system = [ pkgs.python312Packages.setuptools ]; + }) +]; +``` + +**Directory plugins** (no `pyproject.toml` needed): +```nix +services.hermes-agent.extraPlugins = [ + (pkgs.fetchFromGitHub { + owner = "you"; + repo = "hermes-my-plugin"; + rev = "v1.0.0"; + hash = "sha256-..."; + }) +]; +``` + +See the [Nix Setup guide](/docs/getting-started/nix-setup#plugins) for complete documentation including overlay usage and collision checking. + ## Common mistakes **Handler doesn't return JSON string:** diff --git a/website/docs/user-guide/features/plugins.md b/website/docs/user-guide/features/plugins.md index 32d401f44b..7010ca637f 100644 --- a/website/docs/user-guide/features/plugins.md +++ b/website/docs/user-guide/features/plugins.md @@ -99,6 +99,7 @@ Project-local plugins under `./.hermes/plugins/` are disabled by default. Enable | User | `~/.hermes/plugins/` | Personal plugins | | Project | `.hermes/plugins/` | Project-specific plugins (requires `HERMES_ENABLE_PROJECT_PLUGINS=true`) | | pip | `hermes_agent.plugins` entry_points | Distributed packages | +| Nix | `services.hermes-agent.extraPlugins` / `extraPythonPackages` | NixOS declarative installs — see [Nix Setup](/docs/getting-started/nix-setup#plugins) | Later sources override earlier ones on name collision, so a user plugin with the same name as a bundled plugin replaces it. @@ -155,6 +156,23 @@ Hermes has three kinds of plugins: Memory providers and context engines are **provider plugins** — only one of each type can be active at a time. General plugins can be enabled in any combination. +## NixOS declarative plugins + +On NixOS, plugins can be installed declaratively via the module options — no `hermes plugins install` needed. See the **[Nix Setup guide](/docs/getting-started/nix-setup#plugins)** for full details. + +```nix +services.hermes-agent = { + # Directory plugin (source tree with plugin.yaml) + extraPlugins = [ (pkgs.fetchFromGitHub { ... }) ]; + # Entry-point plugin (pip package) + extraPythonPackages = [ (pkgs.python312Packages.buildPythonPackage { ... }) ]; + # Enable in config + settings.plugins.enabled = [ "my-plugin" ]; +}; +``` + +Declarative plugins are symlinked with a `nix-managed-` prefix — they coexist with manually installed plugins and are cleaned up automatically when removed from the Nix config. + ## Managing plugins ```bash