[Bug][desktop] 顶栏会话菜单(标题右侧 ⌄)展开被一次 RPC 阻塞且无加载反馈,点击后表现为"没反应"
Los mantenedores suelen responder en 1 día
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Aptitud para principiantes
- 45/100
- Tipo de issue
- Error
- Claridad
- Bien especificado
- Estado de actividad
- Activo
- Stack tecnológico
- typescript
Línea de trabajo
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.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
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()。
- Lenguaje dominante
- TypeScript
- Estrellas
- 2k
- Forks
- 259
- Merge medio
- 13 h 16 min
- PR fusionados (30 d)
- 63
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Tiene una plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de MiniMax-AI/minimax-code
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
MiniMax-AI/minimax-code#507 ·
Los mantenedores suelen responder en 1 día
-
bug needs-triage tui
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
MiniMax-AI/minimax-code#481 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
bug cli documentation needs-triage
Dificultad 2/5 1-3 horas Aptitud para principiantes 84/100
MiniMax-AI/minimax-code#299 · 3 comentarios ·
Los mantenedores suelen responder en 1 día
-
Dificultad 5/5 Más de una semana Aptitud para principiantes 35/100
MiniMax-AI/minimax-code#540 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 4/5 3-5 días Aptitud para principiantes 38/100
MiniMax-AI/minimax-code#539 ·
Los mantenedores suelen responder en 1 día
Todos los issues de MiniMax-AI/minimax-code
Issues similares
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
awesome-dsh-plugin/awesome-dsh-plugin#9184 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 85/100
farion1231/cc-switch#8829 ·
Los mantenedores suelen responder en 1 día
-
[core-client] Remove unused hand-maintained transport helpers after the definition-table cutoverAbiertodoc-audit enhancement
Dificultad 2/5 1-3 horas Aptitud para principiantes 88/100
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 85/100