Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

[Bug]: mcode exec fails with limit_exceeded (exit 7) when auto-compaction runs, because the checkpoint consumes --max-steps

オープン
#514 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
15/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
node.js, typescript
領域
backend, cli

調査の方向性

Start by reading the listed consumers in packages/tui/src/application/run-coordinator.ts, response-usage.ts, headless/events.ts, acp/updates.ts, and the projection, transcript, and channel adapter files. Trace how assistant lifecycle messages are classified and run the local fixture reproduction with --max-steps 1; done means the checkpoint does not consume a user step or leak as assistant output across the affected consumers. The issue reports an existing fork patch, so check contribution guidance before taking it on.

索引モデルが issue の本文から書いたものです。

説明

Product or interface

CLI - headless

Version
  • Source checkout at commit 5821f7c (package.json version 0.6.5, docs/open-source-status.md calls this the 0.6.3 source preview)
  • Node.js 24.9.0, pnpm 9.12.0
  • Affects packages/tui and packages/local-runtime-v2 as shipped in this repository
Platform

Multiple platforms

OS version and architecture

Originally reproduced on Windows x64. The defect is platform-independent: it is a message-classification bug in shared TypeScript, with no platform, filesystem or native dependency involved.

Issue area

Agent stuck / slow / repeated loop

Steps to reproduce

Use a local OpenAI-compatible fixture so no real provider or account is involved. The key requirement is that automatic context compaction triggers during the turn.

  1. Register a provider with a small context window, which lowers the auto-compaction trigger:
mcode provider add --name ctx --base-url http://127.0.0.1:<port>/v1 \
  --api-format openai-completions --model fixture-model \
  --context-limit 32768 --support-image --use
  1. Run a single-turn task with --max-steps 1:
mcode exec "IMAGE_INPUT_TEST" \
  --model custom_provider:ctx/fixture-model \
  --file fixture.png \
  --timeout 20s --max-steps 1

--file only matters because it is one way to push the request over the compaction trigger. Permission mode is irrelevant; the failure happens before the tool loop. No credentials are needed beyond the fixture key.

The same failure occurs with any prompt when the context is near the trigger, e.g. --context-limit 8192 with no attachment at all.

Expected and actual behavior

Expected: --max-steps 1 bounds how many times the agent calls the model for the user's turn. An internal compaction checkpoint is bookkeeping, not a user turn step, so the run should succeed with one model response and report the real answer.

Actual:

mcode exec limit_exceeded: The run reached its step limit. Increase --max-steps or narrow the task.
$ echo $?
7

Diagnostics confirm the first provider request of the turn is the checkpoint, and the real turn is the second request:

{"kind":"model_phase_started","operationId":"turn_...:model:1",...}
# request 1 -> "Checkpoint control: summarize the preceding conversation now. ..."
# request 2 -> the user's actual turn

Deterministic before/after matrix (local fixture, --max-steps 1):

context limit image attachment checkpoint performed result
32768 yes 1 exit 7
32768 no 0 exit 0
8192 yes 0 exit 7
8192 no 0 exit 7

The 8192 rows fail even without a checkpoint because the request alone exceeds the trigger; either way the reported reason is "step limit", which points a user at --max-steps instead of at context compaction.

Same root cause, four additional user-visible effects (all reachable from the same misclassification, see below):

  1. A lifecycle frame can replace an answer that was already selected: answer is cleared and the retained streamed draft is discarded, so the turn can end with no answer or with the checkpoint text.
  2. Compaction content is projected to ACP clients as agent_message_chunk, so an IDE sees checkpoint prose as assistant output.
  3. Compaction checkpoint text renders as the live assistant reply in the TUI and is written into exported Markdown transcripts.
  4. Chat-channel replies (Feishu/Telegram/WeChat) leak compaction and review text, because the collector only filters the terminal kind === 'compaction' state and misses compaction_start, compaction_failed and all review_* frames.
