{ pkgs, lib, config, ... }: let
hermes-agent = import ./package.nix;
in {
imports = [
./container-service
];
home.packages = [
hermes-agent
];
home.shellAliases.hermes-tui = "hermes --tui";
yq-merge.".hermes/config.yaml" = {
generator = builtins.toJSON;
yqExtraArgs = "-P";
expr = {
model = {
default = config.ai.minimax-china.default_large_model_id;
provider = "minimax-cn";
base_url = config.ai.minimax-china.api_endpoint;
};
# the avaliable fields see: <hermes-agent>/hermes_cli/config.py: _normalize_custom_provider_entry
providers = {
jw-claude = {
name = "JW Claude";
api = config.ai.jw-claude.api_endpoint;
api_key = config.ai.jw-claude.api_key;
transport = "anthropic_messages";
};
jw-codex = {
name = "JW Codex";
api = config.ai.jw-codex.api_endpoint;
api_key = config.ai.jw-codex.api_key;
transport = "codex_responses";
models."${config.ai.jw-codex.default_large_model_id}".context_length
= config.ai.jw-codex.models."${config.ai.jw-codex.default_large_model_id}".context_window;
models."${config.ai.jw-codex.default_small_model_id}".context_length
= config.ai.jw-codex.models."${config.ai.jw-codex.default_small_model_id}".context_window;
};
};
compression = {
enabled = true;
threshold = 0.8;
};
web = {
backend = "tavily";
search_backend = "tavily";
extract_backend = "tavily";
};
# CLI vs TUI
# CLI
# - Cons
# - No session selection UI
# - Does not support `/background`: the `/background` behavior is the same as /queue
# TUI
# - Cons
# - The providers/models selection UI does not filter out un-configured providers.
# - The scroll sometimes jump/glitch
# - Does not respect tool_preview_length = 0
display = {
show_reasoning = true;
# The hermes verbose does not output gracefully: the newline is printde as "\n"!
tool_progress = "all";
tool_preview_length = 0; # unlimited
tui_compact = false;
streaming = true;
final_response_markdown = "render";
};
mcp_servers = {
ddgs = { inherit (config.ai.mcp.ddgs) command args; };
};
};
};
yq-merge.".hermes/.env" = {
generator = lib.generators.toKeyValue {};
yqExtraArgs = "-p=props -o=props --properties-separator='='";
expr = {
KIMI_API_KEY = config.ai.kimi.api_key;
MINIMAX_CN_API_KEY = config.ai.minimax-china.api_key;
TAVILY_API_KEY = config.ai.tavily.api_key;
};
};
# zsh completion via fpath (not eval, which breaks _arguments)
# https://github.com/NousResearch/hermes-agent/issues/6122
home.file."zsh-completions/_hermes" = {
target = ".zsh/completions/_hermes";
source = pkgs.runCommand "hermes-zsh-completion" {} ''
${hermes-agent}/bin/hermes completion zsh > $out
'';
};
programs.zsh.initContent = lib.mkBefore ''
fpath+=("$HOME/.zsh/completions")
'';
home.file.".hermes/memories/USER.md".source = config.lib.file.mkOutOfStoreSymlink ~/Gist/Data/hermes/memories/USER.md;
home.file.".hermes/memories/MEMORY.md".source = config.lib.file.mkOutOfStoreSymlink ~/Gist/Data/hermes/memories/MEMORY.md;
home.file.".hermes/skills".source = config.lib.file.mkOutOfStoreSymlink ~/Gist/Data/hermes/skills;
home.file.".hermes/skill-bundles".source = config.lib.file.mkOutOfStoreSymlink ~/Gist/Data/hermes/skill-bundles;
}