Conversation
`mmx text chat --stream` ended its SSE loop on the first `done` read from
the response body, whether or not the server had sent `message_stop` or
`data: [DONE]`. A connection dropped mid-response therefore printed the
partial answer (or, with `--output json`, a complete-looking
`{"content": "..."}` object) and exited 0, so callers could not tell a
truncated response from a finished one.
ERRORS.md documents the intended behaviour for `mmx text chat`:
| Stream disconnected mid-response | `Stream disconnected before response completed.` |
Track the terminator and raise that error with the documented network
exit code (6) when the stream ends without one.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
mmx text chat --streamtreats a dropped connection as a finished response. Itprints the partial answer and exits
0, so a caller cannot distinguish atruncated reply from a complete one. With
--output jsonit is worse: thecommand emits a well-formed, complete-looking
{"content": "..."}object thatsilently contains only the bytes that arrived.
ERRORS.mdalready documents the intended behaviour under## Text Commands→mmx text chat:Stream disconnected before response completed.That string does not exist anywhere in
src/ortest/— the documented erroris never raised. This is a contract violation against the repo's own error
reference, not a new behaviour proposal.
Root cause
src/commands/text/chat.ts— the SSE consumer exits its loop on whatever endsthe generator, with no notion of a terminator:
parseSSE(src/client/stream.ts) returns normally when the body readerreports
done, which is exactly what a server or proxy closing the connectionearly produces.
message_stop— a member of theStreamEventunion insrc/types/api.ts— is never inspected, and neither is the absence of[DONE]. The success path then runs unchanged.Merged PR #227 (
fix: time out stalled streams) covers the stalled case (nobytes for N seconds) in
src/client/http.ts; a stream that closes cleanly butearly never trips that timeout.
Fix
One flag in
src/commands/text/chat.ts, set by either terminator the API uses,checked once after the loop:
Exit code 6 (
ExitCode.NETWORK), per the### Exit Codestable inERRORS.md("Network error") — a dropped stream is a transport failure, not a usage or
content error. Text already streamed to stdout is left as-is (a newline is
added so the shell prompt is not glued to the partial output); the JSON summary
is not printed, so no complete-looking object is produced for an incomplete
response.
Accepting
[DONE]as well asmessage_stopkeeps every existing streamingtest green — the repo's
sseResponsehelper appendsdata: [DONE].How tested
New regression test in
test/commands/text/chat.test.tsdriving the repo'sexisting
test/helpers/mock-server— no live API call, no API key.Reproduction (before the fix)
Mock route returns an SSE body with deltas and no terminator:
mmx text chat --message Hello --stream --output jsonprints:Exit code
0. Expected (perERRORS.md):Stream disconnected before response completed.with exit code 6.Test evidence — fails before, passes after
Without the source change (test only):
With the fix:
Full suite / typecheck / lint:
Environment: bun 1.3.13, macOS.
Duplicate check
Run via
gh api search/issues(all states) andgh api .../pulls/<n>/files:repo:MiniMax-AI/cli Stream disconnectedrepo:MiniMax-AI/cli message_stoprepo:MiniMax-AI/cli stream truncatedrepo:MiniMax-AI/cli SSEparseSSEtests, #197 surfaces music stream errorsrepo:MiniMax-AI/cli DONE streamrepo:MiniMax-AI/cli parseSSErepo:MiniMax-AI/cli text chat streamrepo:MiniMax-AI/cli in:title streamfix: time out stalled streams(merged,src/client/http.ts): an idle timeout, which a cleanly-closed early stream never tripsAll 13 open PRs checked file-by-file (#261, #230, #228, #226, #225, #223, #222,
#221, #219, #209, #207, #204, #186). Only #225 and #204 touch
src/commands/text/chat.ts; neither patch mentionsparseSSE,message_stop,[DONE]or disconnect handling, and neither touchesERRORS.md.Disclosure: prepared with AI assistance (Claude Code); I reviewed the change and take responsibility for it.
🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.