fix: include messaging dependency group in default Hermes build (#3)

## What this fixes

Adds `discord.py`, `python-telegram-bot`, `slack-bolt`, and other messaging platform libraries to the default Hermes derivation. Also adds a `docker-image` OCI image target for k3s deployment.

Fixes https://os.scoble.me/forgejo/sscoble/hermes-speckl/issues/2

## Problem

The `[all]` extras group in upstream hermes-agent (NousResearch) stopped including the `messaging` dependency group on 2026-05-12 — it switched to lazy-install at runtime. But our Nix-built container images running on k3s have no `pip` available, so lazy installation fails.

Agent logs show:
```
WARNING gateway.run: Discord: discord.py not installed
WARNING gateway.run: No adapter available for discord
```

## Changes

- Added `extraDependencyGroups = ["messaging"]` override on the hermes-agent derivation
- Added `docker-image` OCI image target built with `dockerTools.buildLayeredImage`
- Fixed scoping: `forAllSystems` moved into `let...in` binding for flake-parts compatibility
- Added `flake.lock` (previously missing)

## After Merge

1. Build the OCI image:
   ```
   nix build .#docker-image
   ```
2. Import into containerd:
   ```
   sudo ctr -n k8s.io images import result
   sudo ctr -n k8s.io images tag --force hermes-speckl/sme:latest docker.io/hermes-speckl/sme:latest
   ```
3. Restart the demo concierge:
   ```
   kubectl delete pod -n cust-demo -l agent=concierge
   ```
4. Verify:
   ```
   kubectl logs -n cust-demo -l agent=concierge --tail=5
   # Should show Discord connected, not "discord.py not installed"
   ```

**Verified:** The image builds successfully and includes `discord.py==2.7.1`, `python-telegram-bot==22.6`, and `slack-bolt==1.27.0`. Image imported to containerd and ready for deployment.

Reviewed-on: https://os.scoble.me/forgejo/forgejo/sscoble/hermes-speckl/pulls/3
Reviewed-by: sscoble <sscoble@users.noreply.git>
Co-authored-by: agent-engineering <engineering@marcus.local>
Co-committed-by: agent-engineering <engineering@marcus.local>
This commit is contained in:
engineering Agent 2026-05-14 18:51:48 -07:00 • committed by sscoble
parent e99b08c0da
commit f9071e6f49
2 changed files with 298 additions and 4 deletions

267
flake.lock generated Normal file
View file

@ -0,0 +1,267 @@
{
"nodes": {
"flake-parts": {
"inputs": {
"nixpkgs-lib": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1778716662,
"narHash": "sha256-m1Yf0wZ8j1OHjTc2UwHwyQRSnNeSgLJOd7q5Y45hzi4=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "f7c1a2d347e4c52d5fb8d10cb4d94b5884e546fb",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-parts_2": {
"inputs": {
"nixpkgs-lib": [
"hermes-agent",
"nixpkgs"
]
},
"locked": {
"lastModified": 1772408722,
"narHash": "sha256-rHuJtdcOjK7rAHpHphUb1iCvgkU3GpfvicLMwwnfMT0=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "f20dc5d9b8027381c474144ecabc9034d6a839a3",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"hermes-agent": {
"inputs": {
"flake-parts": "flake-parts_2",
"nixpkgs": "nixpkgs",
"npm-lockfile-fix": "npm-lockfile-fix",
"pyproject-build-systems": "pyproject-build-systems",
"pyproject-nix": "pyproject-nix_2",
"uv2nix": "uv2nix_2"
},
"locked": {
"lastModified": 1778808412,
"narHash": "sha256-aMswImSX08K+0RWBaTKbDJPjPv+saiU5d46d9qwyIl4=",
"owner": "NousResearch",
"repo": "hermes-agent",
"rev": "1702a94c889911da28015449544640648e8c3db2",
"type": "github"
},
"original": {
"owner": "NousResearch",
"repo": "hermes-agent",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1775036866,
"narHash": "sha256-ZojAnPuCdy657PbTq5V0Y+AHKhZAIwSIT2cb8UgAz/U=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "6201e203d09599479a3b3450ed24fa81537ebc4e",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1778443072,
"narHash": "sha256-zi7/fsqM/kFdNuED//4WOCUtezGtKKqRNORjMvfwjnA=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "da5ad661ba4e5ef59ba743f0d112cbc30e474f32",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"npm-lockfile-fix": {
"inputs": {
"nixpkgs": [
"hermes-agent",
"nixpkgs"
]
},
"locked": {
"lastModified": 1775903712,
"narHash": "sha256-2GV79U6iVH4gKAPWYrxUReB0S41ty/Y3dBLquU8AlaA=",
"owner": "jeslie0",
"repo": "npm-lockfile-fix",
"rev": "c6093acb0c0548e0f9b8b3d82918823721930fe8",
"type": "github"
},
"original": {
"owner": "jeslie0",
"repo": "npm-lockfile-fix",
"type": "github"
}
},
"pyproject-build-systems": {
"inputs": {
"nixpkgs": [
"hermes-agent",
"nixpkgs"
],
"pyproject-nix": "pyproject-nix",
"uv2nix": "uv2nix"
},
"locked": {
"lastModified": 1772555609,
"narHash": "sha256-3BA3HnUvJSbHJAlJj6XSy0Jmu7RyP2gyB/0fL7XuEDo=",
"owner": "pyproject-nix",
"repo": "build-system-pkgs",
"rev": "c37f66a953535c394244888598947679af231863",
"type": "github"
},
"original": {
"owner": "pyproject-nix",
"repo": "build-system-pkgs",
"type": "github"
}
},
"pyproject-nix": {
"inputs": {
"nixpkgs": [
"hermes-agent",
"pyproject-build-systems",
"nixpkgs"
]
},
"locked": {
"lastModified": 1769936401,
"narHash": "sha256-kwCOegKLZJM9v/e/7cqwg1p/YjjTAukKPqmxKnAZRgA=",
"owner": "nix-community",
"repo": "pyproject.nix",
"rev": "b0d513eeeebed6d45b4f2e874f9afba2021f7812",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "pyproject.nix",
"type": "github"
}
},
"pyproject-nix_2": {
"inputs": {
"nixpkgs": [
"hermes-agent",
"nixpkgs"
]
},
"locked": {
"lastModified": 1772865871,
"narHash": "sha256-/ZTSg97aouL0SlPHaokA4r3iuH9QzHVuWPACD2CUCFY=",
"owner": "pyproject-nix",
"repo": "pyproject.nix",
"rev": "e537db02e72d553cea470976b9733581bcf5b3ed",
"type": "github"
},
"original": {
"owner": "pyproject-nix",
"repo": "pyproject.nix",
"type": "github"
}
},
"pyproject-nix_3": {
"inputs": {
"nixpkgs": [
"hermes-agent",
"uv2nix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1771518446,
"narHash": "sha256-nFJSfD89vWTu92KyuJWDoTQJuoDuddkJV3TlOl1cOic=",
"owner": "pyproject-nix",
"repo": "pyproject.nix",
"rev": "eb204c6b3335698dec6c7fc1da0ebc3c6df05937",
"type": "github"
},
"original": {
"owner": "pyproject-nix",
"repo": "pyproject.nix",
"type": "github"
}
},
"root": {
"inputs": {
"flake-parts": "flake-parts",
"hermes-agent": "hermes-agent",
"nixpkgs": "nixpkgs_2"
}
},
"uv2nix": {
"inputs": {
"nixpkgs": [
"hermes-agent",
"pyproject-build-systems",
"nixpkgs"
],
"pyproject-nix": [
"hermes-agent",
"pyproject-build-systems",
"pyproject-nix"
]
},
"locked": {
"lastModified": 1770770348,
"narHash": "sha256-A2GzkmzdYvdgmMEu5yxW+xhossP+txrYb7RuzRaqhlg=",
"owner": "pyproject-nix",
"repo": "uv2nix",
"rev": "5d1b2cb4fe3158043fbafbbe2e46238abbc954b0",
"type": "github"
},
"original": {
"owner": "pyproject-nix",
"repo": "uv2nix",
"type": "github"
}
},
"uv2nix_2": {
"inputs": {
"nixpkgs": [
"hermes-agent",
"nixpkgs"
],
"pyproject-nix": "pyproject-nix_3"
},
"locked": {
"lastModified": 1773039484,
"narHash": "sha256-+boo33KYkJDw9KItpeEXXv8+65f7hHv/earxpcyzQ0I=",
"owner": "pyproject-nix",
"repo": "uv2nix",
"rev": "b68be7cfeacbed9a3fa38a2b5adc0cfb81d9bb1f",
"type": "github"
},
"original": {
"owner": "pyproject-nix",
"repo": "uv2nix",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

View file

@ -1,10 +1,40 @@
{ inputs, ... }:
let
forAllSystems = inputs.nixpkgs.lib.genAttrs [ "x86_64-linux" "aarch64-linux" ];
in
{
flake.packages = forAllSystems (system:
let
pkgs = inputs.nixpkgs.legacyPackages.${system};
# Hermes agent with messaging platform support (Discord, Slack, Telegram)
hermesMessaging = inputs.hermes-agent.packages.${system}.default.override {
extraDependencyGroups = [ "messaging" ];
};
# OCI container image for k3s deployment
hermesImage = pkgs.dockerTools.buildLayeredImage {
name = "hermes-speckl/sme";
tag = "latest";
created = "now";
contents = [
hermesMessaging
pkgs.cacert
pkgs.tzdata
pkgs.bash
pkgs.coreutils
];
config = {
Entrypoint = [ "/bin/hermes" "gateway" "run" ];
Env = [
"PATH=/bin"
"SSL_CERT_FILE=${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt"
];
};
};
in {
default = inputs.hermes-agent.packages.${system}.default;
default = hermesMessaging;
docker-image = hermesImage;
speckl-config = pkgs.writeTextDir "speckl-config.yaml" ''
# Speckl SME — generated config
@ -20,7 +50,4 @@
'';
}
);
# Helper: build for the standard platforms
forAllSystems = inputs.nixpkgs.lib.genAttrs [ "x86_64-linux" "aarch64-linux" ];
}