Skip to content

fix(runtime): отказ модели пересказать историю больше не останавливает чат (#331) - #356

Merged
nyxandro merged 4 commits into
developfrom
fix/compaction-refusal-recovery
Oct 8, 2026
Merged

nyxandro merged 4 commits into
developfrom
fix/compaction-refusal-recovery

Conversation

@nyxandro

@nyxandro nyxandro commented Oct 8, 2026 •

Copy link
Copy Markdown
Owner

Что меняется

Если модель отклоняла сам запрос на пересказ старой части истории, чат застревал навсегда: каждое следующее сообщение отправляло тот же запрос с тем же отказом.

Теперь выход начинается со следующего сообщения, без повтора внутри хода (решение владельца 08.10):

  • отказ на пересказ (не временная недоступность модели и не отмена) записывается в состояние сессии (compaction_summary_refusals, миграция 130);
  • каждый отказ вдвое уменьшает бюджет следующего пересказа, и бюджет становится жёстким: что не спасает обрезка, отдают старейшие сообщения с пометкой, сколько их выпало;
  • после четырёх отказов подряд старая часть заменяется пометкой «не удалось пересказать», без вызова модели;
  • удачное сжатие обнуляет счётчик; в лог пишется строка AGENT_COMPACTION_SUMMARY_REFUSED с числом отказов.

Обычное сжатие без отказов не меняется.

Проверено

Модульные тесты сжатия и интеграционный тест хода: временный сбой не считается отказом, отказ запоминается, следующий пересказ меньше, после успеха счётчик обнулён. Все тесты agent/runtime (246) и проверка типов зелёные.

Closes #331

🤖 Generated with Claude Code

Изменения

  • Добавлен счётчик последовательных отказов модели при суммаризации истории. Миграция 130_compaction_summary_refusals.sql создаёт для него поле со значением по умолчанию 0.
  • После отказа следующий запрос на суммаризацию получает вдвое меньший бюджет. При строгом бюджете система также удаляет самые старые сообщения, если они не помещаются.
  • После четырёх отказов система удаляет старую часть истории и добавляет уведомление о количестве удалённых сообщений. Предыдущая сводка сохраняется.
  • После успешной компактизации счётчик сбрасывается. Для отказа в суммаризации ход возвращает AGENT_COMPACTION_SUMMARY_REFUSED и записывает предупреждение. Ошибка сохранения счётчика не заменяет исходный отказ.
  • Отказы классифицируются отдельно от временных ошибок и ошибок доступа. Ошибки со статусами 401, 402, 403 и 404 не увеличивают счётчик.

Проверки

Добавлены тесты классификации отказов, компактизации и восстановления в следующем ходе. Результаты запуска тестов и проверки типов не указаны.

nyxandro and others added 2 commits October 8, 2026 17:42
…т чат навсегда

#331: если модель отклоняла сам запрос на пересказ старой части истории (окно по её счёту,
отказ провайдера), ход падал, история не менялась, и следующее сообщение отправляло тот же
запрос с тем же результатом — чат замолкал навсегда.

Выход — со следующего сообщения, без повтора внутри хода (решение владельца 08.10.2026):
- отказ на пересказ (не временная недоступность и не отмена хода) записывается в состояние
  сессии отдельной транзакцией: compaction_summary_refusals, миграция 130;
- каждый отказ вдвое уменьшает бюджет следующего пересказа, и бюджет становится жёстким: что
  не спасает обрезка, отдают старейшие сообщения с пометкой, сколько их выпало;
- после четырёх отказов подряд старая часть заменяется пометкой «не удалось пересказать» без
  вызова модели — путь выхода гарантирован;
- удачное сжатие обнуляет счётчик; строка AGENT_COMPACTION_SUMMARY_REFUSED с числом отказов.

Обычное сжатие без отказов работает как раньше.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 3ea8b753-9c65-47a7-a798-a43345262995
📥 Commits

Reviewing files that changed from the base of the PR and between 416e431 and 9f79439.

📒 Files selected for processing (11)
  • agent/lib/memory-upgrade-ledger.integration.test.ts
  • agent/runtime/history/history-repository.integration.test.ts
  • agent/runtime/history/history-repository.ts
  • agent/runtime/turn/compaction-prompt.ts
  • agent/runtime/turn/compaction.test.ts
  • agent/runtime/turn/compaction.ts
  • agent/runtime/turn/model-errors.test.ts
  • agent/runtime/turn/model-errors.ts
  • agent/runtime/turn/run-turn.integration.test.ts
  • agent/runtime/turn/run-turn.ts
  • migrations/130_compaction_summary_refusals.sql

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.


