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).