0.167.15

Fixed

  • AutoCompact мерял не тот набор сообщений и читал старейшие 1000 вместо свежих ( — P1). Два независимых дефекта делали решение о компакции неверным. (1) Токен-триггер считал сообщения, которых нет в промпте: estimateHistoryTokens суммировал оценку по результату GetMessages (все роли), включая JSON-блобы tool_iteration и tool_call_history, которые SQL-фильтр dialogRoleFilter в промпт не пропускает — у агента, активно использующего инструменты, служебные блобы составляют бо́льшую часть таблицы, и порог срабатывал многократно раньше реального заполнения контекста (лишние LLM-вызовы, архивация ещё актуальной истории). Фикс: новый isDialogRole (зеркалит dialogRoleFilter) — estimateHistoryTokens считает только роли user/assistant/system/tool/memory_context. (2) Читались старейшие сообщения: GetMessages сортирует ORDER BY id ASC — при более чем 1000 активных сообщений AutoCompact работал по устаревшему префиксу истории. Фикс: maybeCompact и compactWithPairs (включая поиск userID для pre-consolidate) переведены на GetRecentMessages (id DESC + разворот — свежий хвост). (3) Мёртвая конфигурация: поля CompactConfig.Enabled/HardThresholdPct/MaxPasses AutoCompact не читал вовсе, при этом HardThresholdPct выводился слайдером «Hard threshold (%)» в UI настроек памяти и не влиял ни на что. Поля удалены из Go-типа и DefaultCompactConfig (JSON в БД с лишними полями обратно совместим — unmarshal игнорирует), слайдер удалён из SettingsTab.svelte, state/сеттер/поле payload — из useMemoryData.svelte.ts и MemoryTabContent.svelte; канонический интерфейс CompactConfig в types.ts сокращён до реально работающих полей (legacy-интерфейс CompactionConfig для чтения произвольного JSON из БД не тронут — старые записи содержат эти поля). Устаревший комментарий фолбэка бюджета исправлен: 10000 («~budget.History при 16k») → 116800 (budget.History при дефолтных 128k минус резервы 11200). Тесты: служебные роли не влияют на estimateHistoryTokens; 10 диалоговых + 200 tool_iteration → триггер молчит; >1000 сообщений → summary-вход содержит свежий хвост (NEW-*); пустая история → 0 LLM-вызовов; SoftThresholdPct=0 → дефолт 70, а не вечный триггер. npm run check — 0 ошибок; npm test — 603/603.