排队消息一多,队列面板无限增高把主对话顶出视野;且「立即」按钮响应要等整个前台执行真正停下(v3.14.x 桌面版)
摘要
任务执行中连续输入多条消息后,队列面板(ConversationQueuePanel)会随着条目数一直往上长,没有高度上限也没有滚动,把上面的对话内容整片推出视口。用户看不到自己在等的是什么回复,只能看到一列排队消息。
同时,点击某条的「立即」按钮(sendQueuedNow)后,界面长时间没有反馈。看代码后确认:这个动作会先中止当前前台执行并轮询等待其真正释放(preemptActiveTurnAndWait → waitForSessionIdle),前台执行越重等得越久,而按钮本身没有任何 loading 态。
两个问题叠在一起:队列越长面板越高,越看不清主对话;而想让某条快点发,又得等很久且没有任何进度提示。
环境
- ZCode 桌面版 v3.14.x(Windows 11,x64)
- 复现时使用默认 follow-up 模式(Queue)
- 源码核对于公开仓库
zai-org/ZCode(默认分支 main)
问题一:队列面板无高度上限,遮挡主对话
现象
在主对话里连续排队 8~12 条消息(截图里就是这种情况),队列面板会占掉大半个窗口高度,主对话被挤到看不见。
源码定位
packages/ui/src/v4/ConversationQueuePanel.tsx:328-331,容器类名:
className={cn(
"relative z-0 w-full overflow-hidden rounded-t-2xl border border-border bg-surface p-1 backdrop-blur-md",
"-mb-7 pb-7",
)}
条目列表在 ConversationQueuePanel.tsx:371:
<ul className="space-y-0.5">
整个面板只有 overflow-hidden,没有任何 max-h-*,<ul> 也没有 overflow-y-auto。因此条目数量直接决定面板高度,条目越多面板越高,把 timeline 往上顶。
期望行为
队列面板应该有高度上限并内部滚动,例如:
- 给容器加
max-h-[40vh](或按可用空间计算),<ul> 加 overflow-y-auto;
- 或者超过 N 条后折叠成「还有 N 条排队」的可展开摘要,默认只显示前 2~3 条;
- 无论多少条,主对话至少要保留可见区域。
截图里 12 条排队时,面板高度已经超过半屏。这类场景在长任务里很常见(用户想到什么就补一条),不是边缘情况。
问题二:「立即」按钮要等整个前台执行停下,且无加载态
现象
点「立即」后,按钮没有 loading、没有禁用态、没有任何反馈,要过一段时间才生效。前台执行越重(例如正在跑前台子智能体),等待越明显。
源码定位
UI 侧 packages/ui/src/v4/SessionPane.tsx:3226-3242,handleSendQueuedNow 只做了一次 focusTimelineToLatest() 然后 dispatchCommand("sendQueuedNow", ...),没有设置任何 pending/loading 状态:
const handleSendQueuedNow = useCallback(
(queueItemId: string) => {
const current = snapshotRef.current;
if (!sessionId || current === null) return;
focusTimelineToLatest();
void dispatchCommand("sendQueuedNow", { queueItemId }, sessionId, current.revision).then(...);
},
[dispatchCommand, focusTimelineToLatest, sessionId],
);
而按钮本身在 ConversationQueuePanel.tsx:214-234 也没有 busy 态,只有 disabled={rowLocked}(仅编辑中的那一行会锁)。
后端这条路径是「先停再发」:apps/zcode-cli/packages/bootstrap/src/zcode-protocol-v4/commands/handlers/session-flow.ts:410-438 的 preemptActiveTurnAndWait 会调用 stopActiveForegroundExecution,然后 await waitForSessionIdle(record)。该轮询函数在 session-flow.ts:396-407:
async function waitForSessionIdle(record: V4SessionRecordView): Promise<void> {
const deadline = Date.now() + IDLE_POLL_TIMEOUT_MS;
while (
record.activeAbortController !== undefined ||
record.app.runtime?.getActiveForegroundExecutionId?.() !== undefined
) {
if (Date.now() >= deadline) {
throw new V4SessionIdleTimeoutError(record.app.sessionId);
}
await new Promise((resolve) => setTimeout(resolve, IDLE_POLL_INTERVAL_MS));
}
}
其中 IDLE_POLL_INTERVAL_MS = 25、IDLE_POLL_TIMEOUT_MS = 5_000(session-flow.ts:23-24)。也就是说前台执行释放得慢时,用户要一直等到它真正 idle,界面上却什么提示都没有。
相关但不重复:#772 讨论的是这个按钮的语义(它会中止前台执行、取消前台子智能体,标签写 Steer 有误导)。本 issue 说的是交互反馈:等待期间 UI 完全没有状态提示。两者可以分别修。
期望行为
- 点击后按钮立即进入 pending 态(转圈 / 禁用 / 文案改成「正在切换…」),让用户知道点到了;
- 等待期间能看出「正在停止当前任务」这一步,而不是静默卡住;
- 如果最终超时(
V4SessionIdleTimeoutError),要在界面上明确报错,不能只写日志。
复现步骤
- 让 agent 跑一个耗时较长、带前台子智能体的任务(不要用
run_in_background)。
- 在任务执行中连续输入 8~12 条消息并回车,让它们进入队列。
- 观察:队列面板持续增高,主对话被顶出可视区域。
- 点击任意一条的「立即」。
实际结果:面板高度随条目数线性增长并遮挡主对话;「立即」点击后长时间无任何视觉反馈。
期望结果:面板有高度上限、内部可滚动(或折叠),主对话始终可见;「立即」点击后立刻有 pending 反馈,等待停止的过程可见,超时有明确报错。
影响
- 长任务里「一边看输出一边补需求」是主要用法,队列面板遮住主对话会直接让人失去上下文,只能反复滚动;
- 「立即」无反馈会让人以为没点上而重复点击,而每次点击都会触发一次前台执行中止流程。
补充
如果维护者认为「面板加 max-height + 内部滚动」是最小改动,我可以按 zai-org/ZCode 的贡献流程提 PR(需要确认目标文件与测试约定)。上面的行号基于 main 分支当前内容,如已变动请以实际为准。
排队消息一多,队列面板无限增高把主对话顶出视野;且「立即」按钮响应要等整个前台执行真正停下(v3.14.x 桌面版)
摘要
任务执行中连续输入多条消息后,队列面板(
ConversationQueuePanel)会随着条目数一直往上长,没有高度上限也没有滚动,把上面的对话内容整片推出视口。用户看不到自己在等的是什么回复,只能看到一列排队消息。同时,点击某条的「立即」按钮(
sendQueuedNow)后,界面长时间没有反馈。看代码后确认:这个动作会先中止当前前台执行并轮询等待其真正释放(preemptActiveTurnAndWait→waitForSessionIdle),前台执行越重等得越久,而按钮本身没有任何 loading 态。两个问题叠在一起:队列越长面板越高,越看不清主对话;而想让某条快点发,又得等很久且没有任何进度提示。
环境
zai-org/ZCode(默认分支main)问题一:队列面板无高度上限,遮挡主对话
现象
在主对话里连续排队 8~12 条消息(截图里就是这种情况),队列面板会占掉大半个窗口高度,主对话被挤到看不见。
源码定位
packages/ui/src/v4/ConversationQueuePanel.tsx:328-331,容器类名:条目列表在
ConversationQueuePanel.tsx:371:整个面板只有
overflow-hidden,没有任何max-h-*,<ul>也没有overflow-y-auto。因此条目数量直接决定面板高度,条目越多面板越高,把 timeline 往上顶。期望行为
队列面板应该有高度上限并内部滚动,例如:
max-h-[40vh](或按可用空间计算),<ul>加overflow-y-auto;截图里 12 条排队时,面板高度已经超过半屏。这类场景在长任务里很常见(用户想到什么就补一条),不是边缘情况。
问题二:「立即」按钮要等整个前台执行停下,且无加载态
现象
点「立即」后,按钮没有 loading、没有禁用态、没有任何反馈,要过一段时间才生效。前台执行越重(例如正在跑前台子智能体),等待越明显。
源码定位
UI 侧
packages/ui/src/v4/SessionPane.tsx:3226-3242,handleSendQueuedNow只做了一次focusTimelineToLatest()然后dispatchCommand("sendQueuedNow", ...),没有设置任何 pending/loading 状态:而按钮本身在
ConversationQueuePanel.tsx:214-234也没有 busy 态,只有disabled={rowLocked}(仅编辑中的那一行会锁)。后端这条路径是「先停再发」:
apps/zcode-cli/packages/bootstrap/src/zcode-protocol-v4/commands/handlers/session-flow.ts:410-438的preemptActiveTurnAndWait会调用stopActiveForegroundExecution,然后await waitForSessionIdle(record)。该轮询函数在session-flow.ts:396-407:其中
IDLE_POLL_INTERVAL_MS = 25、IDLE_POLL_TIMEOUT_MS = 5_000(session-flow.ts:23-24)。也就是说前台执行释放得慢时,用户要一直等到它真正 idle,界面上却什么提示都没有。期望行为
V4SessionIdleTimeoutError),要在界面上明确报错,不能只写日志。复现步骤
run_in_background)。实际结果:面板高度随条目数线性增长并遮挡主对话;「立即」点击后长时间无任何视觉反馈。
期望结果:面板有高度上限、内部可滚动(或折叠),主对话始终可见;「立即」点击后立刻有 pending 反馈,等待停止的过程可见,超时有明确报错。
影响
补充
如果维护者认为「面板加 max-height + 内部滚动」是最小改动,我可以按
zai-org/ZCode的贡献流程提 PR(需要确认目标文件与测试约定)。上面的行号基于main分支当前内容,如已变动请以实际为准。