Walkthrough

Добавлены учёт отказов модели при суммаризации истории и обработка повторных отказов. Последующие запросы сводки используют меньший бюджет. После четырёх отказов система исключает старую часть истории и добавляет уведомление.

Changes

Обработка отказов при суммаризации

Layer / File(s) Summary
Хранение счётчика отказов
migrations/130_compaction_summary_refusals.sql, agent/runtime/history/history-repository.ts, agent/runtime/history/history-repository.integration.test.ts, agent/lib/memory-upgrade-ledger.integration.test.ts
Добавлен счётчик последовательных отказов в состояние сессии. Репозиторий загружает и увеличивает его, а при замене истории сбрасывает. Тесты проверяют состояние сессии и список миграций.
Распознавание и запись отказа
agent/runtime/turn/model-errors.ts, agent/runtime/turn/model-errors.test.ts, agent/runtime/turn/run-turn.ts, agent/runtime/turn/run-turn.integration.test.ts
Добавлена классификация отказов модели. При отказе запроса сводки ход возвращает AGENT_COMPACTION_SUMMARY_REFUSED и записывает отказ. Интеграционный тест проверяет счётчик, обработку ошибок и последующее успешное сжатие.
Сокращение запросов сводки
agent/runtime/turn/compaction.ts, agent/runtime/turn/compaction-prompt.ts, agent/runtime/turn/compaction.test.ts
При каждом отказе бюджет запроса сводки уменьшается вдвое. После четырёх отказов повторный запрос сводки не выполняется: старая часть истории заменяется уведомлением, а недавний хвост и существующая сводка сохраняются. Добавлены тесты этих сценариев.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Bug fix · Severity of issue fixed: Medium

Sequence Diagram(s)

sequenceDiagram
  participant TurnLoop
  participant HistoryRepository
  participant compactIfNeeded
  participant Model
  participant isRequestRefusal
  TurnLoop->>HistoryRepository: загружает историю и счётчик отказов
  HistoryRepository-->>TurnLoop: возвращает состояние сессии
  TurnLoop->>compactIfNeeded: передаёт историю и счётчик
  compactIfNeeded->>Model: отправляет запрос сводки с текущим бюджетом
  Model-->>compactIfNeeded: возвращает отказ
  compactIfNeeded->>isRequestRefusal: классифицирует ошибку
  isRequestRefusal-->>compactIfNeeded: подтверждает отказ
  compactIfNeeded->>HistoryRepository: увеличивает счётчик отказов
  compactIfNeeded-->>TurnLoop: возвращает AGENT_COMPACTION_SUMMARY_REFUSED
Loading

Merge Risk: ⚪ Minimal · up to 9f794

The refusal-recovery change is mergeable after normal checks; transient model errors do not consume the refusal counter.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 78.57% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 14 functions across 10 files. (1 skipped:… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed Заголовок точно описывает основное изменение: отказ модели при суммаризации истории больше не блокирует чат.
Linked Issues check ✅ Passed Требования #331 выполнены. recordCompactionSummaryRefusal сохраняет последовательный отказ в состоянии сессии через миграцию 130_compaction_summary_refusals.sql. compactIfNeeded учитывает только…
Out of Scope Changes check ✅ Passed Изменения остаются в области #331. Миграция, загрузка и сохранение счётчика, классификация отказов, логирование, логика сжатия и тесты непосредственно поддерживают восстановление после отказа запроса …
Full details: Docstring Coverage

Explanation

Docstring coverage is 78.57% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 14 functions across 10 files. (1 skipped: 1 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

nyxandro and others added 2 commits October 8, 2026 18:05
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
По ревью #331. Ошибка ключа, оплаты, пропавшая модель или модель, не
ответившая вовремя, валят любой запрос, а не этот пересказ. Раньше они
тоже засчитывались как отказ: четыре сообщения во время такой аварии
молча выбросили бы старую часть истории. Отказом теперь считаются только
переполнение окна, пустой ответ и отклонённый запрос без статусов
доступа (401, 402, 403, 404).

Когда старая часть истории выбрасывается после четырёх отказов,
принятая раньше сводка остаётся. Ход падает с понятным кодом
AGENT_COMPACTION_SUMMARY_REFUSED и сообщением, что следующее сообщение
сожмёт историю сильнее, вместо «повтор не поможет». Если счётчик отказов
записать не удалось, это уходит в лог, а ход падает с исходным отказом.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@nyxandro
nyxandro merged commit 534bb0d into develop Oct 8, 2026
4 checks passed
@nyxandro
nyxandro deleted the fix/compaction-refusal-recovery branch October 8, 2026 18:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant