Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion config/hermes/hydrate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ if [ -z "$CLIPROXY_API_KEY" ]; then
CLIPROXY_API_KEY="$(read_secret "${SECRETS_DIR}/cliproxy-key")"
fi

TELEGRAM_TOKEN="${TELEGRAM_TOKEN:-$(read_secret "${SECRETS_DIR}/telegram-token")}"
TELEGRAM_TOKEN="${HERMES_TELEGRAM_TOKEN:-${TELEGRAM_TOKEN:-$(read_secret "${SECRETS_DIR}/telegram-token")}}"
GATEWAY_TOKEN="${HERMES_GATEWAY_TOKEN:-${GATEWAY_TOKEN:-$(read_secret "${SECRETS_DIR}/gateway-token")}}"
WHATSAPP_ALLOW_FROM="${WHATSAPP_ALLOW_FROM:-$(read_secret "${SECRETS_DIR}/whatsapp-allow-from")}"

Expand Down
10 changes: 9 additions & 1 deletion home-manager/services/hermes/activate.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
# Create Hermes directories with correct permissions
# Create Hermes directories and install runtime deps
# Usage: activate.sh <home_dir>
set -euo pipefail
HOME_DIR="$1"
Expand All @@ -11,3 +11,11 @@ mkdir -p "$HOME_DIR/.hermes/memories"
mkdir -p "$HOME_DIR/.hermes/skills"
mkdir -p "$HOME_DIR/.hermes/cron"
chmod 700 "$HOME_DIR/.hermes"

# Install hermes gateway runtime deps from pyproject.toml dependency group
HERMES_VENV="$HOME_DIR/ghq/github.com/NousResearch/hermes-agent/.venv"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The path to the virtual environment is hardcoded to a specific ghq directory structure. This makes the script brittle if the repository is cloned elsewhere. Consider allowing this path to be overridden via an environment variable to improve portability.

Suggested change
HERMES_VENV="$HOME_DIR/ghq/github.com/NousResearch/hermes-agent/.venv"
HERMES_VENV="${HERMES_VENV_PATH:-$HOME_DIR/ghq/github.com/NousResearch/hermes-agent/.venv}"

if [ -d "$HERMES_VENV" ]; then
uv pip install --python "$HERMES_VENV/bin/python" \
--group hermes \
--project "$HOME_DIR/dotfiles" 2>/dev/null || true
Comment on lines +18 to +20

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Silencing stderr with 2>/dev/null makes it difficult to diagnose failures during the dependency installation (e.g., if uv is missing, the network is down, or there are version conflicts). It is better to allow the error output to be visible, especially since the exit code is already safely ignored with || true. Additionally, the --project path is hardcoded to ~/dotfiles; using an environment variable would make this more flexible.

Suggested change
uv pip install --python "$HERMES_VENV/bin/python" \
--group hermes \
--project "$HOME_DIR/dotfiles" 2>/dev/null || true
uv pip install --python "$HERMES_VENV/bin/python" \
--group hermes \
--project "${DOTFILES_DIR:-$HOME_DIR/dotfiles}" || true

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Do not silence and ignore uv pip install failures; this can leave Hermes missing runtime dependencies while activation appears successful.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At home-manager/services/hermes/activate.sh, line 20:

<comment>Do not silence and ignore `uv pip install` failures; this can leave Hermes missing runtime dependencies while activation appears successful.</comment>

<file context>
@@ -11,3 +11,11 @@ mkdir -p "$HOME_DIR/.hermes/memories"
+if [ -d "$HERMES_VENV" ]; then
+  uv pip install --python "$HERMES_VENV/bin/python" \
+    --group hermes \
+    --project "$HOME_DIR/dotfiles" 2>/dev/null || true
+fi
</file context>
Suggested change
--project "$HOME_DIR/dotfiles" 2>/dev/null || true
--project "$HOME_DIR/dotfiles"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Next uv sync on hermes-agent will undo this install.

Upstream NousResearch/hermes-agent's pyproject.toml only declares python-telegram-bot[webhooks]>=22.6,<23 under the optional [messaging] (and [termux]) extras — croniter is already a core dep. Meanwhile scripts/update-local-binaries.sh:223 runs a bare uv sync against the hermes-agent repo, and uv sync removes packages that aren't in the project's pyproject by default (verified locally: a uv sync after uv pip install python-telegram-bot removed it: - python-telegram-bot==22.7, - httpx, - httpcore, ...).

