Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fa7937fc64 |
+24
-61
@@ -11,6 +11,14 @@
|
||||
|
||||
configMergeScript = pkgs.callPackage ./configMergeScript.nix { };
|
||||
|
||||
mkCheck = name: attrs: script:
|
||||
pkgs.runCommand name attrs (''
|
||||
set -e
|
||||
'' + script + ''
|
||||
mkdir -p $out
|
||||
echo "ok" > $out/result
|
||||
'');
|
||||
|
||||
# Auto-generated config key reference — always in sync with Python
|
||||
configKeys = pkgs.runCommand "hermes-config-keys" {} ''
|
||||
set -euo pipefail
|
||||
@@ -49,35 +57,28 @@ json.dump(sorted(leaf_paths(DEFAULT_CONFIG)), sys.stdout, indent=2)
|
||||
results = map (sys: { inherit sys; result = tryEvalPkg sys; }) targetSystems;
|
||||
failures = builtins.filter (r: !r.result.success) results;
|
||||
failMsg = lib.concatMapStringsSep "\n" (r: " - ${r.sys}") failures;
|
||||
in pkgs.runCommand "hermes-cross-eval" { } (
|
||||
in mkCheck "hermes-cross-eval" { } (
|
||||
if failures != [] then
|
||||
throw "Package fails to evaluate on:\n${failMsg}"
|
||||
else ''
|
||||
echo "PASS: package evaluates on all ${toString (builtins.length targetSystems)} platforms"
|
||||
mkdir -p $out
|
||||
echo "ok" > $out/result
|
||||
''
|
||||
);
|
||||
|
||||
# Verify the default package builds successfully (cross-platform).
|
||||
# On Linux the runtime checks below already depend on the package,
|
||||
# but this ensures darwin builders also build it during flake check.
|
||||
build-package = pkgs.runCommand "hermes-build-package" { } ''
|
||||
build-package = mkCheck "hermes-build-package" { } ''
|
||||
echo "PASS: package built at ${hermes-agent}"
|
||||
mkdir -p $out
|
||||
echo "ok" > $out/result
|
||||
'';
|
||||
|
||||
# Verify the devShell builds successfully (cross-platform).
|
||||
build-devshell = pkgs.runCommand "hermes-build-devshell" { } ''
|
||||
build-devshell = mkCheck "hermes-build-devshell" { } ''
|
||||
echo "PASS: devShell built at ${self'.devShells.default}"
|
||||
mkdir -p $out
|
||||
echo "ok" > $out/result
|
||||
'';
|
||||
} // lib.optionalAttrs pkgs.stdenv.hostPlatform.isLinux {
|
||||
# Verify binaries exist and are executable
|
||||
package-contents = pkgs.runCommand "hermes-package-contents" { } ''
|
||||
set -e
|
||||
package-contents = mkCheck "hermes-package-contents" { } ''
|
||||
echo "=== Checking binaries ==="
|
||||
test -x ${hermes-agent}/bin/hermes || (echo "FAIL: hermes binary missing"; exit 1)
|
||||
test -x ${hermes-agent}/bin/hermes-agent || (echo "FAIL: hermes-agent binary missing"; exit 1)
|
||||
@@ -88,26 +89,20 @@ json.dump(sorted(leaf_paths(DEFAULT_CONFIG)), sys.stdout, indent=2)
|
||||
echo "PASS: Version check"
|
||||
|
||||
echo "=== All checks passed ==="
|
||||
mkdir -p $out
|
||||
echo "ok" > $out/result
|
||||
'';
|
||||
|
||||
# Verify every pyproject.toml [project.scripts] entry has a wrapped binary
|
||||
entry-points-sync = pkgs.runCommand "hermes-entry-points-sync" { } ''
|
||||
set -e
|
||||
entry-points-sync = mkCheck "hermes-entry-points-sync" { } ''
|
||||
echo "=== Checking entry points match pyproject.toml [project.scripts] ==="
|
||||
for bin in hermes hermes-agent hermes-acp; do
|
||||
test -x ${hermes-agent}/bin/$bin || (echo "FAIL: $bin binary missing from Nix package"; exit 1)
|
||||
echo "PASS: $bin present"
|
||||
done
|
||||
|
||||
mkdir -p $out
|
||||
echo "ok" > $out/result
|
||||
'';
|
||||
|
||||
# Verify CLI subcommands are accessible
|
||||
cli-commands = pkgs.runCommand "hermes-cli-commands" { } ''
|
||||
set -e
|
||||
cli-commands = mkCheck "hermes-cli-commands" { } ''
|
||||
export HOME=$(mktemp -d)
|
||||
|
||||
echo "=== Checking hermes --help ==="
|
||||
@@ -116,13 +111,10 @@ json.dump(sorted(leaf_paths(DEFAULT_CONFIG)), sys.stdout, indent=2)
|
||||
echo "PASS: All subcommands accessible"
|
||||
|
||||
echo "=== All CLI checks passed ==="
|
||||
mkdir -p $out
|
||||
echo "ok" > $out/result
|
||||
'';
|
||||
|
||||
# Verify bundled skills are present in the package
|
||||
bundled-skills = pkgs.runCommand "hermes-bundled-skills" { } ''
|
||||
set -e
|
||||
bundled-skills = mkCheck "hermes-bundled-skills" { } ''
|
||||
echo "=== Checking bundled skills ==="
|
||||
test -d ${hermes-agent}/share/hermes-agent/skills || (echo "FAIL: skills directory missing"; exit 1)
|
||||
echo "PASS: skills directory exists"
|
||||
@@ -147,13 +139,10 @@ json.dump(sorted(leaf_paths(DEFAULT_CONFIG)), sys.stdout, indent=2)
|
||||
echo "PASS: $OPT_COUNT optional skills found, HERMES_OPTIONAL_SKILLS set in wrapper"
|
||||
|
||||
echo "=== All bundled skills checks passed ==="
|
||||
mkdir -p $out
|
||||
echo "ok" > $out/result
|
||||
'';
|
||||
|
||||
# Verify bundled plugins (platforms, memory, context_engine) are present
|
||||
bundled-plugins = pkgs.runCommand "hermes-bundled-plugins" { } ''
|
||||
set -e
|
||||
bundled-plugins = mkCheck "hermes-bundled-plugins" { } ''
|
||||
echo "=== Checking bundled plugins ==="
|
||||
test -d ${hermes-agent}/share/hermes-agent/plugins || (echo "FAIL: plugins directory missing"; exit 1)
|
||||
echo "PASS: plugins directory exists"
|
||||
@@ -167,15 +156,12 @@ json.dump(sorted(leaf_paths(DEFAULT_CONFIG)), sys.stdout, indent=2)
|
||||
echo "PASS: HERMES_BUNDLED_PLUGINS set in wrapper"
|
||||
|
||||
echo "=== All bundled plugins checks passed ==="
|
||||
mkdir -p $out
|
||||
echo "ok" > $out/result
|
||||
'';
|
||||
|
||||
# Verify bundled i18n locale catalogs are present and resolvable.
|
||||
# Regression for #23943 / #27632 / #35374 — sealed Nix venvs dropped
|
||||
# locales/, surfacing raw i18n keys like gateway.reset.header_default.
|
||||
bundled-locales = pkgs.runCommand "hermes-bundled-locales" { } ''
|
||||
set -e
|
||||
bundled-locales = mkCheck "hermes-bundled-locales" { } ''
|
||||
echo "=== Checking bundled locales ==="
|
||||
test -d ${hermes-agent}/share/hermes-agent/locales || (echo "FAIL: locales directory missing"; exit 1)
|
||||
echo "PASS: locales directory exists"
|
||||
@@ -215,13 +201,10 @@ json.dump(sorted(leaf_paths(DEFAULT_CONFIG)), sys.stdout, indent=2)
|
||||
echo "PASS: sealed venv resolves locales via data-files without the env var"
|
||||
|
||||
echo "=== All bundled locales checks passed ==="
|
||||
mkdir -p $out
|
||||
echo "ok" > $out/result
|
||||
'';
|
||||
|
||||
# Verify bundled TUI is present and compiled
|
||||
bundled-tui = pkgs.runCommand "hermes-bundled-tui" { } ''
|
||||
set -e
|
||||
bundled-tui = mkCheck "hermes-bundled-tui" { } ''
|
||||
echo "=== Checking bundled TUI ==="
|
||||
test -d ${hermes-agent}/ui-tui || (echo "FAIL: ui-tui directory missing"; exit 1)
|
||||
echo "PASS: ui-tui directory exists"
|
||||
@@ -236,14 +219,11 @@ json.dump(sorted(leaf_paths(DEFAULT_CONFIG)), sys.stdout, indent=2)
|
||||
echo "PASS: HERMES_TUI_DIR set in wrapper"
|
||||
|
||||
echo "=== All bundled TUI checks passed ==="
|
||||
mkdir -p $out
|
||||
echo "ok" > $out/result
|
||||
'';
|
||||
|
||||
# Verify HERMES_NODE is set in wrapper and points to Node 20+
|
||||
# (string-width uses the /v regex flag which requires Node 20+)
|
||||
hermes-node = pkgs.runCommand "hermes-node-version" { } ''
|
||||
set -e
|
||||
hermes-node = mkCheck "hermes-node-version" { } ''
|
||||
echo "=== Checking HERMES_NODE in wrapper ==="
|
||||
grep -q "HERMES_NODE" ${hermes-agent}/bin/hermes || \
|
||||
(echo "FAIL: HERMES_NODE not set in wrapper"; exit 1)
|
||||
@@ -259,13 +239,10 @@ json.dump(sorted(leaf_paths(DEFAULT_CONFIG)), sys.stdout, indent=2)
|
||||
echo "PASS: Node v$NODE_MAJOR >= 20"
|
||||
|
||||
echo "=== All HERMES_NODE checks passed ==="
|
||||
mkdir -p $out
|
||||
echo "ok" > $out/result
|
||||
'';
|
||||
|
||||
# Verify HERMES_MANAGED guard works on all mutation commands
|
||||
managed-guard = pkgs.runCommand "hermes-managed-guard" { } ''
|
||||
set -e
|
||||
managed-guard = mkCheck "hermes-managed-guard" { } ''
|
||||
export HOME=$(mktemp -d)
|
||||
|
||||
check_blocked() {
|
||||
@@ -281,8 +258,6 @@ json.dump(sorted(leaf_paths(DEFAULT_CONFIG)), sys.stdout, indent=2)
|
||||
check_blocked "config edit" ${hermes-agent}/bin/hermes config edit
|
||||
|
||||
echo "=== All guard checks passed ==="
|
||||
mkdir -p $out
|
||||
echo "ok" > $out/result
|
||||
'';
|
||||
|
||||
# Verify extraPythonPackages PYTHONPATH injection
|
||||
@@ -291,8 +266,7 @@ json.dump(sorted(leaf_paths(DEFAULT_CONFIG)), sys.stdout, indent=2)
|
||||
hermesWithExtra = hermes-agent.override {
|
||||
extraPythonPackages = [ testPkg ];
|
||||
};
|
||||
in pkgs.runCommand "hermes-extra-python-packages" { } ''
|
||||
set -e
|
||||
in mkCheck "hermes-extra-python-packages" { } ''
|
||||
echo "=== Checking extraPythonPackages PYTHONPATH injection ==="
|
||||
|
||||
grep -q "PYTHONPATH" ${hermesWithExtra}/bin/hermes || \
|
||||
@@ -310,8 +284,6 @@ json.dump(sorted(leaf_paths(DEFAULT_CONFIG)), sys.stdout, indent=2)
|
||||
echo "PASS: base package clean"
|
||||
|
||||
echo "=== All extraPythonPackages checks passed ==="
|
||||
mkdir -p $out
|
||||
echo "ok" > $out/result
|
||||
'';
|
||||
|
||||
# Verify extraDependencyGroups passes through to python.nix
|
||||
@@ -319,8 +291,7 @@ json.dump(sorted(leaf_paths(DEFAULT_CONFIG)), sys.stdout, indent=2)
|
||||
hermesWithGroups = hermes-agent.override {
|
||||
extraDependencyGroups = [ "honcho" ];
|
||||
};
|
||||
in pkgs.runCommand "hermes-extra-dependency-groups" { } ''
|
||||
set -e
|
||||
in mkCheck "hermes-extra-dependency-groups" { } ''
|
||||
echo "=== Checking extraDependencyGroups override evaluates ==="
|
||||
|
||||
# Eval-only: verify the override produces valid derivation paths
|
||||
@@ -331,21 +302,16 @@ json.dump(sorted(leaf_paths(DEFAULT_CONFIG)), sys.stdout, indent=2)
|
||||
echo "PASS: extraDependencyGroups override evaluates cleanly"
|
||||
|
||||
echo "=== All extraDependencyGroups checks passed ==="
|
||||
mkdir -p $out
|
||||
echo "ok" > $out/result
|
||||
'';
|
||||
|
||||
# Regression guard: messaging deps live outside [all], so the
|
||||
# #messaging variant must actually ship discord.py — otherwise
|
||||
# `nix profile install .#messaging` regresses to the broken default.
|
||||
messaging-variant = pkgs.runCommand "hermes-messaging-variant" { } ''
|
||||
set -e
|
||||
messaging-variant = mkCheck "hermes-messaging-variant" { } ''
|
||||
echo "=== Checking discord.py importable from messaging variant ==="
|
||||
${self'.packages.messaging.hermesVenv}/bin/python3 -c \
|
||||
"import discord; print(discord.__version__)"
|
||||
echo "PASS: discord.py importable from messaging variant venv"
|
||||
mkdir -p $out
|
||||
echo "ok" > $out/result
|
||||
'';
|
||||
|
||||
# ── Config merge + round-trip test ────────────────────────────────
|
||||
@@ -408,10 +374,9 @@ json.dump(sorted(leaf_paths(DEFAULT_CONFIG)), sys.stdout, indent=2)
|
||||
- USER_VAR
|
||||
'';
|
||||
|
||||
in pkgs.runCommand "hermes-config-roundtrip" {
|
||||
in mkCheck "hermes-config-roundtrip" {
|
||||
nativeBuildInputs = [ pkgs.jq ];
|
||||
} ''
|
||||
set -e
|
||||
export HOME=$(mktemp -d)
|
||||
ERRORS=""
|
||||
|
||||
@@ -558,8 +523,6 @@ json.dump(load_config(), sys.stdout, default=str)
|
||||
|
||||
echo ""
|
||||
echo "=== All 7 merge scenarios passed ==="
|
||||
mkdir -p $out
|
||||
echo "ok" > $out/result
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
+8
-1
@@ -1,5 +1,5 @@
|
||||
# nix/tui.nix — Hermes TUI (Ink/React) compiled with tsc and bundled
|
||||
{ pkgs, hermesNpmLib, ... }:
|
||||
{ pkgs, lib, hermesNpmLib, ... }:
|
||||
let
|
||||
npm = hermesNpmLib.mkNpmPassthru {
|
||||
dirs = [
|
||||
@@ -35,4 +35,11 @@ pkgs.buildNpmPackage (npm // {
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
meta = with lib; {
|
||||
description = "Ink/React terminal user interface for Hermes Agent";
|
||||
homepage = "https://github.com/NousResearch/hermes-agent";
|
||||
license = licenses.mit;
|
||||
platforms = platforms.unix;
|
||||
};
|
||||
})
|
||||
|
||||
+8
-1
@@ -1,5 +1,5 @@
|
||||
# nix/web.nix — Hermes Web Dashboard (Vite/React) frontend build
|
||||
{ pkgs, hermesNpmLib, ... }:
|
||||
{ pkgs, lib, hermesNpmLib, ... }:
|
||||
let
|
||||
# @hermes/shared ships as a file: workspace dep of web, so its source
|
||||
# must be in the filtered src tree too.
|
||||
@@ -38,4 +38,11 @@ pkgs.buildNpmPackage (npm // {
|
||||
cp -r web/dist $out
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
meta = with lib; {
|
||||
description = "Web dashboard frontend for Hermes Agent";
|
||||
homepage = "https://github.com/NousResearch/hermes-agent";
|
||||
license = licenses.mit;
|
||||
platforms = platforms.unix;
|
||||
};
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user