snens

Долгая память

Механизмов два, и они не заменяют друг друга: карточка memory.md в системном префиксе и плагин memory с базой фактов, из которой достаётся релевантное.

memory.md — карточка

Файл <данные>/memory.md читается каждый ход и целиком приклеивается к системному промпту. Лимит — около 4 КБ по смыслу, а не по проверке: файл платится на каждом ходу любой сессии, поэтому в него идут только факты, нужные всегда и не добываемые разведкой за минуту. Остальное — указателями: «грабли проекта — в тикетах таких-то».

Правит агент. Дописывая, сжимай: две строки вместо одной — это рост префикса в каждой сессии навсегда.

Плагин memory

Один бинарь, один файл SQLite (FTS5 + sqlite-vec), без демона. Ядро знает только argv-контракт:

memory recall <запрос>     # строки фактов; пусто = нечего сказать
memory retain              # JSON {"user","assistant"} на stdin → очередь
memory flush               # очередь → факты (LLM извлекает 0–5 фактов + эмбеддинги)
memory stats               # живые/устаревшие факты, очередь, типы
memory reindex             # досчитать вектора, если провайдер лежал
memory forget <uid>        # закрыть факт по uid

recall — гибридный поиск: BM25 (FTS5) ∪ вектор (sqlite-vec, int8) → RRF → реранк cross-encoder'ом → относительный порог → не больше max_facts строк. LLM на пути чтения нет. Пустая выдача — законный исход: один нерелевантный факт роняет точность сильнее, чем помогает случайный.

flush — стадия дистилляции: модель извлекает факты, дедуп по векторам, перекрытие через supersedes — старый факт получает valid_to и остаётся в таймлайне. Зовут его таймером или руками, ядро этого не делает.

Что уходит в сеть

Настройки

Свой конфиг плагина — ~/.config/snens/memory.toml:

db = "~/.local/share/snens/memory.db"
api_base = "https://…/v1"          # любой OpenAI-совместимый
embed_model = "…"
distill_model = "…"
rerank_model = "…"                 # rerank = "off" — выключить реранк
max_facts = 6
max_tokens = 400

Ключ — SNENS_API_KEY в окружении или в ~/.config/snens/.env рядом с конфигом ядра; реранкер может жить у другого провайдера — тогда свой ключ и своя переменная. MEMORY_DEBUG=1 печатает в stderr скоры кандидатов до отсева.

Секция [memory] в config.toml управляет каналом, а не базой:

[memory]
enabled = true          # мастер-выключатель: false — ни recall, ни retain
recall = "always"       # always | session | off
retain = true
timeout_seconds = 60
cmd = "memory"          # имя программы в каталоге тулов

recall — политика впрыска справки: always каждый ход, session один раз на сессию, off только по явному вызову тула. Справка короткая по замыслу: она уезжает в префикс и остаётся там.

Как выключить

snens memory off                     # весь канал
snens memory retain off              # только запись ходов в банк
snens memory recall off              # только впрыск справки
snens memory recall session          # или always
snens memory                         # показать состояние

Правки действуют со следующего хода: живой процесс перечитывает секцию на старте цикла. Бинаря нет в PATH — канала нет, тихо.

Отличить пустую выдачу от неработающего канала можно по memory stats: он показывает живые/устаревшие факты и очередь.

Дальше: файлы инстанса · контекст