Repository navigation
Description
Проблема
При реальном прогоне library_fine на zai-coding-plan/glm-5.1 OpenCode иногда исчерпывает внутренний per-step output budget ровно в 32 000 токенов, закрывает ход без tool call, файла и финального ответа, а benchmark классифицирует это как:
зависший POST /message: ответа провайдера не было, сессия закрылась без результата
Эта формулировка неверна: провайдер ответил и usage получен. Фактическая сигнатура соответствует finish_reason=length / исчерпанию output budget в OpenCode.
Доказательства
Сохранённые прогоны в data/main.db
Отчёты 290, 296, 298: 12 копий library_fine на zai-coding-plan/glm-5.1.
- 5 успешных;
- 7 ошибок с одинаковым
HUNG_POST_REASON; - во всех 7 ошибках
output_tokens + reasoning_tokens = 32 000; - ни одного артефакта или финального результата.
| report/run | elapsed, s | output | reasoning | completion |
|---|---|---|---|---|
| 290/2 | 915.1 | 33 | 31 967 | 32 000 |
| 290/3 | 691.2 | 52 | 31 948 | 32 000 |
| 290/4 | 565.6 | 20 | 31 980 | 32 000 |
| 290/5 | 703.4 | 67 | 31 933 | 32 000 |
| 296/1 | 357.6 | 36 | 31 964 | 32 000 |
| 296/3 | 377.6 | 13 | 31 987 | 32 000 |
| 298/2 | 470.1 | 61 | 31 939 | 32 000 |
Успешные копии длились 515.4–1077.0 с, ошибочные — 357.6–915.1 с. Поэтому простой wall-clock cutoff не отличает зависание от медленного успешного выполнения.
Два свежих повторных прогона
Оба выполнены с --no-save на OpenCode 1.17.18:
| repeat | elapsed, s | input | output | reasoning | completion | result |
|---|---|---|---|---|---|---|
| 1 | 457.1 | 9 877 | 33 | 31 967 | 32 000 | no artifact |
| 2 | 517.7 | 9 814 | 29 | 31 971 | 32 000 | no artifact |
Для контроля простые задачи на той же модели и провайдере проходят:
hello_world: 21.9 с;fast_sort: 19.4 с;stock_downloader: 151.3 с.
Это не общий отказ Z.AI и не отсутствие ответа на любой prompt.
Воспроизведение
python bench.py \
--project library_fine \
-p zai-coding-plan \
-m glm-5.1 \
-n 1 \
--no-save \
--base-port 4096 \
--timeout 1000 \
"<prompt from reports 290/296/298 in data/main.db>"В окружении локальной диагностики proxy-переменные были очищены.
Точный prompt хранится в reports.raw_json отчётов 290, 296, 298.
Почему это не обычный сетевой сбой Z.AI
В проблемных копиях:
- есть ненулевой input/output/reasoning usage;
- completion всегда заканчивается ровно на 32 000;
- нет
ECONNRESET, JSON parse error или provider network error; - сессия доходит до terminal/idle, но без результата.
Это отличается от #160: там glm-5v-turbo не отдаёт ни одного события и usage отсутствует.
Upstream
Сигнатура напрямую совпадает с открытыми issue OpenCode:
- Bug:
limit.outputin config is silently capped at 32k;OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAXis a poor workaround anomalyco/opencode#29363 — скрытый per-step cap 32k; - [FEATURE]: Auto-continue when model hits output token limit (finish_reason: "length") anomalyco/opencode#17471 — OpenCode завершает цикл при
finish_reason=lengthвместо продолжения; - Truncated tool calls are misclassified and unrecoverable (finishReason: length + repairToolCall + doom loop) anomalyco/opencode#18108 — headless-запуск получает пустой результат при исчерпании output budget.
Локальная причина неправильной диагностики
- POST
/messageне завершается за 30 с →post_hung=True. - Benchmark правильно продолжает ждать SSE/terminal state.
- OpenCode заканчивает ход без файла/финального текста.
- При
code=0 + post_hung + no artifactbenchmark заменяет результат наHUNG_POST_REASON. - Terminal
finish_reasonне сохраняется, поэтому реальная причинаlengthтеряется.
Ожидаемое поведение benchmark
- Сохранять terminal
finish_reasonи сигналMessageOutputLengthError, если он есть. - При
finish=lengthи отсутствии результата сразу возвращать отдельную точную причину, например:
output budget OpenCode исчерпан (32 000), модель не завершила действие. - Не называть это отсутствием ответа провайдера.
- Не ждать общий wall-clock timeout после получения terminal
length. - Добавить CLI/config для явной передачи
OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX. - Провести A/B live-test
32 000против65 536. - Опциональный first-action watchdog держать отдельной страховкой: длительности успешных и ошибочных запусков пересекаются.
Тесты
- terminal
finish=length+ usage + no artifact → отдельный error reason; - POST read timeout + последующий успешный tool/file → success, без регрессии;
- terminal idle + no artifact без
length→ существующая диагностика; - transport error → существующий network reason (Обрыв интернет-соединения во время прогона: нет покрытия (POST /message вне planning + единая диагностика «локальный обрыв») #158);
- CLI/output-token-max корректно попадает в environment
opencode serve; - live A/B на
zai-coding-plan/glm-5.1.
Связанные issue
- Регрессия glm-5v-turbo (zai-coding-plan): вчера работала, сегодня молчит (0/12) #160 — отдельный случай полного молчания
glm-5v-turbo; - Обрыв интернет-соединения во время прогона: нет покрытия (POST /message вне planning + единая диагностика «локальный обрыв») #158 — обработка сетевых обрывов;
- bench: code=0 без артефакта — ложный успех (модель отработала, но файл не сохранила; это не успешный запуск) #142 — ложный успех без артефакта.
Activity
axisrow commentedon Jul 20, 2026
Реализация готова в рабочем дереве (без коммита/PR).
Что сделано:
--output-token-max INT, значение явно передаётся вOPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAXдля каждогоopencode serve;finish=lengthиMessageOutputLengthErrorтеперь сохраняются и классифицируются как отдельная ошибкалимит ответа OpenCode исчерпан, а не как отсутствие ответа провайдера;lengthожидание потерянногоsession.idleпрекращается;--first-action-timeout SECONDS; watchdog считает только первый text/tool/question основного assistant и игнорирует user prompt, title-agent и reasoning;finish_reasonиfirst_action_elapsedсохраняются в отчёт.Live A/B: OpenCode 1.17.18,
zai-coding-plan/glm-5.1, тот же полныйlibrary_fineprompt,-n 1 --no-save --timeout 1000, proxy env очищен.--output-token-max 65536Default-прогон в этот раз прошёл, что подтверждает стохастичность: ранее 9 независимых запусков завершались ровно на 32,000 completion. Для 65k OpenCode log показывает около 784s до первого tool action. 62,783 — aggregate completion всего прогона, не доказательство per-step usage, но результат согласуется с тем, что повышенный потолок снимает прежний 32k барьер.
Live watchdog-проверка с
--first-action-timeout 5завершила такой же тяжёлый запуск ошибкой за 34.1s вместо 600–1000s. Задержка выше 5s объясняется существующим POST read timeout 30s.Проверка:
python3 -m py_compile bench.py;git diff --check.Live-прогоны были
--no-save; измененияdata/main.dbне включены в реализацию.fix(session): MessageOutputLengthError через session.error → OUTPUT_L…
fix(session): сохранять early.finish_reason при раннем возврате POST (#…
fix(serve): диагностика исчерпания output budget OpenCode вместо HUNG…