From 7126524e8d0b8108693176bb58d2b31c76ec3cd3 Mon Sep 17 00:00:00 2001 From: Siddharth Balyan <52913345+alt-glitch@users.noreply.github.com> Date: Thu, 26 Mar 2026 04:16:29 +0530 Subject: [PATCH] remove config drift check for nix (#3061) --- nix/checks.nix | 81 ++++---------- nix/config-keys.json | 129 ---------------------- website/docs/getting-started/nix-setup.md | 4 +- 3 files changed, 25 insertions(+), 189 deletions(-) delete mode 100644 nix/config-keys.json diff --git a/nix/checks.nix b/nix/checks.nix index 4af5d5521..6dd5115c9 100644 --- a/nix/checks.nix +++ b/nix/checks.nix @@ -12,7 +12,31 @@ }; configMergeScript = pkgs.callPackage ./configMergeScript.nix { }; + + # Auto-generated config key reference — always in sync with Python + configKeys = pkgs.runCommand "hermes-config-keys" {} '' + set -euo pipefail + export HOME=$TMPDIR + ${hermesVenv}/bin/python3 -c ' +import json, sys +from hermes_cli.config import DEFAULT_CONFIG + +def leaf_paths(d, prefix=""): + paths = [] + for k, v in sorted(d.items()): + path = f"{prefix}.{k}" if prefix else k + if isinstance(v, dict) and v: + paths.extend(leaf_paths(v, path)) + else: + paths.append(path) + return paths + +json.dump(sorted(leaf_paths(DEFAULT_CONFIG)), sys.stdout, indent=2) +' > $out + ''; in { + packages.configKeys = configKeys; + checks = lib.optionalAttrs pkgs.stdenv.hostPlatform.isLinux { # Verify binaries exist and are executable package-contents = pkgs.runCommand "hermes-package-contents" { } '' @@ -101,63 +125,6 @@ echo "ok" > $out/result ''; - # ── Config drift detection ──────────────────────────────────────── - # Extracts leaf key paths from Python's DEFAULT_CONFIG and compares - # against the committed reference in nix/config-keys.json. - config-drift = pkgs.runCommand "hermes-config-drift" { - nativeBuildInputs = [ pkgs.jq ]; - referenceKeys = ./config-keys.json; - } '' - set -e - export HOME=$(mktemp -d) - - echo "=== Extracting DEFAULT_CONFIG leaf keys from Python ===" - ${hermesVenv}/bin/python3 -c ' -import json, sys -from hermes_cli.config import DEFAULT_CONFIG - -def leaf_paths(d, prefix=""): - paths = [] - for k, v in sorted(d.items()): - path = f"{prefix}.{k}" if prefix else k - if isinstance(v, dict) and v: - paths.extend(leaf_paths(v, path)) - else: - paths.append(path) - return paths - -json.dump(sorted(leaf_paths(DEFAULT_CONFIG)), sys.stdout) -' > /tmp/actual-keys.json - - echo "=== Comparing against reference ===" - jq -r '.[]' $referenceKeys | sort > /tmp/reference.txt - jq -r '.[]' /tmp/actual-keys.json | sort > /tmp/actual.txt - - ADDED=$(comm -23 /tmp/actual.txt /tmp/reference.txt || true) - REMOVED=$(comm -13 /tmp/actual.txt /tmp/reference.txt || true) - FAILED=false - - if [ -n "$ADDED" ]; then - echo "FAIL: New keys in DEFAULT_CONFIG not in nix/config-keys.json:" - echo "$ADDED" | sed 's/^/ + /' - FAILED=true - fi - if [ -n "$REMOVED" ]; then - echo "FAIL: Keys in nix/config-keys.json missing from DEFAULT_CONFIG:" - echo "$REMOVED" | sed 's/^/ - /' - FAILED=true - fi - - if [ "$FAILED" = "true" ]; then - exit 1 - fi - - ACTUAL_COUNT=$(wc -l < /tmp/actual.txt) - echo "PASS: All $ACTUAL_COUNT config keys match reference" - mkdir -p $out - echo "ok" > $out/result - ''; - # ── Config merge + round-trip test ──────────────────────────────── # Tests the merge script (Nix activation behavior) across 7 # scenarios, then verifies Python's load_config() reads correctly. diff --git a/nix/config-keys.json b/nix/config-keys.json deleted file mode 100644 index 327958fbb..000000000 --- a/nix/config-keys.json +++ /dev/null @@ -1,129 +0,0 @@ -[ - "_config_version", - "agent.max_turns", - "approvals.mode", - "auxiliary.approval.api_key", - "auxiliary.approval.base_url", - "auxiliary.approval.model", - "auxiliary.approval.provider", - "auxiliary.compression.api_key", - "auxiliary.compression.base_url", - "auxiliary.compression.model", - "auxiliary.compression.provider", - "auxiliary.flush_memories.api_key", - "auxiliary.flush_memories.base_url", - "auxiliary.flush_memories.model", - "auxiliary.flush_memories.provider", - "auxiliary.mcp.api_key", - "auxiliary.mcp.base_url", - "auxiliary.mcp.model", - "auxiliary.mcp.provider", - "auxiliary.session_search.api_key", - "auxiliary.session_search.base_url", - "auxiliary.session_search.model", - "auxiliary.session_search.provider", - "auxiliary.skills_hub.api_key", - "auxiliary.skills_hub.base_url", - "auxiliary.skills_hub.model", - "auxiliary.skills_hub.provider", - "auxiliary.vision.api_key", - "auxiliary.vision.base_url", - "auxiliary.vision.model", - "auxiliary.vision.provider", - "auxiliary.vision.timeout", - "auxiliary.web_extract.api_key", - "auxiliary.web_extract.base_url", - "auxiliary.web_extract.model", - "auxiliary.web_extract.provider", - "browser.command_timeout", - "browser.inactivity_timeout", - "browser.record_sessions", - "checkpoints.enabled", - "checkpoints.max_snapshots", - "command_allowlist", - "compression.enabled", - "compression.protect_last_n", - "compression.summary_base_url", - "compression.summary_model", - "compression.summary_provider", - "compression.target_ratio", - "compression.threshold", - "delegation.api_key", - "delegation.base_url", - "delegation.model", - "delegation.provider", - "discord.auto_thread", - "discord.free_response_channels", - "discord.require_mention", - "display.bell_on_complete", - "display.compact", - "display.personality", - "display.resume_display", - "display.show_cost", - "display.show_reasoning", - "display.skin", - "display.streaming", - "honcho", - "human_delay.max_ms", - "human_delay.min_ms", - "human_delay.mode", - "memory.memory_char_limit", - "memory.memory_enabled", - "memory.user_char_limit", - "memory.user_profile_enabled", - "model", - "personalities", - "prefill_messages_file", - "privacy.redact_pii", - "quick_commands", - "security.redact_secrets", - "security.tirith_enabled", - "security.tirith_fail_open", - "security.tirith_path", - "security.tirith_timeout", - "security.website_blocklist.domains", - "security.website_blocklist.enabled", - "security.website_blocklist.shared_files", - "smart_model_routing.cheap_model", - "smart_model_routing.enabled", - "smart_model_routing.max_simple_chars", - "smart_model_routing.max_simple_words", - "stt.enabled", - "stt.local.model", - "stt.openai.model", - "stt.provider", - "terminal.backend", - "terminal.container_cpu", - "terminal.container_disk", - "terminal.container_memory", - "terminal.container_persistent", - "terminal.cwd", - "terminal.daytona_image", - "terminal.docker_forward_env", - "terminal.docker_image", - "terminal.docker_mount_cwd_to_workspace", - "terminal.docker_volumes", - "terminal.env_passthrough", - "terminal.modal_image", - "terminal.persistent_shell", - "terminal.singularity_image", - "terminal.timeout", - "timezone", - "toolsets", - "tts.edge.voice", - "tts.elevenlabs.model_id", - "tts.elevenlabs.voice_id", - "tts.neutts.device", - "tts.neutts.model", - "tts.neutts.ref_audio", - "tts.neutts.ref_text", - "tts.openai.model", - "tts.openai.voice", - "tts.provider", - "voice.auto_tts", - "voice.max_recording_seconds", - "voice.record_key", - "voice.silence_duration", - "voice.silence_threshold", - "whatsapp" -] diff --git a/website/docs/getting-started/nix-setup.md b/website/docs/getting-started/nix-setup.md index 2adec8b41..8bd192405 100644 --- a/website/docs/getting-started/nix-setup.md +++ b/website/docs/getting-started/nix-setup.md @@ -196,7 +196,7 @@ Both are deep-merged at evaluation time. Nix-declared keys always win over keys ::: :::tip Discovering available config keys -The full set of config keys is defined in [`nix/config-keys.json`](https://github.com/NousResearch/hermes-agent/blob/main/nix/config-keys.json) (127 leaf keys). You can paste your existing `config.yaml` into the `settings` attrset — the structure maps 1:1. The build-time `config-drift` check catches any drift between the reference and the Python source. +Run `nix build .#configKeys && cat result` to see every leaf config key extracted from Python's `DEFAULT_CONFIG`. You can paste your existing `config.yaml` into the `settings` attrset — the structure maps 1:1. :::
@@ -607,7 +607,6 @@ nix build .#checks.x86_64-linux.entry-points-sync # pyproject.toml ↔ Nix pack nix build .#checks.x86_64-linux.cli-commands # gateway/config subcommands nix build .#checks.x86_64-linux.managed-guard # HERMES_MANAGED blocks mutation nix build .#checks.x86_64-linux.bundled-skills # skills present in package -nix build .#checks.x86_64-linux.config-drift # config keys match Python source nix build .#checks.x86_64-linux.config-roundtrip # merge script preserves user keys ``` @@ -621,7 +620,6 @@ nix build .#checks.x86_64-linux.config-roundtrip # merge script preserves use | `cli-commands` | `hermes --help` exposes `gateway` and `config` subcommands | | `managed-guard` | `HERMES_MANAGED=true hermes config set ...` prints the NixOS error | | `bundled-skills` | Skills directory exists, contains SKILL.md files, `HERMES_BUNDLED_SKILLS` is set in wrapper | -| `config-drift` | Leaf keys extracted from Python's `DEFAULT_CONFIG` match the committed `nix/config-keys.json` reference | | `config-roundtrip` | 7 merge scenarios: fresh install, Nix override, user key preservation, mixed merge, MCP additive merge, nested deep merge, idempotency |