This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

machines.coaxmetal.hermes: hermes-notify through the gateway webhook, regenerate hermes-env on script changes

+69 -22
+7 -15
machines/coaxmetal/hermes-voice.nix
··· 8 8 let 9 9 port = 8790; 10 10 # The gateway's webhook platform (hermes.nix), loopback only. 11 - webhookPort = 8644; 11 + webhookPort = config.services.hermes-agent.settings.platforms.webhook.extra.port; 12 12 in 13 13 { 14 14 # hermes-voice (tools/hermes-voice): live voice conversations with Hermes ··· 88 88 services.hermes-agent.environment.HERMES_VOICE_URL = "http://localhost:${toString port}"; 89 89 90 90 # How hermes-voice asks for an approval when no call can hear it: a 91 - # deliver_only route posts the text to the Matrix home room through the 92 - # gateway, no agent turn. Signed with WEBHOOK_SECRET, which is the API 93 - # server key (hermes-env in hermes.nix), so no secret is added. 94 - services.hermes-agent.settings.platforms.webhook = { 95 - enabled = true; 96 - extra = { 97 - host = "127.0.0.1"; 98 - port = webhookPort; 99 - routes.voice-approval = { 100 - deliver = "matrix"; 101 - deliver_only = true; 102 - prompt = "{text}"; 103 - }; 104 - }; 91 + # deliver_only route on the gateway's webhook platform (hermes.nix) posts 92 + # the text to the Matrix home room, no agent turn. 93 + services.hermes-agent.settings.platforms.webhook.extra.routes.voice-approval = { 94 + deliver = "matrix"; 95 + deliver_only = true; 96 + prompt = "{text}"; 105 97 }; 106 98 107 99 # OpenAI project key with GPT-Live access; billed per second of open voice
+62 -7
machines/coaxmetal/hermes.nix
··· 42 42 ''; 43 43 }; 44 44 45 + # The gateway's webhook platform (settings.platforms.webhook below), 46 + # loopback only. 47 + webhookPort = 8644; 48 + 49 + # Post a message to the Matrix home room through the running gateway: the 50 + # "notify" webhook route below hands it to the gateway's own Matrix adapter. 51 + # For the agent's shell scripts (phonetpm heads-ups, background deploys). 52 + # `hermes send -t matrix` is no substitute: outside the gateway it opens a 53 + # second Matrix client on the gateway's device and crypto store, and the two 54 + # desync the Olm sessions until no client can decrypt Hermes any more. 55 + hermes-notify = pkgs.writeShellApplication { 56 + name = "hermes-notify"; 57 + runtimeInputs = [ 58 + pkgs.coreutils 59 + pkgs.curl 60 + pkgs.gnused 61 + pkgs.jq 62 + pkgs.openssl 63 + ]; 64 + text = '' 65 + if [ $# -eq 0 ]; then 66 + echo "usage: hermes-notify <message>" >&2 67 + exit 2 68 + fi 69 + secret=$(sed -n 's/^WEBHOOK_SECRET=//p' "''${HERMES_HOME:-/var/lib/hermes/.hermes}/.env") 70 + body=$(jq -cn --arg text "$*" '{text: $text}') 71 + stamp=$(date +%s) 72 + signature=$(printf '%s.%s' "$stamp" "$body" | openssl dgst -sha256 -hmac "$secret" -r | cut -d' ' -f1) 73 + curl -fsS --max-time 30 -o /dev/null \ 74 + -H 'Content-Type: application/json' \ 75 + -H "X-Webhook-Timestamp: $stamp" \ 76 + -H "X-Webhook-Signature-V2: $signature" \ 77 + --data-binary "$body" \ 78 + http://127.0.0.1:${toString webhookPort}/webhooks/notify 79 + ''; 80 + }; 81 + 45 82 in 46 83 { 47 84 imports = [ ··· 90 127 pkgs.curl 91 128 # ssh through the phonetpm agent (SSH_AUTH_SOCK below). 92 129 pkgs.openssh 130 + hermes-notify 93 131 ]; 94 132 95 133 # Home Assistant (acheron, configs/hass) left hermes core for the ··· 223 261 # EMAIL_PASSWORD, EMAIL_IMAP_HOST and EMAIL_SMTP_HOST are set 224 262 # (gateway/config_env.py); only an explicit `enabled: false` stops that. 225 263 settings.platforms.email.enabled = false; 264 + 265 + # deliver_only routes post their rendered prompt to the Matrix home room 266 + # through the gateway, no agent turn. Signed with WEBHOOK_SECRET, the API 267 + # server key again (hermes-env). hermes-voice.nix adds voice-approval. 268 + settings.platforms.webhook = { 269 + enabled = true; 270 + extra = { 271 + host = "127.0.0.1"; 272 + port = webhookPort; 273 + routes.notify = { 274 + deliver = "matrix"; 275 + deliver_only = true; 276 + prompt = "{text}"; 277 + }; 278 + }; 279 + }; 226 280 227 281 # The one shared calendar (configs/radicale.nix): lass's own events, the 228 282 # book.lassul.us requests and bookings, and anything Hermes adds. Hermes ··· 368 422 # deps are present (they are) and keeps the crypto store under 369 423 # /var/lib/hermes/.hermes/platforms/matrix/store/. 370 424 MATRIX_E2EE_MODE = "optional"; 371 - # Clients now exclude devices their owner did not cross-sign (MSC4153, 372 - # Element/SchildiChat Next): they show such a device's messages as 373 - # undecryptable and withhold their own room keys from it. With this set 374 - # the adapter bootstraps cross-signing once (no master key on the 375 - # account yet) and signs its device; the key is written here 0600 and 376 - # never overwritten. Move it into pass afterwards; it is needed only to 377 - # cross-sign a new device id (MATRIX_RECOVERY_KEY). 425 + # Element is moving to exclude devices their owner did not cross-sign 426 + # (MSC4153). With this set the adapter bootstraps cross-signing once (no 427 + # master key on the account yet) and signs its device; the key is 428 + # written here 0600 and never overwritten. Move it into pass afterwards; 429 + # it is needed only to cross-sign a new device id (MATRIX_RECOVERY_KEY). 378 430 MATRIX_RECOVERY_KEY_OUTPUT_FILE = "/var/lib/hermes/.hermes/matrix-recovery-key"; 379 431 # Optional defense-in-depth (confine to specific rooms; DMs are exempt): 380 432 # MATRIX_ALLOWED_ROOMS = "!yourRoomId:lassul.us"; ··· 570 622 "hermes-homeassistant" 571 623 ]; 572 624 files."hermes.env" = { }; 625 + # clan regenerates a var only when its validation changes, not when the 626 + # script does: without this a key added below never reaches the .env. 627 + validation.script = builtins.hashString "sha256" config.clan.core.vars.generators.hermes-env.script; 573 628 runtimeInputs = [ pkgs.coreutils ]; 574 629 script = '' 575 630 cat > "$out/hermes.env" <<EOF