So the runtime sequence becomes:

  1. ulb builds the venv → no python-telegram-bot (the messaging extra wasn't requested).
  2. home-manager switch → this script reinstalls python-telegram-bot.
  3. User runs ulb again for any reason → uv sync strips python-telegram-bot.
  4. systemd starts hermes-gateway → import fails, Restart=always + StartLimitBurst=10 kicks in until it stops.

Until the user remembers to re-run home-manager switch, the gateway is dead. Cleaner long-term fix: pass --extra messaging to the uv sync call inside scripts/update-local-binaries.sh for the hermes-agent build (and drop this whole install block + the hermes group from pyproject.toml). Alternative: add an ExecStartPre to home-manager/services/hermes/default.nix that re-runs this install before each gateway start.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Silent failure hides every install error.

With 2>/dev/null || true, all of the following exit 0 with zero output:

  • uv not on PATH (verified: PATH=/usr/bin:/bin bash -c 'uv pip install ... 2>/dev/null || true' → exit 0, nothing printed even though uv: command not found fired on stderr).
  • Network unreachable.
  • Resolver/version conflicts (e.g. if hermes-agent later pins an incompatible version).
  • The existing exclude-newer = "1 week" parse warning that uv 0.8.x emits on this repo's pyproject.toml (visible in dry-run).

When hermes-gateway later crashes due to missing deps, there will be nothing in the home-manager activation log to point at the cause.

Compare to the codebase's own pattern in home-manager/modules/uv-globals/install-uv-globals.sh:24-27, 70:

if ! command -v uv &>/dev/null; then
  echo "uv not found, skipping uv globals install"
  exit 0
fi
...
uv tool install "$pkg" ... 2>/dev/null || echo "Failed to install $pkg, skipping..."

Suggested change here: drop the 2>/dev/null and replace || true with || echo "[hermes] failed to install runtime deps" >&2, plus an explicit command -v uv guard. That keeps the script non-fatal but lets the user see why nothing was installed.

fi
26 changes: 26 additions & 0 deletions home-manager/services/hermes/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,30 @@ lib.mkIf host.isKyber {
WantedBy = [ "default.target" ];
};
};

systemd.user.services.hermes-dashboard = {
Unit = {
Description = "Hermes dashboard";
After = [ "network-online.target" ];
Wants = [ "network-online.target" ];
StartLimitIntervalSec = 300;
StartLimitBurst = 10;
};
Service = {
Type = "simple";
ExecStart = "${homeDir}/.local/bin/hermes dashboard --host 0.0.0.0 --port 9119 --no-open --insecure";
Restart = "always";
RestartSec = "5s";
Environment = [
"HOME=${homeDir}"
"PATH=${homeDir}/.local/bin:${homeDir}/.nix-profile/bin:/usr/local/bin:/usr/bin:/bin"
];
WorkingDirectory = "${homeDir}/.hermes";
StandardOutput = "append:/tmp/hermes/hermes-dashboard.log";
StandardError = "append:/tmp/hermes/hermes-dashboard.log";
};
Install = {
WantedBy = [ "default.target" ];
};
};
}
7 changes: 7 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ tools = [
"vllm>=0.20.0",
"vllm-mlx>=0.2.9",
]
# Hermes gateway runtime deps - installed into hermes venv via uv pip install
hermes = [
"python-telegram-bot[webhooks]>=22.6,<23",
"croniter>=6.0.0,<7",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

croniter is already a core dep of hermes-agent.

Upstream NousResearch/hermes-agent's pyproject.toml lists croniter>=6.0.0,<7 as a core dependency (the project explicitly notes "croniter is now a core dependency; this extra kept for back-compat"). So uv sync against the hermes-agent repo will always install it — the line here just creates a second version pin that has to be kept in sync with upstream.

The only dep that genuinely benefits from this declarative install path is python-telegram-bot[webhooks], since it lives in upstream's optional [messaging] (and [termux]) extras and is therefore not installed by a bare uv sync.

Safe to drop just this line. Even better: switch the build to uv sync --extra messaging in scripts/update-local-binaries.sh and remove the whole hermes group + the install block in activate.sh (see the other comment).

Suggested change
"croniter>=6.0.0,<7",
hermes = [
"python-telegram-bot[webhooks]>=22.6,<23",
]

"fastapi[standard]>=0.115.0",
"uvicorn>=0.30.0",
]

[tool.uv]
exclude-newer = "1 week"
Expand Down
Loading