[Bug][desktop] 顶栏会话菜单(标题右侧 ⌄)展开被一次 RPC 阻塞且无加载反馈,点击后表现为"没反应"
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
評価
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 初心者へのやさしさ
- 45/100
- issue の種類
- バグ
- 明瞭さ
- 明確に書かれている
- 活発さ
- 活発
- 技術スタック
- typescript
調査の方向性
The issue analyzes the shipped desktop bundle, but does not identify source files or tests, so first locate the session menu and fork menu hook in the repository. Trace how opening the top bar and sidebar menus waits for fork options, then check the existing loading state and tests. Done means the menu opens promptly, fork actions show a useful loading or failure state, and repeated clicks do not prevent it from opening.
索引モデルが issue の本文から書いたものです。
説明
Product or interface
Desktop app
Version
MiniMax Code Desktop 3.1.4.189 (macOS build)
Platform
macOS
OS version and architecture
macOS 26.3.1 (build 25D2128), arm64
Issue area
UI / UX
Desktop log upload ID (optional)
No response
Steps to reproduce
- 打开 MiniMax Code Desktop,进入任意一个本地会话(非云端会话)。
- 顶栏会话标题右侧有一个
⌄箭头按钮(data-testid="chat-topbar-session-menu-trigger")。 - 点击该箭头。
观察两点:
- 触发方式没有提示:鼠标悬浮在箭头上只会有一个浅灰背景和图标颜色变化,不会弹出菜单;必须点击才会展开。全程没有任何 tooltip / 文案说明这一点。
- 点击后不是立即响应:点击和菜单真正出现之间,存在一段明显可感知的"空窗期"(空窗期长短取决于一次本地 RPC 的耗时)。本地 runtime 正在跑任务、刚启动尚未就绪、或会话尚未注册时,这个空窗期会被显著拉长,表现就是"点了没反应";连点几次反而更糟。
Expected and actual behavior
Expected: 点击箭头后菜单应立即展开(至多对"复制为新会话 / 新工作树"这两项显示加载态),且悬浮时有 tooltip 说明这是可点击的下拉菜单。
Actual:
- 打开动作被一次异步 RPC 整体阻塞。 菜单不是点击即开,而是要先等一次
GetSessionForkOptionsRPC 返回后才展开;等待期间界面零反馈。 - 等待期没有任何加载/禁用/旋转等可见反馈,按钮只有
aria-label(zh:会话操作),没有title、没有 tooltip、没有aria-expanded,所以用户既不知道触发方式,也不知道系统是否已经收到点击。 - 重复点击会互相作废。 打开流程用了一个自增计数器做守卫,加载期间再次点击会让前一次待处理的"打开"失效,菜单要等最后一次请求返回才出现 —— 越点越慢,主观感受就是"按钮坏了"。
- UI 层没有超时与降级。 整个 gate 没有
Promise.race超时兜底,本地 runtime 忙或未就绪时,点击可以长时间表现为完全无响应。 - Promise 链没有
.catch()。 目前底层loadMenuOptions内部吞掉了异常所以不会 reject,但一旦该调用链任一环抛出,就会变成 unhandled rejection,菜单永远不打开且没有任何报错提示。 - 可发现性缺失 + 目标语义冲突。 箭头命中区只有 30×30;而点击标题文字(
data-testid="chat-topbar-title-button")触发的是内联重命名,不是菜单 —— 最显眼的入口做的是另一件事,真正的主菜单入口却没有任何指引。
Root cause analysis (analyzed from the shipped 3.1.4.189 bundle)
分析对象:
/Applications/MiniMax Code.app/Contents/Resources/app.asar→out/_next/static/chunks/(桌面端 UI 未开源,以下为对已发布产物的静态分析)。
1) 触发方式是"点击",不是"悬浮"。
-
顶栏触发按钮:
chunks/75788.db1775b1813df733.js<Dropdown menu={nI} placement="bottomLeft" compact open={ts} onOpenChange={tL} ...> <button type="button" aria-label={t("chat_panel.session_menu_aria")} // zh: 会话操作 data-testid="chat-topbar-session-menu-trigger" className={eG(ts)}> <ChevronDown size={16} /> </button> </Dropdown> -
共享 Dropdown 封装(webpack module
13376,位于chunks/90321-e50007b0d4d62264.js):trigger: L = ["click"], // 默认值 ... <AntDropdown trigger={L} open={ei} onOpenChange={es} ... /> // trigger 原样透传给 antd顶栏调用处没有传
trigger,因此为 click-only。悬浮时的hover:bg-bg_interaction_tertiary_hover只是背景色反馈,不触发展开。
2) 为什么"点了没反应":打开被一次 fork 选项预取整体 gate 住。
顶栏容器(chunks/75788.db1775b1813df733.js):
const [ts, ti] = useState(false); // ts = 菜单是否展开
const tr = useRef(0); // 请求序号
const tF = onMenuOpen; // fork 菜单预取
const tL = useCallback((open) => {
const token = ++tr.current;
if (!open) { ti(false); tF(false); return; }
ti(false); // ① 先关掉
tF(true).then(() => { // ② 等一次异步预取
if (tr.current === token) ti(true); // ③ 才真正展开
});
}, [tF]);
tF 来自 fork 菜单 hook(webpack module 82610):
onMenuOpen: async (open) => {
open && enabled && await forkMenuStore.getState().loadMenuOptions({ source, sessionId });
}
loadMenuOptions → service.getForkOptions() → thrift DesktopService.GetSessionForkOptions,
GET /minimax-desktop/api/v1/session/:id/fork/options(transport: "metadataOnly"),即一次到本地 runtime 的 RPC。
于是 "展开菜单"被绑死在"预取 fork 选项"上:本地 runtime 越慢,点击后菜单出现得越晚,慢到一定程度就是"完全没反应"。
3) 同一模式也存在于侧边栏会话菜单(chunks/app/(pages)/(mavis)/archon/page-f0f825d0d4c82846.js):
tc = (open) => {
const token = ++eU.current;
if (!open) { eO(false); eE(false); return; }
eO(false); eW(false);
eE(true).then(() => { if (eU.current === token) eO(true); });
};
两者共用同一个 fork-menu store,建议一并修复。
4) 其他相关事实
- hook 已经暴露了
loading(以及available/worktreeVisible),但顶栏完全没有使用loading。 - 该 gate 只在本地会话且会话支持 fork 时生效(
enabled && isLocal(source) && !isRemote());云端会话会立即展开 —— 这也解释了为什么这个问题只在本地会话上稳定复现。 - 箭头按钮尺寸为
size-[30px] min-h-[30px] min-w-[30px],展开态只切换bg-bg_interaction_tertiary_selected/text-icon_default_primary;chevron 图标不会旋转,没有aria-expanded。
Proposed fix
按优先级:
- 点击即展开,异步只补数据。
onOpenChange(true)时立刻ti(true);复制为新会话 / 新工作树两项先以 loading 骨架呈现,GetSessionForkOptions返回后再填充或启用。用户感知延迟降为 0。 - 给 RPC 加超时与降级。
Promise.race([rpc, timeout(1500~2000ms)]);超时按canFork=false降级(该项置灰),不再阻塞整个菜单。 - 补可见反馈与可发现性。
- 触发器加
aria-expanded/aria-busy;pending 时显示 spinner 或让 chevron 旋转。 - 加 tooltip(如"会话菜单")明确这是点击触发;悬浮时 chevron 可轻微位移/加深,给出"可点"的暗示。
- 展开态让 chevron 旋转 180°,让开合状态一眼可辨。
- 触发器加
- 修掉重复点击互相作废的竞态。 用 request-id +
AbortController取代自增计数器守卫:旧的请求取消,而不是仅仅被忽略,保证"最后一次点击一定打开"。 - 补
.catch()。 失败时 toast 提示,并且仍然打开菜单(其余菜单项不依赖 fork),避免静默失败。 - 统一修复侧边栏会话菜单,复用同一 hook 与同一套降级逻辑。
- (可选,产品决策) 让标题区域本身承载菜单(如点击标题 = 菜单、双击 = 重命名),或支持右键菜单,减少"标题是重命名、箭头才是菜单"的语义冲突。
Redacted error summary
No response
Screenshots
(附:顶栏标题与 ⌄ 按钮、以及展开后的会话菜单截图)
附:给维护者的简短结论
- 触发方式:点击(不是悬浮)。
module 13376的trigger默认["click"],顶栏未覆盖。 - "不灵敏"的根因:菜单展开被
loadMenuOptions()(一次到本地 runtime 的 thrift RPC)整体 gate 住,且 UI 层无超时、无 loading 反馈、无 catch,并带一个会让重复点击互相作废的计数器守卫。 - 最小可行修复:先展开菜单 + fork 项 loading 态,再补超时降级与
.catch()。
- 主要言語
- TypeScript
- スター
- 2k
- フォーク
- 259
- 平均マージ
- 11時間
- マージ済み PR(30日)
- 81
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートあり
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
MiniMax-AI/minimax-code のほかの issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
MiniMax-AI/minimax-code#507 ·
メンテナーはふだん 1 日以内に返信
-
bug needs-triage tui
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
MiniMax-AI/minimax-code#481 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
bug cli documentation needs-triage
難易度 2/5 1〜3時間 初心者へのやさしさ 84/100
MiniMax-AI/minimax-code#299 · コメント 3 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 4/5 3〜5日 初心者へのやさしさ 55/100
MiniMax-AI/minimax-code#527 ·
メンテナーはふだん 1 日以内に返信
-
難易度 4/5 3〜5日 初心者へのやさしさ 55/100
MiniMax-AI/minimax-code#526 ·
メンテナーはふだん 1 日以内に返信
MiniMax-AI/minimax-code の issue をすべて見る
似ている issue
-
level/task type/bug
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
wazuh/wazuh-dashboard-plugins#9508 ·
メンテナーはふだん 1 日以内に返信
-
Testnet EOL page links Zonescan mainnet対応中かも @napelvs が今日担当しました。 オープン
難易度 1/5 1時間未満 初心者へのやさしさ 76/100
-
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
Azure-Samples/azure-search-openai-demo#3249 ·
メンテナーはふだん 1 日以内に返信
-
[Docs] docs/architecture.mermaid leaves out 21 of the 51 src/ directories対応中かも @uyg7x が今日担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
メンテナーはふだん 1 日以内に返信
-
enhancement status:needs-triage
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
dongdongbh/Mindwtr#1438 ·
メンテナーはふだん 1 日以内に返信