[Bug][desktop] 顶栏会话菜单(标题右侧 ⌄)展开被一次 RPC 阻塞且无加载反馈,点击后表现为"没反应"
Les mainteneurs répondent en général sous 1 jour
Personne n'a encore pris cette issue.
Évaluation
- Difficulté
- 4/5
- Temps estimé
- 3-5 jours
- Accessibilité débutants
- 45/100
- Type d'issue
- Bug
- Clarté
- Clairement spécifiée
- Activité
- Active
- Stack technique
- typescript
Piste de recherche
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.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Description
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()。
- Langage dominant
- TypeScript
- Étoiles
- 2k
- Forks
- 259
- Merge moyen
- 11 h
- PR mergées (30 j)
- 81
Préparer son environnement
- Aucun Dockerfile ni fichier Docker Compose
- Propose un modèle de pull request
- Lire le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Autres issues de MiniMax-AI/minimax-code
-
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
MiniMax-AI/minimax-code#507 ·
Les mainteneurs répondent en général sous 1 jour
-
bug needs-triage tui
Difficulté 2/5 1-3 heures Accessibilité débutants 72/100
MiniMax-AI/minimax-code#481 · 1 commentaire ·
Les mainteneurs répondent en général sous 1 jour
-
bug cli documentation needs-triage
Difficulté 2/5 1-3 heures Accessibilité débutants 84/100
MiniMax-AI/minimax-code#299 · 3 commentaires ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 4/5 3-5 jours Accessibilité débutants 55/100
MiniMax-AI/minimax-code#527 ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 4/5 3-5 jours Accessibilité débutants 55/100
MiniMax-AI/minimax-code#526 ·
Les mainteneurs répondent en général sous 1 jour
Toutes les issues de MiniMax-AI/minimax-code
Issues similaires
-
Difficulté 2/5 1-3 heures Accessibilité débutants 76/100
Nimblesite/SharpLsp#468 ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 2/5 1-3 heures Accessibilité débutants 72/100
Les mainteneurs répondent en général sous 1 jour
-
Bundled uv is never updated and trusts the compromised eMudhra certificatesPeut-être pris @FabienDanieau l’a pris aujourd’hui. Ouvertebug
Difficulté 2/5 1-3 heures Accessibilité débutants 76/100
-
bg_wait's blocking mode (stopOnAttention: false) is under-documented and effectively undiscoverableOuverte
Difficulté 2/5 1-3 heures Accessibilité débutants 66/100
nicobailon/pi-subagents#3019 ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 2/5 1-3 heures Accessibilité débutants 66/100
db-ux-design-system/core-web#8613 ·
Les mainteneurs répondent en général sous 1 jour