diff options
Diffstat (limited to 'modules')
| -rw-r--r-- | modules/agent.nix | 168 | ||||
| -rw-r--r-- | modules/foundation/agent.nix | 196 | ||||
| -rw-r--r-- | modules/foundation/default.nix | 1 |
3 files changed, 197 insertions, 168 deletions
diff --git a/modules/agent.nix b/modules/agent.nix deleted file mode 100644 index 880919b..0000000 --- a/modules/agent.nix +++ /dev/null @@ -1,168 +0,0 @@ -{ config, pkgs, hermes-agent, ... }: - -{ - imports = [ - hermes-agent.nixosModules.default - ]; - - age.secrets.renard-agent = { - file = ../secrets/renard-agent.age; - owner = "renard"; - group = "renard"; - mode = "0440"; - }; - - users.groups.renard = { }; - users.users.renard = { - isSystemUser = true; - group = "renard"; - home = "/home/renard"; - createHome = true; - shell = pkgs.bashInteractive; - }; - - services.hermes-agent = { - enable = true; - - # the agent has it's own user on the host under - # which it runs and can change state at. - user = "renard"; - group = "renard"; - stateDir = "/home/renard"; - createUser = false; - - extraDependencyGroups = [ "messaging" ]; - - # packages for the agent to work with. - # it should also always be able to call `nix-shell` to gain access to more tools. - extraPackages = with pkgs; [ - nix - nixfmt-rfc-style - - openssh - tailscale - - docker_29 - - jq - yq-go - ripgrep - fd - tree - file - unzip - gnused - gawk - - curl - wget - - htop - glances - lsof - iproute2 - iputils - inetutils - - dig - tcpdump - nmap - - git - - vim - ]; - - environmentFiles = [ - # required secrets: - # * OPENROUTER_API_KEY - # * DISCORD_BOT_TOKEN - # * DISCORD_ALLOWED_USERS - config.age.secrets.renard-agent.path - ]; - - documents = { - "SOUL.md" = ../assets/agent/SOUL.md; - }; - - settings = { - model = { - provider = "openrouter"; - # my current favorite budget model, with recent price - # changes by far the cheapest for the performance, - # with other chinese models also being close. - # only modality is text, requires auxiliary vision model! - # native price: $0.44/m in, $0.87/m out. - default = "deepseek/deepseek-v4-pro"; - }; - - agent = { - reasoning_effort = "high"; # 'high' rated highest in benchmarks, tune to taste! - max_turns = 90; - }; - - auxiliary.vision = { - # auxiliary vision model for image comprehension. - # this qwen model is built for this exact use-case and is extremely - # cheap for the performance (though below gemini), however, - # it does not do any reasoning on the visual input! - # possible upgrade path for reasoning: qwen3-vl-30b-a3b-thinking - # native price: $0.13/m in, $1.56/m out. - provider = "openrouter"; - model = "qwen/qwen3-vl-32b-instruct"; - timeout = 120; - }; - - toolsets = [ "all" ]; - - terminal = { - backend = "local"; - persistent_shell = true; - timeout = 180; - }; - - memory = { - memory_enabled = true; - user_profile_enabled = true; - }; - - # slightly higher limits and targets than default for better - # long session preservation. - compression = { - enabled = true; - threshold = 0.75; - target_ratio = 0.35; - protect_last_n = 40; - }; - - # progressive message editing, a little silly in discord but looks like - # the classic llm chats. - streaming = { - enabled = true; - }; - display = { - streaming = true; # small regression with streaming.enabled, keep both on. - tool_progress = "new"; # only show fresh new tool calls, not every call. - }; - - discord = { - require_mention = false; - thread_require_mention = false; - auto_thread = false; - reactions = true; - history_backfill = true; - allow_mentions = { - everyone = false; - roles = false; - users = true; - replied_user = true; - }; - }; - - unauthorized_dm_behavior = "ignore"; # ignore strangers - - timezone = "Europe/Berlin"; - group_sessions_per_user = false; - }; - }; -} diff --git a/modules/foundation/agent.nix b/modules/foundation/agent.nix new file mode 100644 index 0000000..6ac25aa --- /dev/null +++ b/modules/foundation/agent.nix @@ -0,0 +1,196 @@ +{ + config, + pkgs, + lib, + hermes-agent, + ... +}: + +let + inherit (lib) mkEnableOption mkIf mkMerge; + cfg = config.foundation.agent; + + # the set of tools the agent has access to by default. + # it should also always be able to call `nix-shell` to gain access to more tools. + agentPackages = with pkgs; [ + nix + nixfmt-rfc-style + + openssh + tailscale + + docker_29 + + jq + yq-go + ripgrep + fd + tree + file + unzip + gnused + gawk + + curl + wget + + htop + glances + lsof + iproute2 + iputils + inetutils + + dig + tcpdump + nmap + + git + + vim + ]; +in +{ + imports = [ + hermes-agent.nixosModules.default + ]; + + options.foundation.agent = { + home = mkEnableOption "the 'renard' agent to live on this machine"; + neighbor = mkEnableOption "letting the 'renard' agent access this machine"; + }; + + config = mkMerge [ + # both the home and each neighbor have a user for the agent. + (mkIf (cfg.home || cfg.neighbor) { + users = { + groups.renard = { }; + + users.renard = { + isSystemUser = true; + group = "renard"; + home = "/home/renard"; + createHome = true; + shell = pkgs.bashInteractive; + packages = agentPackages; + }; + }; + }) + + # the agent lives at home. + (mkIf cfg.home { + age.secrets.renard-agent = { + file = ../../secrets/renard-agent.age; + owner = "renard"; + group = "renard"; + mode = "0440"; + }; + + services.hermes-agent = { + enable = true; + + user = "renard"; + group = "renard"; + stateDir = "/home/renard"; + createUser = false; + + extraDependencyGroups = [ "messaging" ]; + + # both the user and the path house the same package set + extraPackages = agentPackages; + + environmentFiles = [ + # required secrets: + # * OPENROUTER_API_KEY + # * DISCORD_BOT_TOKEN + # * DISCORD_ALLOWED_USERS + config.age.secrets.renard-agent.path + ]; + + documents = { + "SOUL.md" = ../../assets/agent/SOUL.md; + }; + + settings = { + model = { + provider = "openrouter"; + # my current favorite budget model, with recent price + # changes by far the cheapest for the performance, + # with other chinese models also being close. + # only modality is text, requires auxiliary vision model! + # native price: $0.44/m in, $0.87/m out. + default = "deepseek/deepseek-v4-pro"; + }; + + agent = { + reasoning_effort = "high"; # 'high' rated highest in benchmarks, tune to taste! + max_turns = 90; + }; + + auxiliary.vision = { + # auxiliary vision model for image comprehension. + # this qwen model is built for this exact use-case and is extremely + # cheap for the performance (though below gemini), however, + # it does not do any reasoning on the visual input! + # possible upgrade path for reasoning: qwen3-vl-30b-a3b-thinking + # native price: $0.13/m in, $1.56/m out. + provider = "openrouter"; + model = "qwen/qwen3-vl-32b-instruct"; + timeout = 120; + }; + + toolsets = [ "all" ]; + + terminal = { + backend = "local"; + persistent_shell = true; + timeout = 180; + }; + + memory = { + memory_enabled = true; + user_profile_enabled = true; + }; + + # slightly higher limits and targets than default for better + # long session preservation. + compression = { + enabled = true; + threshold = 0.75; + target_ratio = 0.35; + protect_last_n = 40; + }; + + # progressive message editing, a little silly in discord but looks like + # the classic llm chats. + streaming = { + enabled = true; + }; + display = { + streaming = true; # small regression with streaming.enabled, keep both on. + tool_progress = "new"; # only show fresh new tool calls, not every call. + }; + + discord = { + require_mention = false; + thread_require_mention = false; + auto_thread = false; + reactions = true; + history_backfill = true; + allow_mentions = { + everyone = false; + roles = false; + users = true; + replied_user = true; + }; + }; + + unauthorized_dm_behavior = "ignore"; # ignore strangers + + timezone = "Europe/Berlin"; + group_sessions_per_user = false; + }; + }; + }) + ]; +} diff --git a/modules/foundation/default.nix b/modules/foundation/default.nix index fa84750..558f80a 100644 --- a/modules/foundation/default.nix +++ b/modules/foundation/default.nix @@ -7,5 +7,6 @@ ./monitoring ./www ./vpn.nix + ./agent.nix ]; } |
