mirror of
https://github.com/0xrsydn/nix-hermes-agent.git
synced 2026-08-07 00:53:52 +00:00
ci: fix lint glob + format nix files
This commit is contained in:
parent
c3da68363c
commit
ba6c63e9bf
4 changed files with 113 additions and 58 deletions
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
|
|
@ -16,7 +16,7 @@ jobs:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: DeterminateSystems/nix-installer-action@v13
|
- uses: DeterminateSystems/nix-installer-action@v13
|
||||||
- name: Check formatting (nixfmt)
|
- name: Check formatting (nixfmt)
|
||||||
run: nix run nixpkgs#nixfmt-rfc-style -- --check *.nix docs/*.nix tests/*.nix
|
run: find . -name '*.nix' -not -path './_*' | xargs nix run nixpkgs#nixfmt-rfc-style -- --check
|
||||||
- name: Lint (statix)
|
- name: Lint (statix)
|
||||||
run: nix run nixpkgs#statix -- check .
|
run: nix run nixpkgs#statix -- check .
|
||||||
|
|
||||||
|
|
|
||||||
15
flake.nix
15
flake.nix
|
|
@ -6,8 +6,14 @@
|
||||||
flake-utils.url = "github:numtide/flake-utils";
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = { self, nixpkgs, flake-utils }:
|
outputs =
|
||||||
flake-utils.lib.eachDefaultSystem (system:
|
{
|
||||||
|
self,
|
||||||
|
nixpkgs,
|
||||||
|
flake-utils,
|
||||||
|
}:
|
||||||
|
flake-utils.lib.eachDefaultSystem (
|
||||||
|
system:
|
||||||
let
|
let
|
||||||
pkgs = import nixpkgs { inherit system; };
|
pkgs = import nixpkgs { inherit system; };
|
||||||
in
|
in
|
||||||
|
|
@ -19,14 +25,15 @@
|
||||||
|
|
||||||
checks = import ./checks.nix {
|
checks = import ./checks.nix {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
hermes-agent = self.packages.${system}.hermes-agent;
|
inherit (self.packages.${system}) hermes-agent;
|
||||||
};
|
};
|
||||||
|
|
||||||
devShells.default = pkgs.mkShell {
|
devShells.default = pkgs.mkShell {
|
||||||
packages = [ self.packages.${system}.hermes-agent ];
|
packages = [ self.packages.${system}.hermes-agent ];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
) // {
|
)
|
||||||
|
// {
|
||||||
nixosModules = {
|
nixosModules = {
|
||||||
hermes-agent = import ./module.nix self;
|
hermes-agent = import ./module.nix self;
|
||||||
default = self.nixosModules.hermes-agent;
|
default = self.nixosModules.hermes-agent;
|
||||||
|
|
|
||||||
114
module.nix
114
module.nix
|
|
@ -1,9 +1,14 @@
|
||||||
self:
|
self:
|
||||||
{ config, lib, pkgs, ... }:
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.services.hermes-agent;
|
cfg = config.services.hermes-agent;
|
||||||
hermes-agent = self.packages.${pkgs.system}.hermes-agent;
|
inherit (self.packages.${pkgs.system}) hermes-agent;
|
||||||
|
|
||||||
# Deep-merge config type (same pattern as nix-openclaw)
|
# Deep-merge config type (same pattern as nix-openclaw)
|
||||||
deepConfigType = lib.types.mkOptionType {
|
deepConfigType = lib.types.mkOptionType {
|
||||||
|
|
@ -20,20 +25,21 @@ let
|
||||||
configFile = if cfg.configFile != null then cfg.configFile else generatedConfigFile;
|
configFile = if cfg.configFile != null then cfg.configFile else generatedConfigFile;
|
||||||
|
|
||||||
# Generate .env file from environment attrset (non-secret env vars)
|
# Generate .env file from environment attrset (non-secret env vars)
|
||||||
envFileContent = lib.concatStringsSep "\n" (
|
envFileContent = lib.concatStringsSep "\n" (lib.mapAttrsToList (k: v: "${k}=${v}") cfg.environment);
|
||||||
lib.mapAttrsToList (k: v: "${k}=${v}") cfg.environment
|
|
||||||
);
|
|
||||||
generatedEnvFile = pkgs.writeText "hermes-env" envFileContent;
|
generatedEnvFile = pkgs.writeText "hermes-env" envFileContent;
|
||||||
|
|
||||||
# Document files → symlinked into workspace
|
# Document files → symlinked into workspace
|
||||||
documentDerivation = pkgs.runCommand "hermes-documents" { } (
|
documentDerivation = pkgs.runCommand "hermes-documents" { } (
|
||||||
''
|
''
|
||||||
mkdir -p $out
|
mkdir -p $out
|
||||||
'' + lib.concatStringsSep "\n" (
|
''
|
||||||
lib.mapAttrsToList (name: value:
|
+ lib.concatStringsSep "\n" (
|
||||||
if builtins.isPath value || lib.isStorePath value
|
lib.mapAttrsToList (
|
||||||
then "cp ${value} $out/${name}"
|
name: value:
|
||||||
else "cat > $out/${name} <<'HERMES_DOC_EOF'\n${value}\nHERMES_DOC_EOF"
|
if builtins.isPath value || lib.isStorePath value then
|
||||||
|
"cp ${value} $out/${name}"
|
||||||
|
else
|
||||||
|
"cat > $out/${name} <<'HERMES_DOC_EOF'\n${value}\nHERMES_DOC_EOF"
|
||||||
) cfg.documents
|
) cfg.documents
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
@ -254,14 +260,28 @@ in
|
||||||
|
|
||||||
# ── MCP servers ──────────────────────────────────────────────────────
|
# ── MCP servers ──────────────────────────────────────────────────────
|
||||||
mcpServers = mkOption {
|
mcpServers = mkOption {
|
||||||
type = types.attrsOf (types.submodule {
|
type = types.attrsOf (
|
||||||
options = {
|
types.submodule {
|
||||||
command = mkOption { type = types.str; description = "MCP server command."; };
|
options = {
|
||||||
args = mkOption { type = types.listOf types.str; default = [ ]; };
|
command = mkOption {
|
||||||
env = mkOption { type = types.attrsOf types.str; default = { }; };
|
type = types.str;
|
||||||
timeout = mkOption { type = types.nullOr types.int; default = null; };
|
description = "MCP server command.";
|
||||||
};
|
};
|
||||||
});
|
args = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [ ];
|
||||||
|
};
|
||||||
|
env = mkOption {
|
||||||
|
type = types.attrsOf types.str;
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
timeout = mkOption {
|
||||||
|
type = types.nullOr types.int;
|
||||||
|
default = null;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
default = { };
|
default = { };
|
||||||
description = "MCP server configurations (merged into config.mcp_servers).";
|
description = "MCP server configurations (merged into config.mcp_servers).";
|
||||||
};
|
};
|
||||||
|
|
@ -270,8 +290,11 @@ in
|
||||||
config = lib.mkIf cfg.enable {
|
config = lib.mkIf cfg.enable {
|
||||||
# ── Merge MCP servers into config ────────────────────────────────────
|
# ── Merge MCP servers into config ────────────────────────────────────
|
||||||
services.hermes-agent.config = lib.mkIf (cfg.mcpServers != { }) {
|
services.hermes-agent.config = lib.mkIf (cfg.mcpServers != { }) {
|
||||||
mcp_servers = lib.mapAttrs (_name: srv:
|
mcp_servers = lib.mapAttrs (
|
||||||
{ inherit (srv) command args; }
|
_name: srv:
|
||||||
|
{
|
||||||
|
inherit (srv) command args;
|
||||||
|
}
|
||||||
// lib.optionalAttrs (srv.env != { }) { inherit (srv) env; }
|
// lib.optionalAttrs (srv.env != { }) { inherit (srv) env; }
|
||||||
// lib.optionalAttrs (srv.timeout != null) { inherit (srv) timeout; }
|
// lib.optionalAttrs (srv.timeout != null) { inherit (srv) timeout; }
|
||||||
) cfg.mcpServers;
|
) cfg.mcpServers;
|
||||||
|
|
@ -281,7 +304,7 @@ in
|
||||||
users.groups.${cfg.group} = lib.mkIf cfg.createUser { };
|
users.groups.${cfg.group} = lib.mkIf cfg.createUser { };
|
||||||
users.users.${cfg.user} = lib.mkIf cfg.createUser {
|
users.users.${cfg.user} = lib.mkIf cfg.createUser {
|
||||||
isSystemUser = true;
|
isSystemUser = true;
|
||||||
group = cfg.group;
|
inherit (cfg) group;
|
||||||
home = cfg.stateDir;
|
home = cfg.stateDir;
|
||||||
createHome = true;
|
createHome = true;
|
||||||
shell = pkgs.bashInteractive;
|
shell = pkgs.bashInteractive;
|
||||||
|
|
@ -302,19 +325,26 @@ in
|
||||||
|
|
||||||
# Seed auth file if provided (only if not already present, unless force overwrite)
|
# Seed auth file if provided (only if not already present, unless force overwrite)
|
||||||
${lib.optionalString (cfg.authFile != null) ''
|
${lib.optionalString (cfg.authFile != null) ''
|
||||||
${if cfg.authFileForceOverwrite then ''
|
${
|
||||||
install -o ${cfg.user} -g ${cfg.group} -m 0600 ${cfg.authFile} ${cfg.stateDir}/.hermes/auth.json
|
if cfg.authFileForceOverwrite then
|
||||||
'' else ''
|
''
|
||||||
if [ ! -f ${cfg.stateDir}/.hermes/auth.json ]; then
|
install -o ${cfg.user} -g ${cfg.group} -m 0600 ${cfg.authFile} ${cfg.stateDir}/.hermes/auth.json
|
||||||
install -o ${cfg.user} -g ${cfg.group} -m 0600 ${cfg.authFile} ${cfg.stateDir}/.hermes/auth.json
|
''
|
||||||
fi
|
else
|
||||||
''}
|
''
|
||||||
|
if [ ! -f ${cfg.stateDir}/.hermes/auth.json ]; then
|
||||||
|
install -o ${cfg.user} -g ${cfg.group} -m 0600 ${cfg.authFile} ${cfg.stateDir}/.hermes/auth.json
|
||||||
|
fi
|
||||||
|
''
|
||||||
|
}
|
||||||
''}
|
''}
|
||||||
|
|
||||||
# Link documents into workspace
|
# Link documents into workspace
|
||||||
${lib.concatStringsSep "\n" (lib.mapAttrsToList (name: _value: ''
|
${lib.concatStringsSep "\n" (
|
||||||
install -o ${cfg.user} -g ${cfg.group} -m 0644 ${documentDerivation}/${name} ${cfg.workingDirectory}/${name}
|
lib.mapAttrsToList (name: _value: ''
|
||||||
'') cfg.documents)}
|
install -o ${cfg.user} -g ${cfg.group} -m 0644 ${documentDerivation}/${name} ${cfg.workingDirectory}/${name}
|
||||||
|
'') cfg.documents
|
||||||
|
)}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
# ── systemd service ──────────────────────────────────────────────────
|
# ── systemd service ──────────────────────────────────────────────────
|
||||||
|
|
@ -335,16 +365,19 @@ in
|
||||||
Group = cfg.group;
|
Group = cfg.group;
|
||||||
WorkingDirectory = cfg.workingDirectory;
|
WorkingDirectory = cfg.workingDirectory;
|
||||||
|
|
||||||
EnvironmentFile =
|
EnvironmentFile = [ generatedEnvFile ] ++ cfg.environmentFiles;
|
||||||
[ generatedEnvFile ]
|
|
||||||
++ cfg.environmentFiles;
|
|
||||||
|
|
||||||
ExecStart =
|
ExecStart =
|
||||||
if cfg.execStart != null then cfg.execStart
|
if cfg.execStart != null then
|
||||||
else lib.concatStringsSep " " ([
|
cfg.execStart
|
||||||
"${cfg.package}/bin/hermes"
|
else
|
||||||
"gateway"
|
lib.concatStringsSep " " (
|
||||||
] ++ cfg.extraArgs);
|
[
|
||||||
|
"${cfg.package}/bin/hermes"
|
||||||
|
"gateway"
|
||||||
|
]
|
||||||
|
++ cfg.extraArgs
|
||||||
|
);
|
||||||
|
|
||||||
Restart = cfg.restart;
|
Restart = cfg.restart;
|
||||||
RestartSec = cfg.restartSec;
|
RestartSec = cfg.restartSec;
|
||||||
|
|
@ -365,7 +398,8 @@ in
|
||||||
pkgs.bash
|
pkgs.bash
|
||||||
pkgs.coreutils
|
pkgs.coreutils
|
||||||
pkgs.git
|
pkgs.git
|
||||||
] ++ cfg.extraPackages;
|
]
|
||||||
|
++ cfg.extraPackages;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
40
package.nix
40
package.nix
|
|
@ -1,13 +1,14 @@
|
||||||
{ lib
|
{
|
||||||
, python312Packages
|
lib,
|
||||||
, python312
|
python312Packages,
|
||||||
, fetchFromGitHub
|
python312,
|
||||||
, fetchPypi
|
fetchFromGitHub,
|
||||||
, makeWrapper
|
fetchPypi,
|
||||||
, nodejs_22
|
makeWrapper,
|
||||||
, ripgrep
|
nodejs_22,
|
||||||
, ffmpeg
|
ripgrep,
|
||||||
, git
|
ffmpeg,
|
||||||
|
git,
|
||||||
}:
|
}:
|
||||||
|
|
||||||
let
|
let
|
||||||
|
|
@ -25,7 +26,10 @@ let
|
||||||
inherit version;
|
inherit version;
|
||||||
hash = "sha256-nhwH0KYbRSqP+0jBmd5fJUPXVG8SMPYxI3BEMSfF6Tc=";
|
hash = "sha256-nhwH0KYbRSqP+0jBmd5fJUPXVG8SMPYxI3BEMSfF6Tc=";
|
||||||
};
|
};
|
||||||
build-system = with pythonPackages; [ setuptools setuptools-scm ];
|
build-system = with pythonPackages; [
|
||||||
|
setuptools
|
||||||
|
setuptools-scm
|
||||||
|
];
|
||||||
dependencies = with pythonPackages; [
|
dependencies = with pythonPackages; [
|
||||||
httpx
|
httpx
|
||||||
httpx-sse
|
httpx-sse
|
||||||
|
|
@ -45,7 +49,10 @@ let
|
||||||
inherit version;
|
inherit version;
|
||||||
hash = "sha256-b97r+UVOYrxSPVeIjlA1nme6r9sh9oYh+cFOCNwAYjo=";
|
hash = "sha256-b97r+UVOYrxSPVeIjlA1nme6r9sh9oYh+cFOCNwAYjo=";
|
||||||
};
|
};
|
||||||
build-system = with pythonPackages; [ setuptools wheel ];
|
build-system = with pythonPackages; [
|
||||||
|
setuptools
|
||||||
|
wheel
|
||||||
|
];
|
||||||
dependencies = with pythonPackages; [
|
dependencies = with pythonPackages; [
|
||||||
httpx
|
httpx
|
||||||
pydantic
|
pydantic
|
||||||
|
|
@ -166,7 +173,14 @@ pythonPackages.buildPythonApplication {
|
||||||
for bin in $out/bin/hermes $out/bin/hermes-agent $out/bin/hermes-acp; do
|
for bin in $out/bin/hermes $out/bin/hermes-agent $out/bin/hermes-acp; do
|
||||||
if [ -f "$bin" ]; then
|
if [ -f "$bin" ]; then
|
||||||
wrapProgram "$bin" \
|
wrapProgram "$bin" \
|
||||||
--prefix PATH : ${lib.makeBinPath [ nodejs_22 ripgrep ffmpeg git ]}
|
--prefix PATH : ${
|
||||||
|
lib.makeBinPath [
|
||||||
|
nodejs_22
|
||||||
|
ripgrep
|
||||||
|
ffmpeg
|
||||||
|
git
|
||||||
|
]
|
||||||
|
}
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
'';
|
'';
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue