Skip to content

feat(cli): add MiniMax CLI (mmx) adapter - #1300

Open
lijason1121 wants to merge 2 commits into
deepcoldy:masterfrom
lijason1121:feat/minimax-cli-adapter
Open

feat(cli): add MiniMax CLI (mmx) adapter#1300
lijason1121 wants to merge 2 commits into
deepcoldy:masterfrom
lijason1121:feat/minimax-cli-adapter

Conversation

@lijason1121

Copy link
Copy Markdown

Add a minimax CLI adapter bridging MiniMax's official CLI (mmx, package mmx-cli). Its interactive multi-turn surface is mmx text repl, a readline-style chat REPL that requires a TTY — provided by the PTY/tmux backend.

The repl is a pure chat/generation loop with no shell or file-tool surface, so like mira/riff it relays via quiescence + screen capture rather than the botmux send wrapper: no skillsDir, empty systemHints, altScreen=false (it redraws its input line in place, not via the alternate screen buffer). Auth resolves from mmx auth login (~/.mmx/config.json); the whole ~/.mmx dir is the authPath so a sandboxed first login persists.

Registered per src/adapters/cli/CLAUDE.md checklist:

Verified: tsc --noEmit clean; cli-adapters + cli-availability unit suites pass (449); end-to-end PTY harness drove a real MiniMax-M3 reply through buildArgs -> spawn -> writeInput -> output.

Add a `minimax` CLI adapter bridging MiniMax's official CLI (`mmx`,
package `mmx-cli`). Its interactive multi-turn surface is `mmx text repl`,
a readline-style chat REPL that requires a TTY — provided by the PTY/tmux
backend.

The repl is a pure chat/generation loop with no shell or file-tool surface,
so like mira/riff it relays via quiescence + screen capture rather than the
`botmux send` wrapper: no skillsDir, empty systemHints, altScreen=false
(it redraws its input line in place, not via the alternate screen buffer).
Auth resolves from `mmx auth login` (~/.mmx/config.json); the whole ~/.mmx
dir is the authPath so a sandboxed first login persists.

