0.167.14
Fixed
emergencyCompact— слепой срез массива пополам ронял system prompt и игнорировал токен-бюджет ( — P1). Единственный механизм восстановления после context-overflow (retry в runner разрешён один раз,overflowRetryUsed) резалmessages[len/2:]: второй параметрcontextMaxTokensотбрасывался (_), а ведущее system-сообщение — собранный системный промпт с identity, инструментами и правилами безопасности — улетало при срезе, после чего агент посреди хода терял представление о себе; никакое summary отрезанной части не создавалось, и при слишком малом срезе повторный overflow убивал ход окончательно. Фикс:emergencyCompactтеперь (1) извлекает и безусловно сохраняет ведущиеsystem-сообщения (по образцу полноценногоCompressor.Compress); (2) приcontextMaxTokens > 0режет историю поComputeBudget(contextMaxTokens).Historyчерез существующийpruneHistoryByTokens— тот же гейт, что и до хода (applyHistoryBudget), с атомарностью tool-групп и принудительной защитой последнего user-сообщения; (3) фолбэк «пополам» остаётся дляcontextMaxTokens <= 0, вырожденного бюджета и случая «оценка говорит — всё влезает» при фактическом overflow (гарантированное уменьшение, чтобы retry имел шанс); (4)repairToolPairsвычищает осиротевшие tool-пары на границе среза. Мёртвая константаCompactPlaceholderContent(описывала подстановку заглушки, которой не существовало) удалена. Тесты: сохранность system-промпта при трёх режимах (бюджет/минимальный/0-фолбэк), укладка результата в History-бюджет (+system+slack), сохранность последнего user-сообщения, вход из 3 сообщений → без изменений,contextMaxTokens=0→ безопасный фолбэк без паники, атомарность tool-групп (validateToolGroups).