Hacktoberfest 2026:维护者为十月标记出来的 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 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 1 天内回复

还没有人认领这个 Issue。

评估

难度
4/5
预计耗时
3-5 天
新手友好度
15/100
Issue 类型
缺陷
描述清晰度
描述清楚
活跃度
活跃
领域
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
平均合并
9 小时 22 分钟
30 天内合并 PR
105

环境准备

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

MiniMax-AI/minimax-code 的其他 Issue

查看 MiniMax-AI/minimax-code 的全部 Issue

相似的 Issue

更多 TypeScript Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。