Pull to refresh

Продолжаю делиться граблями, на которые я наступил в Claude Code. Как я ловил API Error: Stream idle timeout - partial response received

Дисклеймер: кажется, что всё это можно было и не ловить — по крайней мере в более простых системах я такие ошибки никогда не видел. Но раз уж начал упарываться в агентов, то почему бы не наступить на все грабли.

Проблема такая: оркестратор собирает SEO-статью на 8 000 слов, отдаёт редактору, пробует сохранить. Через 30 секунд тишины: API Error: Stream idle timeout — partial response received

Файл создан, но обрезан на месте, где стрим ушёл в idle.

❌ Первая очевидная неверная гипотеза: большой Write

Значит надо резать на чанки. Снизил лимит 15 000 → 8 000 → 6 000 → 5 000. Таймаут повторялся. Значит, дело не в размере записи.

✨ Настоящая причина: пересборка текста

Оркестратор не копировал готовый текст субагента. Он его пересобирал: переоформлял, перенумеровывал 28 сносок, «причёсывал» заголовки. Пока модель думала над форматированием, токены в стрим не эмитились. API считал соединение мёртвым и закрывал.

Решение РАЗ: passthrough + чанки ≤ 3 000

Вводим правило rules/common/safe-file-save.md:

➡️ Субагент возвращает строку оркестратору. Оркестратор копирует её в Write байт-в-байт — без «улучшений».

➡️ Разбиение планируется один раз до первого Write, потом проходится механически.

➡️ Лимит 3 000 символов на Write/Edit — потолок, при котором стрим не уходит в idle при честном passthrough.

➡️ Перед каждым Edit — сообщение 💾 Чанк K/M…. Иначе пользователь видит тишину и прерывает.

Если таймаут повторяется на 3 000 — спуск на 1 500. Если и там падает — это сеть, не контент.

И Recovery для обрезанных файлов

Повторный Write поверх частичного файла затирает уже сохранённое. Поэтому:

➡️ ls — проверить, что файл есть

➡️ Read — измерить длину

➡️ Edit (append) с точки обрыва, чанки по 3 000

Никогда не стартовать Write заново по тому же пути.

⭐️ Вторая волна: редактор

После фикса записи таймаут вернулся на возврате субагента-редактора. Вход 18 000 символов, выход 18 000 переписанного текста + отчёт «до/после» + метрики. Prefill и генерация занимают десятки секунд без эмита токенов. Retry не помогал: корень — объём выхода.

Решение ДВА: diff-mode

Вводим правило rules/common/editor-diff-mode.md. Редактор возвращает не переписанный текст, а список правок:

=== EDIT id=1 op=replace === FIND: Данное решение является инновационным продуктом REPLACE: VK Cloud управляет инфраструктурой — от ВМ до managed-БД REASON: редполитика + инфостиль === END EDIT ===

Лимиты: ≤ 60 правок, FIND ≤ 300, REPLACE ≤ 500, суммарный выход ≤ 8 000. Оркестратор парсит блоки и применяет через Edit.

Матрица по длине для глубокой редактуры:

➡️ ≤ 4 000 → классический

➡️ 4 000 – 20 000 → diff-mode

➡️ > 20 000 → секционный (одна H2 за вызов)

Пороги ниже именно для тяжёлых режимов — они удваивают выход за счёт отчёта «до/после».

Что в итоге то:

Два источника одной ошибки: оркестратор переформатирует перед Write, редактор генерирует слишком много на выход. Лечатся по отдельности: passthrough + чанки для записи, diff-mode для правок. Recovery закрывает остаточные случаи, когда таймаут всё-таки прилетел.

Я вроде не курю, но захотелось.

Как всегда ссылка на канал. Подписывайтесь

Tags:
0
Comments0

Articles