Skip to content

fix(web-shell): show server queue status for pending messages - #8065

Merged
wenshao merged 2 commits into
QwenLM:mainfrom
wenshao:fix/web-shell-server-queue-status
Jul 30, 2026
Merged

fix(web-shell): show server queue status for pending messages#8065
wenshao merged 2 commits into
QwenLM:mainfrom
wenshao:fix/web-shell-server-queue-status

Conversation

@wenshao

@wenshao wenshao commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator

What this PR does

Shows an explicit “Queued on server...” status above the composer after a message has been accepted into the daemon's per-session queue but has not started running yet. The existing “Submitting...” status remains visible while admission is still in progress. Server-queued messages remain editable and removable, while the mid-turn insert action is hidden until its transfer semantics can guarantee that an accepted-but-undrained message stays visible and recoverable.

Why it's needed

A queued message can already be visible in the Web Shell while the daemon is still waiting to dispatch it. Without a visible server-queue state, users can interpret the lack of processing feedback as a lost message and may submit it again.

Reviewer Test Plan

How to verify

Start a turn, submit another message while that turn is still running, and confirm the queued message appears above the composer with “Queued on server...” after admission completes. Confirm that “Submitting...” is shown before admission completes, that the server-queued state does not show an activity spinner, that the insert action is hidden, and that delete and edit remain enabled. Once the daemon starts the queued prompt, confirm it leaves the queue display and proceeds through the normal turn UI.

Automated verification completed locally: npx vitest run client/components/QueuedPromptDisplay.test.tsx (14 tests), targeted ESLint for the changed files, npm run build, and npm run typecheck.

Evidence (Before & After)

Before: an accepted message waiting in the daemon queue had no state label, which could make it appear lost.

After: the queued message displays “Queued on server...” / “服务器排队中...” above the composer until dispatch begins.

The screenshot below comes from the Chinese UI of a real local daemon and the real Web Shell client, not the mock-daemon visual harness. The first prompt requested a 45-second shell wait and remained active while the second prompt was submitted through the browser. The daemon's /pending-prompts response reported the first prompt as running and the second prompt as queued; the browser visibly rendered “服务器排队中...” with only delete and edit actions.

Real daemon E2E showing 服务器排队中 with delete and edit actions only

Tested on

OS Status
🍏 macOS
🪟 Windows ⚠️
🐧 Linux ⚠️

Environment (optional)

macOS local workspace. The visual evidence was captured in headless Chromium against the real source daemon and real Vite-served Web Shell client. Component tests used Vitest and jsdom.

Risk & Scope

  • Main risk or tradeoff: The new label depends on the existing daemon queued state; it intentionally does not infer queueing from network latency or show a spinner while waiting for dispatch.
  • Not validated / out of scope: Cross-client visual E2E behavior and Windows/Linux browser rendering were not manually tested. No daemon, SDK, queue lifecycle, or message ordering behavior is changed.
  • Breaking changes / migration notes: None.

Linked Issues

N/A

中文说明

此 PR 的改动

消息已被 daemon 接收到每会话队列、但尚未开始执行时,在输入框上方明确显示“服务器排队中...”。请求仍在提交阶段时继续显示“提交中...”;服务端排队中的消息仍可编辑、删除,但暂时隐藏插入当前回合的操作,直到该转移过程能够保证尚未被消费的消息仍然可见且可恢复。

为什么需要

排队消息可能已经在 Web Shell 中可见,但 daemon 尚未调度执行。此前这一阶段没有明确反馈,用户容易认为消息丢失,并重复提交相同内容。

Reviewer 测试计划

验证方式

启动一个回合,在当前回合仍运行时再次提交消息,确认请求被接受后,排队消息在输入框上方显示“服务器排队中...”。确认请求被接受前显示“提交中...”,服务器排队状态不显示活动 spinner,插入操作已隐藏,而删除和编辑仍保持可用。当 daemon 开始执行该排队消息后,确认它离开排队区域并进入正常回合 UI。

本地已完成自动验证:npx vitest run client/components/QueuedPromptDisplay.test.tsx(14 个测试)、针对修改文件的 ESLint、npm run buildnpm run typecheck

证据(改动前后)

改动前:已被服务器接受、但仍在 daemon 队列中等待的消息没有状态标签,看起来可能像消息丢失。

改动后:排队消息在开始调度前,会在输入框上方显示“Queued on server...” / “服务器排队中...”。