Registered per src/adapters/cli/CLAUDE.md checklist:
- src/adapters/cli/minimax.ts (new)
- CliId union (types.ts)
- registry.ts: RAW_CLI_EXECUTABLES + import + export + switch case
- worker.ts CLI_DISPLAY_NAMES
- im/lark/card-builder.ts cliDisplayNames
- setup/bot-config-editor.ts CLI_ID_CHOICES (deepcoldy#30, appended) + CLI_DISPLAY_LABELS

Verified: tsc --noEmit clean; cli-adapters + cli-availability unit suites
pass (449); end-to-end PTY harness drove a real MiniMax-M3 reply through
buildArgs -> spawn -> writeInput -> output.
Region is resolved by mmx itself (--base-url > --region > ~/.mmx config,
default global); the adapter does not pass --region, so a bot follows the
region chosen at `mmx auth login`. Document how to run CN and global bots
on the same host via per-bot env MMX_CONFIG_DIR (separate credential dirs),
and note the sandbox authPaths caveat. Docs/comments only — no behavior
change. Also add minimax to the README adapter list.
@lijason1121
lijason1121 force-pushed the feat/minimax-cli-adapter branch from 0e7ce82 to fbe0e3d Compare September 7, 2026 12:04
@deepcoldy

Copy link
Copy Markdown
Owner

你好!PR #1300 的自动评审群已创建:加入评审群

目前你还不在自动拉群名单里,暂时无法自动邀请你入群。如果希望后续 PR 能自动拉你进评审群,请把你的 GitHub 账号和飞书信息补进这个名单文档,补好后后续复审会自动拉你进群。

这是自动流程,感谢贡献!

@deepcoldy

Copy link
Copy Markdown
Owner

Thanks for a genuinely careful adapter — the authPaths directory-level choice, the appended-at-the-tail CLI_ID_CHOICES numbering, the lazy resolvedBin, and the region/MMX_CONFIG_DIR documentation all match the house rules, and the header comment is more thorough than most adapters get. Two blocking issues came out of review, one of which the checklist genuinely did not warn you about.

1. A registration point outside the checklist makes the unit suite red

test/cli-id-roster-derivation.test.ts asserts two-way key equality between ALL_CLI_IDS and its local EXPECTED map (it deliberately does this at runtime, because test/ is not covered by tsconfig, so the Record<CliId, …> annotation is not enforced). minimax is missing there:

AssertionError: stale or missing entries in EXPECTED: -"minimax"

The fix is one line next to the other no-skill CLIs:

// Tool-less chat REPL (`mmx text repl`) — no skills dir of its own.
minimax: 'none',

Baseline check: the same file is 6/6 green on clean master and 1-failed with this PR, so it is caused by the change rather than flaky. Your reported 449 passed is accurate — cli-adapters + cli-availability really do pass; that file just isn't in those two. Worth noting this step is not in src/adapters/cli/CLAUDE.md's 7-step checklist, so following the docs would still miss it — it's probably worth adding as step 8 so the next adapter doesn't repeat it. Also, CI never actually ran here (fork runs are parked at action_required), so nothing flagged it automatically.

2. systemHints: [] is not the switch that suppresses the routing block

The comment says hints are omitted "same as mira / riff / mojo", but those three additionally set injectsSessionContext: true, and that is the flag session-manager.ts:1145 gates on:

const hints = adapter.injectsSessionContext ? [] : buildBotmuxShellHints(...)

adapter.systemHints has no reader in src/ at all (only tests, plus a comment noting it was superseded by the i18n path). Measured with buildNewTopicPrompt:

minimax  routing=true  botmux_send=true  session_id=true  len=1681
mira     routing=false botmux_send=false session_id=false len=33

So a tool-less chat REPL currently receives the full <botmux_routing> block instructing it to reply via botmux send and to pick one of --mention/--mention-back/--no-mention — none of which it can do.

2b. Compounding this: the first prompt is multi-line, and delivery splits it per line

writeInput is copied from hermes, but hermes drives a TUI composer while mmx text repl is a readline-style prompt. tmux send-keys -l sends \n as Enter (tmux-backend.ts says so in its own comment), and PtyBackend has no sendText, so the else branch (write(content) + '\r') applies there. Measured on both transports with a Node readline consumer on an isolated tmux socket: a 3-line message arrives as three independent submissions. The assembled first prompt is 24 lines, so submission #1 is just <botmux_routing> and the user's actual question lands around line 23.

One caveat on the fix, which we checked before suggesting it: switching to pasteText is not sufficient by itself. tmux paste-buffer -p only inserts \x1b[200~ … \x1b[201~ when the pane has requested bracketed-paste mode. Node's built-in readline never emits \x1b[?2004h, and with load-buffer + paste-buffer -d -p the same 3-line input still arrived as 3 submissions; with a consumer that does request it, the identical command delivered one bracketed chunk. So whether pasteText helps depends on how mmx's input layer is implemented — if it is plain readline, a different approach is needed (e.g. collapsing to a single line, or sending in parts and waiting on echo). Since you have a working mmx install and we don't, could you verify a genuinely multi-line first prompt end-to-end on the real CLI? That is the part we cannot check from here.

Suggested scope to unblock:

  1. Add minimax: 'none' to the roster test's EXPECTED.
  2. Verify multi-line first-turn delivery against real mmx, and fix the transport accordingly.
  3. Decide the injectsSessionContext stance explicitly and correct the comment either way — if minimax should behave like mira/riff, set the flag; if it should keep routing hints, the comment needs updating and the delivery fix in (2) becomes the load-bearing part.

For transparency: everything above was verified on a local rebase onto latest master (506b52d05), which drifted twice during review; your patch applies cleanly with no conflicts and no overlap with the drift. This is automated preliminary review feedback — a maintainer's own review is the final word, and points 2/3 in particular are worth their judgement rather than ours.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants