Repository navigation
fix(minimax-bot): fold the earlier bubbles of a long reply, bottom-left reply actions - #48
Conversation
The reaction, copy, quote and open-session buttons used to sit inside the last bubble, pinned to its top-right corner. A long reply therefore pushed them out of reach while the reader was still at the end of the text, which made quoting a long answer awkward. - Render the action row as a sibling below the bubble, aligned to its left edge, so it always stays under the last line of the reply. - Keep the reaction indicator inside the bubble at its bottom-left, which puts it directly above the action row, and paint it with the app's own tag colours instead of a fixed brand-colour pill so it follows the light and dark themes. - Give the transcript enough bottom padding that scrolling to the end never clips the action row of the last reply. Bumps the package to 0.7.5 and aligns the MCP serverInfo version with the manifest. Assisted-by: mavis reason:minimax-bot-reply-actions
…lance The strip put the owner and the state in the same sentence as the task, then truncated the task to one line, so a busy queue read as a wall of near identical rows. - Lead each row with the task (up to two lines) and put the owner, the state and the elapsed time on a second line. - Tell the states apart by their dot: quiet while queued, amber while it waits, accent while it runs. - Keep the stop action reachable, but out of the way until the row is looked at. - Fold a queue of more than three tasks into one line that can be expanded. Assisted-by: mavis reason:minimax-bot-task-strip
…orded part The Host opens a text part for every assistant turn between two tool calls, so a reply that ran a dozen tools painted a bubble per part. A real group message in the CodeMap chat has 118 text parts, and the bubbles filled the screen so the conversation above was out of reach. Join the text parts of a message into one bubble, the way the server joins them when it stores the message text. The reaction badge follows that single bubble.
replaceChildren renders a null argument as the text "null", so every chat without a background job showed that word above the composer. The fold button is appended on its own now, and only when there is something to fold.
…crollable summary The Host records a text part for every assistant turn between two tool calls, so a reply that worked for a while arrives with dozens of parts, and one bubble per part filled the screen: a real message in our own Bot history carried 479 parts and 118 text segments. The earlier bubbles keep their own shape, but they move into a folded area under the reply: one line says how many of them there are, and opening it shows them in a fixed height area with its own scrollbar, so the conversation above stays in reach. The answer itself is never folded, and a reply with a few parts is unchanged. This replaces the earlier attempt to join the parts into a single bubble: that changed how a reply reads compared to the rest of the app, and the fold keeps the original bubbles.
…e open The fold took every bubble but the answer out of sight, so a collapsed reply showed nothing of the work that produced it. The newest three bubbles now stay where the flat layout put them, and only the earlier ones fold behind the summary. A bubble of such a reply also tells on hover what it said, the way the task rows and the attachments do. A short reply keeps the official markup untouched.
MyPrototypeWhat
left a comment
There was a problem hiding this comment.
APPROVE (head 3f74c9d)
Thanks for the clear bilingual write-up and the latest fold direction. Scope stays only plugins/minimax-ai/minimax-bot/ (9 files). Official package is 0.7.5 with plugin.json, package.json, and MCP serverInfo aligned. Author on the PR is July-X (first-time contributor); commits are authored as Z-starts / 4Dim.
What changed vs prior head 4d3b258
One commit (3f74c9d) adjusts the fold so a collapsed long reply still shows recent work:
- When a reply has more than 3 text parts (
FOLD_AFTER_PARTS), earlier text bubbles move into a closed<details class="bubble-fold">; the newest three stay in the open (answer last, with the reaction badge), instead of folding everything but the last answer. - Fixture with 12 process steps + answer → 10 bubbles in the fold / 3 open (
Step 10,Step 11,The answer). - Bubbles of a folded reply (inside and outside the fold) get a hover
titleviahintOf(≤160 chars); short replies keep official markup with no title. Fold summary also carriesfold.hint. - Reply actions, themed reaction indicator, task-strip layout, and the
replaceChildren(null)→ literal"null"fix are unchanged from4d3b258.
Checked
- Fold / collapse UX (
miniapp/client/app.jsfoldView/partViews,app.css.bubble-fold*): fold only whentextParts.length > 3;textParts.slice(0, -FOLD_AFTER_PARTS)for earlier parts; newest three outside; starts closed; fixed-height bodymax-height: min(320px, 40vh)+overflow-y: auto; EN/ZHfold.show/fold.hide/fold.hint. - Hover summaries: titles on folded and open bubbles of a long reply; short replies untouched.
- Bottom-left reply actions:
.msg-toolsremains a sibling under.bubble-wrap(not absolutely positioned on the bubble); feed bottom padding40pxstill protects the last row. - Task strip: task-first layout, phase order (running → waiting → queued), queue fold after 3, fold control appended separately so empty chats stay blank — still present.
- Security (touched code): client UI + version string only. No credential / Host DB access; approvals still require a user click for
allowOnce(renderApprovalsunchanged). - README: “Reply actions” and “Folded working messages” bullets match the newest-three-open behaviour (including hover titles).
Tests (this box, Node 22.14.0, Asia/Shanghai)
npm run validate→plugins/minimax-ai/minimax-bot: OK,repository: OK- Root
npm test→ 69/69 - Package
node --test 'tests/**/*.test.mjs'→ 207/207 (includes the new hover-title case; fold / actions / task-strip client cases all pass)
Author’s Windows-only timeouts are not reproduced on Linux here.
Non-blocking notes
- Event rows interleaved among earlier text parts still land in the open stream after the fold (
partViewspushesfoldViewfirst, then walks remaining parts). Comment atapp.js~1001 says “Keep part order exactly as recorded”; order for events that sat between folded texts is not identical to the raw parts list. Unusual in practice; fine unless mid-reply event chips must stay between process bubbles. - Overlap with #49. Both touch official
minimax-botversion / README. This PR aligns all three version sites to 0.7.5; #49 (as last reviewed) still hadplugin.json0.7.5 vspackage.json0.7.4 and different engine retry work. Whichever merges second needs a README/version reconcile — review of #48 stands on its own.
No blockers under the repo review policy (check clean, README accurate, no Host/user-data damage). Approving.
…rows The strip was the one part of this branch that changed the official look instead of adding a layer on top of it: two lines per job, different wording, a borderless stop button and a folded queue. The rows render the way the official build does again, one line each, with the stop button at the end of the row. Measured against the official build on the same data: a row is 42px high in both, the strip is 88px high in both, and the stop button sits 9px from the right edge in both. The fold of the long reply and the reply actions stay as they are.
The README already says where the reply actions sit; the indicator above that row now wears the app's own tag colours, so the text says so too.
MyPrototypeWhat
left a comment
There was a problem hiding this comment.
Re-approving at 78fc2d3.
Re-checked the two new commits since my approval at 3f74c9d:
- f750ea2: the background task strip goes back to the official one-line rows (dot, "who is doing what" text, elapsed time,
btn smStop button). The queue folding, phase sorting andhelpersExpandedstate are removed cleanly, and the test now covers the restored row shape, hover title and the queued row with no elapsed time. Againstmain, the strip code and CSS now match upstream again, so the PR is back to only the fold/reply-action changes. - 78fc2d3: README-only note about the themed reaction indicator. Fine.
Checks: npm run check at repo root passes (validate OK, 69/69 tests). node --test tests in plugins/minimax-ai/minimax-bot passes 207/207.
One small, non-blocking nit: strings-app.js now has 'helper.strip' twice in both the zh and en blocks, because the restore re-added a key that was already there. The values are identical, so nothing changes at runtime, but compared with main it's a stray extra line in each locale. Worth dropping the duplicate if you touch the file again.
Thanks!
维护者 review 指出的问题: 1. **`max` 显示成 `2/NaN`**(真 bug,我引入的): 删掉 `this.retryMaxAttempts` 的赋值时漏改了**用法**, `this.retryMaxAttempts + 1` ⇒ `undefined + 1` = NaN。 ⇒ 改用 `this.retryDelays.length + 1`(与上游原本的写法一致)。 2. **清掉还写着「无限重试」的旧注释** —— 现在统一口径: 暂时性错误**同样受次数上限约束**(第 10 次之后把原始错误暴露给用户)。 3. **版本号三处对齐 0.7.5**:`plugin.json` / `package.json` / `mcp.mjs` 的 `serverInfo.version` 之前分别是 0.7.5 / 0.7.4 / 0.7.0。 (与 MiniMax-AI#48 的 0.7.5 撞号是预期的,两边都需要维护者定顺序。) 测试:121 项 / 114 通过 / 7 失败 —— 与上游 main 完全相同(那 7 个是上游自己的失败)。
What changed / 改动内容
The Host records a text part for every assistant turn a Bot takes between two tool calls, so a reply that worked for a while arrives with dozens of parts. The page painted one bubble per part, and the bubbles filled the screen: a real message in our own Bot history carried 479 parts and 118 text segments, so the conversation above it was out of reach. The official flat layout is untouched. The newest three bubbles stay in the open, exactly where the flat layout put them, and only the bubbles before them move into a folded area above them. One line says how many of them there are, and opening it shows them in a fixed height area with its own scrollbar, so the feed around it does not grow. A reply with a few parts is unchanged. In the Bot history we looked at, 63 of 91 replies have more than ten text parts, so this is the normal case rather than an edge case.
A bubble of such a reply also tells on hover what it said: it carries a title with its own text, the way the task rows and the attachments already do. The reply actions keep the official behaviour on top of that: hovering the message still brings the reaction, copy, quote and open-session buttons out, each with its own title.
The action row of a reply (reaction, copy, quote reply, open session) used to be pinned inside the last bubble, at its top-right corner. A long reply therefore pushed the buttons out of reach while the reader was still at the end of the text, which made quoting a long answer awkward. The action row is now a sibling below the bubble, aligned to its left edge, so it always stays under the last line of the reply. The reaction indicator stays inside the bubble at its bottom-left, which puts it directly above the action row, and it is painted with the app's own tag colours (
--tagsurface,--line-strongborder,--mutedink) instead of a fixed brand-colour pill, so it follows the light and dark themes. The transcript also keeps enough bottom padding that scrolling to the end never clips the action row of the last reply. The package version is bumped to 0.7.5, and the MCPserverInfoversion is aligned with the manifest.The background task strip above the composer keeps the rows the official build draws: one line per job, the owner and the state in the same sentence as the task, and the stop button at the end of the row. On top of that a busy queue now folds: the first three rows stay in the open, the rest fold into one line that says how many jobs are left, and a click brings them back. The button sits below the rows' own scroll area, so it stays reachable however long the queue is, and the strip keeps the height budget the official one had. A version of this branch that laid the rows out differently was taken back out, because it changed the official look instead of adding a layer on top of it.
宿主会在两次工具调用之间的每一次助手回合记一个文本 part,所以一条干了活的回复会带着几十个 part 回来,页面上一个 part 画一个气泡,气泡就把屏幕占满了:我们自己的 Bot 历史里就有一条消息带 479 个 part、118 个文本段,上方的对话根本看不到。官方的平铺形态没有动。最新三个气泡留在外面,就是平铺时它们本来的位置,只有更早的那批收进上方的一个可收起区域:折叠时只有一行,写明里面有多少条;展开后是一个固定高度的区域,里面自己带滚动条,所以外面的消息流不会跟着变长。只有几个 part 的回复也完全照旧。我们统计的那批 Bot 历史里,91 条回复有 63 条超过 10 个文本段,所以这是常态而不是个例。
这样一条回复里的气泡,鼠标悬停时会说出自己讲了什么:气泡带上自己那段文字的 title,跟任务行、附件用的就是同一套做法。回复的操作按钮在官方原有行为之上照旧:悬停整条消息,表情回复、复制、引用回复、打开会话这几个按钮照样浮出来,各自带自己的 title。
回复的操作按钮(表情回复、复制、引用回复、打开会话)原来嵌在最后一个气泡里,固定在气泡右上角。回复一长,按钮就被顶到内容开头,读者看到结尾时按钮已经不在手边,引用回复就不好操作。现在按钮行是气泡下方的兄弟节点,与气泡左边缘对齐,回复不管多长都停在最后一行下面。表情指示器仍在气泡内的左下角,几何上正好位于按钮行上方,配色换成这个 App 自己的标签语言(
--tag底、--line-strong描边、--muted文字),不再用写死的品牌色药丸,明暗两套主题各自取值。消息区也补足了底部留白,滚到末尾时最后一条消息的按钮不会被裁掉。包版本升到 0.7.5,MCPserverInfo的版本号与 manifest 对齐。输入框上方的后台任务条保留官方的样子:每个任务一行,谁和什么状态跟任务写在同一句里,停止按钮在行尾。在这之上加了一层:任务多的时候,前三行留在外面,其余折成一行,写明还剩多少个任务,点一下就展开。按钮放在行自己的滚动区下面,所以队列再长也点得到,整条的高度预算也还是官方的那个。这条分支上曾经把任务条改成两行式的那一版已经撤掉了,因为它是改动官方长相,而不是在官方做法外面加一层。
Test environment and results / 测试环境与结果
Windows 11, Chrome 156, MiniMax Code 3.1.2.
npm run checkreportsplugins/minimax-ai/minimax-bot: OKwith 0 errors and the root contract tests pass 69/69; the package suitenode --test testsgives 205 passed and 2 failed out of 207. The package was also installed locally in MiniMax Code (as a renamed copy, so the official MiniMax Bot install stays untouched) and opened in the client with a reply of the same shape as the real one seeded into it: 237 parts and 119 text segments, 116 of them folded behind a one line summary, the newest three in the open, and the folded area scrolling on its own.A real Chrome was driven over the DevTools protocol against the same build: the fold is closed when the reply arrives, the newest three bubbles are in the open, hovering a bubble brings the reply actions out (the action row's opacity goes from 0 to 1) and every bubble of such a reply carries its text as a title, while a reply with a few parts keeps the official markup and gets no title. The group chat with the 119 segment reply folds 116 bubbles into an area that is 320 px tall with a scroll height of 21 203 px, so the feed around it does not grow.
The task strip was compared with the official build on the same seeded data, both rendered in a real Chrome: a job row is 42 px high in both, the strip with two queued jobs is 88 px high in both, the row reads the same way in both, and the stop button sits 9 px from the right edge of the row in both. Under a queue of thirty jobs the folded strip is 166 px high, it shows the first three rows plus one line that says how many jobs are left, and opening it brings all thirty rows back inside the official 280 px budget, with the fold button below the rows' own scroll area so it stays reachable.
Four tests cover the fold: a long reply folds its earlier bubbles away, keeps the newest three in the open with the reaction indicator on the answer, and shows the same bubbles again when the fold is opened; a folded reply tells on hover what every bubble said, while a short reply keeps the official markup and gets no title; a short reply keeps its bubbles in the open and gets no fold at all; and a static assertion pins the fixed height and the scrollbar on the folded area, so the area cannot grow the feed. The task strip test pins the official rows and the fold on top of them: a row is one line, it carries the whole task as its hover hint, the first three rows stay in the open while the rest of the queue folds into one line that can be expanded, and the strip stays empty when no job is running. The earlier cases still hold: a multi-line reply keeps the action row as the bubble's last sibling, keeps the reaction indicator inside the bubble, and still quotes the whole reply; a static assertion makes sure the indicator rule may only use theme variables.
The two failing package tests are pre-existing on this machine and reproduce on the unmodified base commit:
restart after questionnaire …andrestart after dependency verification …both time out after 12 s on Windows. A third one,avatar library persists imports …, fails intermittently on a concurrent avatar upload and also reproduces on the unmodified base commit.Windows 11、Chrome 156、MiniMax Code 3.1.2。
npm run check报plugins/minimax-ai/minimax-bot: OK,0 error,根契约测试 69/69 通过;包内node --test tests是 207 条里 205 通过、2 失败。另外把包以本地副本装进 MiniMax Code(改了名字,官方 minimax-bot 安装不受影响),并往里塞了一条与真实数据同形的回复(237 个 part、119 段文本)后在客户端打开手测:116 段收在一行摘要后面,最新三个留在外面,折叠区自己滚动。另外用 DevTools 协议驱动真实 Chrome 跑了同一个构建:回复到达时折叠区是关着的,最新三个气泡在外面,悬停气泡会把回复操作按钮唤出来(操作行的透明度从 0 变成 1),这条长回复里的每个气泡都带着自己那段文字的 title;而只有几个 part 的回复保持官方原样,不加 title。群里那条 119 段的回复折进去 116 个气泡,折叠区高 320 px、内部内容高 21 303 px,外面的消息流不会跟着变长。
任务条跟官方版在同一份造数据上做了对照,两边都在真实 Chrome 里渲染:单条任务行两边都是 42 px 高,两条排队任务的任务条两边都是 88 px 高,行的文字一样,停止按钮离行右边缘都是 9 px。
折叠这块有四条用例:一条验证长回复把前面的气泡收起来、最新三个留在外面且答案上带着表情指示器、展开后还是那些气泡;一条验证折叠的回复悬停时能说出每个气泡讲了什么,而只有几个 part 的回复保持官方原样、不加 title;一条验证只有几个 part 的回复不折叠、气泡照旧在外面;一条静态断言钉住折叠区的固定高度和滚动条,防止它把消息流撑长。任务条的用例钉住官方的行和加在上面的折叠:一行就是一行,整条任务作为悬停提示,前三行留在外面、其余队列折成一行可展开,没有后台任务时任务条是空的。其余旧用例仍然成立:多行回复的动作行仍是气泡的最后一个兄弟节点、指示器仍在气泡内、引用回复依然带出整条内容;指示器规则只允许用主题变量。
那两条失败的包内用例是本机 Windows 上既有的问题,在未改动的基线提交上同样复现:
restart after questionnaire …与restart after dependency verification …在 Windows 上 12 秒超时。第三条avatar library persists imports …偶尔挂在并发导入头像上,在未改动的基线提交上同样复现。Unverified / 未验证
The package tests were not run on macOS or Linux; only Windows was available here. The long reply was checked by hand in a locally installed copy seeded with a reply of the same shape as the real one, and over the DevTools protocol in a real Chrome; the official install was not replaced, so the official MiniMax Bot still shows the old rendering until this is merged and released. The hover hint itself was verified through the DOM (the title attribute and the action row's opacity), not as a rendered tooltip. The rest of the package is unchanged.
包内测试没在 macOS / Linux 上跑过,本机只有 Windows。长回复是在本地副本里手测的,数据是与真实数据同形的一段回复,也在真实 Chrome 里用 DevTools 协议验过;官方安装没有被覆盖,所以官方 MiniMax Bot 在合并发布之前仍是旧的渲染。悬停提示本身是按 DOM 验的(title 属性与操作行的透明度),没有截到提示框渲染出来的样子。包内其它部分没有改动。