上方截图来自真实本地 daemon 和真实 Web Shell 中文客户端,不是 mock-daemon visual harness。第一条消息请求执行 45 秒 shell 等待,并在仍处于运行状态时通过浏览器提交第二条消息。daemon 的 /pending-prompts 响应显示第一条为 running、第二条为 queued;截图中可直接看到“服务器排队中...”,右侧仅保留删除和编辑操作。

测试平台

OS 状态
🍏 macOS
🪟 Windows ⚠️
🐧 Linux ⚠️

环境(可选)

macOS 本地工作区。视觉证据使用 headless Chromium,连接真实源码 daemon 和由 Vite 提供的真实 Web Shell 客户端;组件测试使用 Vitest 和 jsdom。

风险与范围

  • 主要风险或取舍:新标签依赖现有 daemon queued 状态;不会根据网络延迟推测排队,也不会在等待调度时显示 spinner。
  • 未验证或范围外:未手动验证跨客户端视觉 E2E 行为以及 Windows/Linux 浏览器渲染。未修改 daemon、SDK、队列生命周期或消息顺序行为。
  • 破坏性变更或迁移说明:无。

关联 Issue

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
@qwen-code-ci-bot

qwen-code-ci-bot commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator

Qwen Triage finishedview run. See the stage comments in this thread for the result.

Qwen Triage 已完成 —— 查看运行。结果见本线程中的各阶段评论。

@qwen-code-ci-bot

qwen-code-ci-bot commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator

Thanks for the PR!

Template looks good ✓

Problem: the QueuedPrompt type already declares serverState: 'queued' and useQueuedPrompts already sets that state from the daemon's /pending-prompts response (useQueuedPrompts.ts:544), but the component never rendered a label for it — a real UX gap where an accepted message shows no feedback until dispatch begins. The PR's real-daemon screenshot confirms the state occurs in practice. Not theoretical.

Direction: aligned — this is a small, self-contained UI state display for the Web Shell queue, squarely inside qwen-code's own package. CHANGELOG has no direct reference but the area is relevant.

