This repository has no description
0

Configure Feed

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

superconfig / machines / coaxmetal / hermes-voice.nix
3.2 kB 94 lines
1{ 2 config, 3 lib, 4 pkgs, 5 self, 6 ... 7}: 8let 9 port = 8790; 10in 11{ 12 # hermes-voice (tools/hermes-voice): live voice conversations with Hermes 13 # through OpenAI's gpt-live-1. Runs next to Hermes so its API key never 14 # leaves this host; reachable over retiolum and publicly as 15 # https://voice.lassul.us through neoprism (configs/hermes-proxy.nix). 16 # 17 # SECURITY: the page drives Hermes, which has terminal tools and code 18 # execution as lass (machines/coaxmetal/hermes.nix). The access token below 19 # is the gate on every API route; treat it like the hermes-api key. 20 systemd.services.hermes-voice = { 21 description = "hermes-voice: live voice conversations with Hermes"; 22 wantedBy = [ "multi-user.target" ]; 23 wants = [ "network-online.target" ]; 24 after = [ 25 "network-online.target" 26 "hermes-agent.service" 27 ]; 28 serviceConfig = { 29 ExecStart = lib.escapeShellArgs [ 30 (lib.getExe self.packages.${pkgs.stdenv.hostPlatform.system}.hermes-voice) 31 "--listen" 32 "[::]:${toString port}" 33 # The API server binds the retiolum address (hermes.nix), not 34 # loopback; traffic to the host's own address goes through lo. 35 "--hermes-url" 36 "http://${config.networking.hostName}.r:8642" 37 "--hermes-key-file" 38 "%d/hermes-key" 39 "--openai-key-file" 40 "%d/openai-key" 41 "--access-token-file" 42 "%d/access-token" 43 ]; 44 LoadCredential = [ 45 "hermes-key:${config.clan.core.vars.generators.hermes-api.files."api_key".path}" 46 "openai-key:${config.clan.core.vars.generators.hermes-voice-openai.files."api-key".path}" 47 "access-token:${config.clan.core.vars.generators.hermes-voice.files."access-token".path}" 48 ]; 49 DynamicUser = true; 50 Restart = "on-failure"; 51 CapabilityBoundingSet = ""; 52 NoNewPrivileges = true; 53 PrivateDevices = true; 54 PrivateTmp = true; 55 ProtectHome = true; 56 ProtectSystem = "strict"; 57 ProtectKernelTunables = true; 58 ProtectKernelModules = true; 59 ProtectControlGroups = true; 60 RestrictAddressFamilies = [ 61 "AF_INET" 62 "AF_INET6" 63 ]; 64 RestrictNamespaces = true; 65 LockPersonality = true; 66 SystemCallArchitectures = "native"; 67 }; 68 }; 69 70 # Only retiolum: neoprism's proxy and devices on the mesh. Every other 71 # interface keeps the default DROP (configs/default.nix). 72 networking.firewall.interfaces.retiolum.allowedTCPPorts = [ port ]; 73 74 # OpenAI project key with GPT-Live access; billed per second of open voice 75 # session. persist=true so the prompt value is stored once. 76 clan.core.vars.generators.hermes-voice-openai.prompts.api-key = { 77 description = "OpenAI API key for hermes-voice (gpt-live-1)"; 78 type = "hidden"; 79 persist = true; 80 }; 81 82 # What the page sends as its bearer token. Read it out for the phone with 83 # clan vars get coaxmetal hermes-voice/access-token 84 clan.core.vars.generators.hermes-voice = { 85 files."access-token" = { }; 86 runtimeInputs = [ 87 pkgs.coreutils 88 pkgs.openssl 89 ]; 90 script = '' 91 openssl rand -hex 32 | tr -d '\n' > "$out/access-token" 92 ''; 93 }; 94}