Switch memory provider to hindsight
Check Flake / check-flake (push) Successful in 21m43s

This commit is contained in:
2026-06-04 10:32:17 -07:00
parent 1551e5b02b
commit 2e1146ea68
6 changed files with 218 additions and 8 deletions
+112 -8
View File
@@ -21,6 +21,9 @@
extraPackages = with pkgs; [ nix git ripgrep fd jq codex ];
# Pulls in hindsight-client (the HTTP client lib the memory plugin uses).
extraDependencyGroups = [ "hindsight" ];
environment = {
SIGNAL_HTTP_URL = "http://127.0.0.1:8080";
CODEX_HOME = "/var/lib/hermes/.codex";
@@ -44,14 +47,14 @@
toolsets = [ "all" ];
terminal.backend = "local";
# Self-hosted memory: pure SQLite in-process, no external services or
# API keys. db file lives under HERMES_HOME (= /var/lib/hermes/.hermes),
# which is on the persisted bind-mount.
memory.provider = "holographic";
plugins.hermes-memory-store = {
db_path = "/var/lib/hermes/.hermes/memory_store.db";
auto_extract = true;
default_trust = 0.5;
# Memory lives in a sibling hindsight-api process (see systemd unit
# below) backed by system postgres. Plugin talks HTTP to it locally.
memory.provider = "hindsight";
plugins.hermes-hindsight = {
mode = "local_external";
api_url = "http://127.0.0.1:8888";
bank_id = "hermes";
memory_mode = "hybrid";
};
};
};
@@ -80,6 +83,8 @@
systemd.tmpfiles.rules = [
"d /var/lib/hermes/.codex 0700 googlebot users -"
"C+ /var/lib/hermes/.codex/config.toml 0644 googlebot users - /etc/hermes-codex-config.toml"
"d /var/lib/hermes/hindsight 0700 googlebot users -"
"d /var/lib/hermes/postgresql 0750 postgres postgres -"
];
# signal-cli runs an HTTP JSON-RPC daemon on localhost; hermes-agent talks to
@@ -102,4 +107,103 @@
RestartSec = "5";
};
};
# ---------------------------------------------------------------------------
# Hindsight memory backend
#
# Architecture:
# hermes-agent --HTTP--> hindsight-api (port 8888) --asyncpg--> postgres
# hindsight-worker (background async retain/reflect)
#
# The api + worker run as googlebot with HOME=/var/lib/hermes so the
# `openai-codex` provider's hardcoded Path.home() / ".codex" / "auth.json"
# resolves to the persisted codex tokens.
# ---------------------------------------------------------------------------
services.postgresql = {
enable = true;
package = pkgs.postgresql_17;
extensions = ps: [ ps.pgvector ];
# Persist DB state on the /var/lib/hermes bind mount so the hindsight
# memory bank survives `nixos-rebuild switch` (which recreates the
# incus container and wipes its writable layer).
dataDir = "/var/lib/hermes/postgresql/17";
ensureDatabases = [ "hindsight" ];
ensureUsers = [{
name = "googlebot";
# Superuser so the hindsight-api alembic migrations can `CREATE EXTENSION`
# and own the schema. Acceptable here because postgres is local-only to
# the sandboxed workspace and only talks to hindsight-api over the unix
# socket.
ensureClauses.superuser = true;
}];
};
systemd.services.hindsight-api =
let
env = {
# Connection — postgres is on the local unix socket; sqlalchemy gets
# an asyncpg URL via the asyncpg+host=<socket-dir> trick.
HINDSIGHT_API_DATABASE_URL = "postgresql+asyncpg:///hindsight?host=/run/postgresql";
HINDSIGHT_API_HOST = "127.0.0.1";
HINDSIGHT_API_PORT = "8888";
# LLM + embeddings both ride codex OAuth — no separate keys.
HINDSIGHT_API_LLM_PROVIDER = "openai-codex";
HINDSIGHT_API_EMBEDDINGS_PROVIDER = "openai-codex";
# We did not install [local-ml] extras, so disable the reranker
# (default is "local" which requires sentence-transformers).
HINDSIGHT_API_RERANKER_PROVIDER = "none";
# HOME drives where the codex auth file is read from
# (CodexLLM/CodexOAuthEmbeddings: Path.home() / ".codex" / "auth.json").
HOME = "/var/lib/hermes";
};
in
{
description = "Hindsight memory API server";
wantedBy = [ "multi-user.target" ];
after = [ "postgresql.service" "network-online.target" ];
wants = [ "network-online.target" ];
requires = [ "postgresql.service" ];
before = [ "hermes-agent.service" ];
environment = env;
serviceConfig = {
Type = "simple";
User = "googlebot";
Group = "users";
ExecStart = "${pkgs.hindsight-api}/bin/hindsight-api";
Restart = "always";
RestartSec = "5";
WorkingDirectory = "/var/lib/hermes/hindsight";
};
};
systemd.services.hindsight-worker =
let
env = {
HINDSIGHT_API_DATABASE_URL = "postgresql+asyncpg:///hindsight?host=/run/postgresql";
HINDSIGHT_API_LLM_PROVIDER = "openai-codex";
HINDSIGHT_API_EMBEDDINGS_PROVIDER = "openai-codex";
HINDSIGHT_API_RERANKER_PROVIDER = "none";
HOME = "/var/lib/hermes";
};
in
{
description = "Hindsight background worker (async retain / reflect)";
wantedBy = [ "multi-user.target" ];
after = [ "hindsight-api.service" ];
requires = [ "hindsight-api.service" ];
environment = env;
serviceConfig = {
Type = "simple";
User = "googlebot";
Group = "users";
ExecStart = "${pkgs.hindsight-api}/bin/hindsight-worker";
Restart = "always";
RestartSec = "5";
WorkingDirectory = "/var/lib/hermes/hindsight";
};
};
}