MiniMax-AI / MiniMax-AI/minimax-code
[Feature]: Return the prompt to the composer when aborting before the model replies
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 1.3k
- Forks
- 141
- Avg merge
- 2h 45m
- Merged PRs (30d)
- 46
Description
Product or interface
CLI - interactive TUI
Use case and problem
When I submit a prompt and immediately realize it has a typo, targets the wrong file, or asks the wrong question, the only escape is Esc — which stops the turn and leaves the prompt stuck inside a cancelled turn in the transcript. I have to retype it or recall it with Up and edit from history, losing the "fix one word and resend" flow.
Today the queue flow already returns queued messages to the composer (Alt+Up), and crash recovery already restores interrupted submissions on relaunch — but the most common case, "I just sent it and regret it", has no path.
Desired behavior
State-gated restore, keyed on what the aborted turn actually produced — not a timer:
When the user aborts a running turn AND that turn has produced no user-visible output (no assistant text, no tool call, no steer message), the prompt text returns to the composer for editing. Thinking does not disqualify: it is internal model process and the most common regret moment. Turns with output keep today's stop-only behavior, so intentional stops are never second-guessed.
Interaction example:
type a prompt, press Enter
Esc (before any reply/tool output)
-> "Stopped · message restored to the Composer."
-> the prompt is back in the composer, editable
-> the aborted turn's transcript row is removed
type the correction (merges below the restored text), Enter to resend
Esc after the model started replying
-> turn stops as today; composer stays empty; transcript kept
Acceptance criteria:
- The trigger is the confirmed stop of the aborted turn on the existing abort funnel — delegated-only stops (root still running) never fire it; a stop the runtime does not confirm never fires it.
- Restore merges with text typed during the stop (never overwrites in-progress typing); restores drop the matching pending retry so a relaunch cannot duplicate the text; side conversations are skipped.
- Exiting the app after an abort still persists the restored draft (existing draft-recovery path), so the text survives to the next launch.
- A restore failure reports a warning without breaking Esc handling.
Why state-gated instead of a time window: a timer races the model's first token and behaves non-deterministically; gating on "no output yet" captures exactly the regret window with zero timing sensitivity. Why not unconditional: interrupting a turn that is already replying usually means "stop", not "give my words back" — unconditional restore would fight that intent.
Platform
Multiple platforms
Alternatives and additional context
What I tried / considered:
Upinput-history recall — works, but loses cursor position and attachments and requires knowing the shortcut./historyEdit on the committed message — a runtime-level rewind; far heavier than the regret-window case needs.- Doing nothing — the cancelled turn keeps the text, but editing it means retyping.
I implemented this on my fork (per the collaborators-only PR policy, not opening a PR; feel free to review the fork commit and port it as a maintainer PR — partial adoption welcome):
- Branch
feat/abort-prompt-restore, single commit2dfc60bon top of currentmain: https://github.com/kele98/minimax-code/commit/2dfc60b - TUI-only: 6 files (
packages/tuiabort funnel + app wiring + a small draft-lifecycle helper + tests + theEscshortcut row in README/README_ZH updated in both languages). No runtime, persistence, or protocol changes. - Validation:
tui-app.test.ts270/281 — the 11 failures are the pre-existing zh-CN locale baseline on this machine, reproduced identically with the patch stashed; new/adjusted cases cover no-output restore, thinking-only restore, after-output no-restore, unconfirmed-stop no-restore, delegated-only-stop no-restore, merge-with-typed-text, and a two-instance relaunch non-duplication test through real draft persistence.pnpm verifypasses all gates up totest:capabilities(stops on the same 23 environment-baseline failures: 11 locale assertions + 12 Windows symlink EPERM); remaining gates pass individually (status-contract9/9,smoke16 pass/1 skip,byok11/11); typecheck and build clean. Interactive smoke via a real pty against a local fixture provider (stream holds open until abort) verified both timings end-to-end. Not claimed: macOS/Linux manual acceptance, live-model runs, Desktop app.
Key semantics (trigger scope, thinking exemption, transcript-row removal) are all open to adjustment if maintainers prefer a different shape.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in packages/tui at the existing abort funnel and app wiring, then review tui-app.test.ts and the draft-recovery path. Compare the fork commit 2dfc60b and its cases for no-output, thinking-only, after-output, unconfirmed and delegated stops. Done means confirmed no-output aborts restore and merge the draft safely, while output-bearing or unconfirmed stops retain current behavior and the listed tests pass.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- cli, testing-qa
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100