Root cause

Compaction and review lifecycle frames are persisted with role: 'assistant' because they share the message store with model responses. The two facts are orthogonal — role says who produced the frame, kind says which lifecycle state it is — but the repository never defined a single "is this a model response" predicate. Each consumer re-derived it:

Location Predicate Consequence
packages/tui/src/application/run-coordinator.ts role === 'assistant' lifecycle frame consumes a --max-steps slot
packages/tui/src/application/response-usage.ts kind?.startsWith('compaction') review_* contributes usage and response identity
packages/tui/src/headless/events.ts role === 'assistant' checkpoint text becomes agent_message output
packages/tui/src/acp/updates.ts role === 'assistant' checkpoint text sent to IDE clients
packages/tui/src/tui/controller/projection/turn-live-projection.ts none checkpoint text rendered as assistant body
packages/tui/src/tui/transcript/export.ts role only checkpoint text enters exported Markdown
packages/local-runtime/src/channels/sse-collector.ts kind === 'compaction' three of eight lifecycle kinds filtered
packages/local-runtime/src/api/conversation-message-adapter.ts three literal compaction kinds review_* dropped, then re-read as model output

--max-steps is therefore consumed by an internal auxiliary request, and the CLI reports a limit error for a run that never exceeded its intended budget.

Suggested fix

Introduce one classification module and make every producer type and consumer read it, so no alternate path can drift again. In my working tree this is @mavis/shared/turn-message-class (chosen because packages/tui does not depend on @mavis/agent-core, and @mavis/shared sits at the bottom of the dependency graph):

  • lifecycle kind sets and kind → lifecycle-state tables, replacing three separate if/else ladders
  • isTurnResponseMessage(message) = role === 'assistant' && !isTurnLifecycleMessage(message)
  • MessageKind and RuntimeMessageKind derive from the shared union instead of re-listing literals
  • run-coordinator gates response steps, usage and answer selection through one composed predicate; a lifecycle frame is not a step, but still marks usage incomplete because its auxiliary call spends tokens
  • the other eight call sites ask the same module instead of comparing role or kind

A local fix in run-coordinator alone would stop the exit-7 symptom but leave items 2–4 above in place, which is why I am reporting the shared root cause rather than only the step counter.

Redacted error summary
mcode exec limit_exceeded: The run reached its step limit. Increase --max-steps or narrow the task.

Exit code 7, mapped from limit_exceeded in packages/tui/src/headless/exit-policy.ts. ACP returns stopReason: max_turn_requests for the same underlying condition.

Verification I can and cannot claim

Reproduced deterministically on Windows x64 against a local OpenAI-compatible fixture, and pnpm test:byok fails on this at IMAGE_INPUT_TEST (exit 7) on every run before the fix and passes after it.

Not verified: macOS and Linux were not run at all; no real MiniMax backend, Token Plan or BYOK provider was involved, so this is offline fixture evidence, not live-service acceptance; compaction output quality was not assessed, only whether the checkpoint request occurred; ACP was checked at the projection level only, not against a real IDE client; IM channels were checked at the pure-function level only, not against real services.

Screenshots

No response

Before submitting
  • I have searched existing issues.
  • I have included my version and removed sensitive information.

A working patch exists on a fork branch fix/lifecycle-frame-classification (31 files, +633/−113, four new files, no moved or renamed files, generated release/public-source.json and tsconfig.standalone.json regenerated with their scripts). I understand from CONTRIBUTING.md and the issue-template config that external PRs are not accepted; I am not attaching it as a pull request. I can paste the diff, describe any file in detail, or hand the branch to a collaborator if that is useful.

主要言語
TypeScript
スター
2k
フォーク
259
平均マージ
11時間
マージ済み PR(30日)
81

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

MiniMax-AI/minimax-code のほかの issue

MiniMax-AI/minimax-code の issue をすべて見る

似ている issue

TypeScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。