Size: not applicable (no core paths touched — packages/web-shell/client/** is not core infrastructure; 17 production lines + 30 test lines).

Approach: the scope feels right. The diff adds exactly one derived boolean (isQueued), extends the existing status-label condition, suppresses the spinner for the queued state (correct — nothing is actively happening), hides the insert action for queued messages, and adds the i18n strings. Hiding insert is the one step beyond "show a label," but it's justified: delete and edit both operate specifically on serverState === 'queued' in the hook, so keeping those enabled while holding back insert (whose transfer semantics for an accepted-but-undrained message are less clear) is a coherent, conservative choice. No drive-by changes, nothing to cut.

Risk: no elevated risk signals (no high-risk paths touched).

Moving on to code review. 🔍

中文说明

感谢贡献!

模板完整 ✓

问题:QueuedPrompt 类型已声明 serverState: 'queued'useQueuedPrompts 也已从 daemon 的 /pending-prompts 响应中设置该状态(useQueuedPrompts.ts:544),但组件从未渲染对应标签——这是一个真实的 UX 缺口,消息被接受后在调度开始前没有任何反馈。PR 提供的真实 daemon 截图证明该状态确实会出现。并非理论性问题。

方向:对齐——这是一个小型、独立的 Web Shell 队列 UI 状态展示,完全位于 qwen-code 自己的包内。CHANGELOG 无直接引用,但该领域相关。

规模:不适用(未触及核心路径——packages/web-shell/client/** 不属于核心基础设施;17 行生产代码 + 30 行测试代码)。

方案:范围合理。diff 仅新增一个派生布尔值(isQueued),扩展了现有状态标签条件,在排队状态下不显示 spinner(正确——没有活动正在进行),隐藏排队消息的插入操作,并添加了 i18n 字符串。隐藏插入是"显示标签"之外唯一多出的步骤,但有合理理由:hook 中删除和编辑都专门作用于 serverState === 'queued',因此保留这两者、同时暂缓插入(其对"已接受但未消费"消息的转移语义不够明确)是一个连贯且保守的选择。无顺手改动,无需删减。

风险:无升级风险信号(未触及高风险路径)。

进入代码审查 🔍

Qwen Code · qwen3.8-max-preview

Reviewed at a8b78e5d207639f0cfe33d9fa06292b280c513bf · re-run with @qwen-code /triage

@qwen-code-ci-bot

qwen-code-ci-bot commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator

Code Review

Independent proposal: given a serverState: 'queued' that the type already declares and the hook already populates but the component never renders, I would add a derived boolean, extend the status-label condition, show a label without a spinner (nothing is actively happening), hide insert if its semantics are unclear, keep delete/edit, add EN+ZH i18n strings, and test both the queued and submitting paths.

Comparison: the PR does exactly this. The implementation matches the independent proposal — no simpler path was missed.

Specific observations:

  • The ternary chain (isRemoving → isEditing → isQueued → submitting) is correct: the submitting fallback is only reached when isSubmitting is true and no other state applies, since the outer condition requires one of the four flags.
  • Spinner is correctly suppressed for the queued state — only active operations (submitting, editing, removing) show it.
  • role="status" added to the status span is a reasonable accessibility improvement on the same element being modified; the new test asserts it.
  • isBusy is intentionally not extended with isQueued, so delete and edit stay enabled for queued messages. This matches the hook, where removeServerPromptForAction and editLastQueuedPrompt both gate on serverState === 'queued', and matches the PR's stated intent.
  • Insert is hidden via imageCount === 0 && !isQueued — consistent with holding back the less-clear transfer path while keeping delete/edit.
  • i18n strings are placed correctly in both EN and ZH dictionaries.
  • Tests pin the two key behaviors: queued state shows the label without a spinner, hides insert, and keeps the two remaining buttons enabled; submitting state still shows the spinner.

No critical blockers. No convention violations.

Testing

Final CI results for a8b78e5 (auto-updated by the triage finalize job after CI completed):

Check Conclusion
Test (ubuntu-latest, Node 22.x) ✅ success
Capture web-shell visuals (ubuntu-latest, Node 22.x) ✅ success
web-shell E2E Smoke (ubuntu-latest, Node 22.x) ✅ success
precheck-pr / precheck ✅ success

One row per check name (latest run); skipped checks omitted; failures sort first. / 每个检查名一行(取最新一次运行),省略 skipped,失败项排在最前。

CI is green on the reviewed commit. The Linux unit suite (Test (ubuntu-latest, Node 22.x)) passed, which includes QueuedPromptDisplay.test.tsx (14 tests, including the 2 new ones) that directly asserts the queued label, the absent spinner, the hidden insert action, and the enabled delete/edit buttons — the behavioral claim is pinned by these assertions, not the author's word. The macOS/Windows test legs and CLI integration are skipped for this fork PR (matrix limitation); for a text/state change the cross-platform rendering risk is negligible, and the web-shell E2E smoke and visual capture both passed.

中文说明

代码审查

独立方案: 鉴于 serverState: 'queued' 已在类型中声明、hook 已填充、但组件从未渲染,我会添加一个派生布尔值,扩展状态标签条件,显示无 spinner 的标签(没有活动正在进行),在插入语义不明时隐藏插入,保留删除/编辑,添加 EN+ZH i18n 字符串,并测试 queued 和 submitting 两种路径。

对比: PR 的实现与独立方案完全一致——没有遗漏更简路径。

具体观察:

  • 三元链(isRemoving → isEditing → isQueued → submitting)正确:由于外层条件要求四个标志之一为真,submitting 回退仅在 isSubmitting 为真且无其他状态时到达。
  • 排队状态正确抑制了 spinner——仅活动操作(提交中、编辑中、删除中)显示。
  • 在正在修改的元素上添加 role="status" 是合理的无障碍改进;新测试对其进行了断言。
  • isBusy 有意不包含 isQueued,排队消息的删除和编辑保持可用。这与 hook 一致——removeServerPromptForActioneditLastQueuedPrompt 都以 serverState === 'queued' 为条件,也与 PR 声明的意图一致。
  • 插入通过 imageCount === 0 && !isQueued 隐藏——与"暂缓语义较不明的转移路径、同时保留删除/编辑"一致。
  • i18n 字符串在 EN 和 ZH 字典中位置正确。
  • 测试固定了两个关键行为:排队状态显示标签、无 spinner、隐藏插入、其余两个按钮可用;提交状态仍显示 spinner。

无关键阻塞项。无规范违反。

测试

被审 commit 上 CI 全绿。Linux 单元测试套件(Test (ubuntu-latest, Node 22.x))通过,其中包含 QueuedPromptDisplay.test.tsx(14 个测试,含 2 个新增),直接断言了排队标签、缺失的 spinner、隐藏的插入操作以及可用的删除/编辑按钮——行为声明由这些断言固定,而非凭作者自述。macOS/Windows 测试分支和 CLI 集成对此 fork PR 为 skipped(矩阵限制);对于文本/状态变更,跨平台渲染风险可忽略,且 web-shell E2E smoke 与视觉捕获均已通过。

Qwen Code · qwen3.8-max-preview

Reviewed at a8b78e5d207639f0cfe33d9fa06292b280c513bf · re-run with @qwen-code /triage

@qwen-code-ci-bot

qwen-code-ci-bot commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator

Confidence: 5/5 — clean across every stage; would merge without hesitation.

This is exactly the kind of PR the gate should wave through quickly. The queued state was already in the type and the daemon — the UI just never rendered it. Seventeen production lines fill that gap following the existing pattern precisely: one derived boolean, one extended condition, one suppressed spinner, a hidden insert action whose semantics were genuinely unclear, two i18n strings. The tests pin both the new queued path and the existing submitting path, and CI is green on the reviewed commit — Linux unit suite, web-shell E2E smoke, and visual capture all passed. Nothing to cut, nothing to question, nothing to maintain reluctantly in six months.

CI is green on a8b78e5d207639f0cfe33d9fa06292b280c513bf, so approving now (pinned to that commit).

中文说明

置信度:5/5 —— 每个阶段均无问题,毫不犹豫地合并。

这正是 gate 应该快速放行的 PR。queued 状态已存在于类型和 daemon 中——只是 UI 从未渲染。17 行生产代码完全遵循现有模式填补了该缺口:一个派生布尔值、一个扩展条件、一个抑制的 spinner、一个语义确实不明而被隐藏的插入操作、两个 i18n 字符串。测试固定了新的 queued 路径和现有的 submitting 路径,且被审 commit 上 CI 全绿——Linux 单元测试套件、web-shell E2E smoke 和视觉捕获均通过。无需删减、无需质疑、六个月后维护也不会抱怨。

CI 已在 a8b78e5d207639f0cfe33d9fa06292b280c513bf 上全绿,因此立即审批(固定到该 commit)。

Qwen Code · qwen3.8-max-preview

Reviewed at a8b78e5d207639f0cfe33d9fa06292b280c513bf · re-run with @qwen-code /triage

@qwen-code-ci-bot

qwen-code-ci-bot commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator

🖼️ web-shell visual preview

Rendered against a mock daemon (no real backend): the PR base vs this PR head a8b78e5. Only screenshots that changed are shown (flows below, if any, are head-only) — refreshes on every push.

Screenshots · before / after

ℹ️ No screenshot changed against the PR base — but this PR edits 2 render-shaping files:

  • packages/web-shell/client/components/QueuedPromptDisplay.tsx
  • packages/web-shell/client/i18n.tsx

Either the change has no visual effect (logic, plumbing, a state the scenarios never reach), or no scenario renders this UI — in which case the preview cannot see it, and an empty result is a coverage gap rather than a clean bill of health. To make it visible, add a scenario to packages/web-shell/client/e2e/visuals/screenshots.spec.ts that seeds whatever state the UI is gated on; it then appears here as a head-only (NEW) capture.

Full-resolution recordings (.webm) are attached to the workflow run.

Qwen Code · web-shell visuals

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Downgraded from Approve to Comment: CI still running. Reviewed.

中文说明

⚠️ 已从批准降级为评论:CI still running。 已审查。

— qwen3.8-max-preview via Qwen Code /review

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, looks ready to ship — CI landed green after the review. ✅

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Downgraded from Approve to Comment: CI still running. Reviewed.

中文说明

⚠️ 已从批准降级为评论:CI still running。 已审查。

— qwen3.8-max-preview via Qwen Code /review

@ytahdn ytahdn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed at a8b78e5. No blocking issues found; the queued-state rendering and action availability match the existing server queue lifecycle, with targeted test coverage.

@wenshao

wenshao commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code /triage

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, looks ready to ship. ✅

@wenshao
wenshao added this pull request to the merge queue Jul 30, 2026
Merged via the queue into QwenLM:main with commit cc2cddd Jul 30, 2026
64 checks passed
@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Released in v0.21.2.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants