ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Web Shell 后端权威队列显示:Qwen Code 待处理提示的重复条目消除与失败恢复策略

Web Shell 后端权威队列显示:Qwen Code 待处理提示的重复条目消除与失败恢复策略 Web Shell 后端权威队列显示Qwen Code 待处理提示的重复条目消除与失败恢复策略【免费下载链接】qwen-codeAn open-source AI coding agent that lives in your terminal.项目地址: https://gitcode.com/GitHub_Trending/qw/qwen-code导读在 Qwen Code 的 Web Shell 界面中用户提交的提示词prompt会先进入一个本地队列再通过 daemon 的 admission准入流程转交给后端会话。由于网络抖动或连接中断admission 请求可能已经到达 daemon、但响应在回传途中丢失此时界面会同时出现本地未知行与daemon 权威行两套表现造成重复条目、delivery unknown送达未知、local copy discarded本地副本已丢弃等混乱 UI。本文基于仓库中的设计文档 web-shell-backend-authoritative-queue-display.md结合 useQueuedPrompts.ts 等源码实现与测试用例讲解这套后端权威队列显示方案的边界规则本地行何时存在、失败后何时恢复草稿、何时彻底移除以及如何通过 daemon 快照消除重复条目。读完本文你将掌握 Qwen Code Web Shell 待处理队列的状态机与失败恢复的完整设计。问题背景响应丢失引发的重复条目Web Shell 在两种场景下会发起准入请求pending-prompt待处理提示普通的下一次会话提示词提交mid-turn admission回合中准入当前回合进行中插入的提示词。当这样的请求可能已经到达 daemon、但其响应在传输中丢失时例如连接在onAdmissionStarted之后、响应返回之前断开Web Shell 无法确定请求是否被 daemon 接受。旧实现会保留一个本地的unknown队列行随后一次 daemon 刷新refresh又会在本地副本旁追加一条权威行于是界面上出现看起来重复的条目并伴随 delivery unknown送达状态未知或 local copy discarded本地副本被丢弃之类的 UI 文案。这个问题的本质是本地乐观状态与 daemon 权威状态之间缺乏单一事实来源single source of truth。本地行与服务器行各自独立存活谁也无法裁决哪一条才是真的最终只能靠用户手动选择恢复或丢弃。设计核心本地行只存在于请求在途期间设计文档给出的核心原则非常简洁本地行local row仅在 admission 请求在途in flight期间存在。一旦请求结束无论成败两条 admission 路径都必须查询 daemon 并渲染其队列快照而不是继续相信本地记忆。具体规则如下请求成功立即以 daemon 返回的权威数据promptId、state渲染队列行本地行与权威行按 id 合并绝不出现两行并存。请求失败或后续跟随的查询失败移除本地行。之后的重连reconnect或队列事件queue event只有在 daemon 主动报告该提示时才可能重新恢复它——本地不再单方面复活未知条目。失败发生在请求派发dispatch之后同样遵循上述规则不把 payload 恢复回编辑器因为该内容可能已被 daemon 接受恢复回去会造成用户重复发送。失败发生在请求派发之前例如媒体上传失败此时 daemon 绝无可能接受该内容因此安全地将草稿恢复回编辑器用户可以直接重新编辑提交。源码印证权威快照同步机制在 useQueuedPrompts.ts 中refreshPendingPromptsL704-L736实现了查询 daemon 并渲染其队列快照这一核心动作const refreshPendingPrompts useCallback( async (targetSessionId sessionId): PromiseRefreshPendingPromptsResult { if (!connected || !targetSessionId) return skipped; // ... const result await sessionActions.getPendingPrompts({ sessionId: targetSessionId, }); // 通过 requestSeq 序列号与 ownerToken 双重校验防止过期响应覆盖新状态 if (requestSeq ! refreshRequestSeqRef.current) return superseded; // ... syncServerQueuedPrompts( result.pendingPrompts.filter( (p) p.state queued || p.state running, ), targetSessionId, ); return refreshed; }, [connected, sessionActions, sessionId, syncServerQueuedPrompts], );需要注意两个细节结果类型refreshed | skipped | superseded | failed中superseded表示本次请求已被更新的刷新请求取代stale-response fencefailed表示查询失败——对应文档中请求或后续查询失败则移除本地行的判定。过滤条件只保留queued与running状态的提示已 settle 的提示不再出现在队列快照中从而被同步逻辑自然清除。真正执行合并去重的是syncServerQueuedPromptsL566-L702。它以 daemon 快照为基准重建本地列表本地行若持有serverPromptId但快照中已不存在 → 从列表移除快照中的提示若本地已有同 id 行 → 就地更新其serverState不新增重复行快照中的提示若本地完全没有 → 以serverPromptId重建新行含从content提取的图片/文件附件最终通过areQueuedPromptsEqualL238-L266做深度比较只有列表真正变化时才触发setQueuedPrompts重渲染。这套以服务器为准、按 id 合并、整体替换的逻辑正是消除权威行与本地副本并列这一问题的实现基础。mid-turn 场景快照协调与缺失行清理mid-turn admission 走的是另一条路径。reconcileMidTurnMessagesL935-L977会依次完成调用sessionActions.getMidTurnMessages获取回合中消息快照调用refreshPendingPrompts获取待处理提示快照调用applyMidTurnSnapshotL738-L910合并快照settledMessageIds中的消息触发完成回调并删除本地 pending 记录promotedMessageIds提升为服务器行并抢救其图片附件调用pruneMissingMidTurnRowsL912-L933清理快照中已不存在的 mid-turn 行并触发其onComplete回调。其中applyMidTurnSnapshot的过滤逻辑与文档本地行只在请求在途期间存在完全对应let next current.filter( (prompt) !( prompt.midTurnState ! undefined prompt.midTurnMessageId ! undefined !prompt.isEditing !prompt.isRemoving (displayedServerPromptIdsRef.current.has(prompt.midTurnMessageId) || settledServerPromptIdsRef.current.has(prompt.midTurnMessageId) || settledIds.has(prompt.midTurnMessageId) || (applyPromoted promotedIds.has(prompt.midTurnMessageId))) ), );即一旦消息在服务器端被 settle 或 promoted本地 mid-turn 行立即移除只有当快照中确实还等待中waiting的消息才保留为queued状态行。失败恢复的边界dispatch 前后行为不同文档中最关键的一条实战规则是按失败发生的时间点决定是否恢复草稿其实现位于submitPendingPrompt的.catch分支L1518-L1544.catch((error: unknown) { // ... if (!queuedPromptsRef.current.some((p) p.id localId)) return; const next queuedPromptsRef.current.filter( (prompt) prompt.id ! localId, ); queuedPromptsRef.current next; setQueuedPrompts(next); if (!admissionStarted) { restoreQueuedPromptsToEditor([prompt], targetSessionId); } reportError(error, t(queue.queueFailed)); })这里的admissionStarted标志由onAdmissionStarted回调置位L1403-L1405它标记请求是否已经真正派发给 daemonadmissionStarted falsedispatch 前失败例如媒体上传失败、session 创建失败——daemon 不可能接受该内容因此调用restoreQueuedPromptsToEditor把文本、图片、文件、输入注解完整恢复回编辑器用户可安全地再次编辑提交admissionStarted truedispatch 后失败内容可能已被 daemon 接受不恢复只移除本地行并报错。之后仅当 daemon 在后续快照或队列事件中报告该提示时它才会以权威行的形式重新出现。restoreQueuedPromptsToEditorL998-L1062还配合mergeRestoredPromptTextL226-L230做去重保护若编辑器顶部已经存在相同文本则不再叠加避免刷新/重连多次触发恢复时把同一段输入拼接多次即 issue #7128 报告的 inputs concatenated after refresh。过时 UI 的移除与保留的防护机制设计文档明确指出过时的 unknown-admission 行状态及其 restore/discard恢复/丢弃UI 被移除。旧界面中当送达状态未知时用户会看到类似这样的提示与操作Delivery is uncertain. Check the session before trying again.消息是否送达尚不确定请先检查会话再重试Restore local copy / Discard local copy恢复本地副本 / 丢弃本地副本Continue editing继续编辑带二次确认The prompt may already be running. Continue editing only if you accept the risk of sending it twice.这些文案仍可在 i18n.tsx 的queue.admissionUnknown、queue.restoreUnknown、queue.discardUnknown、queue.continueEditing等键中找到L1765-L1771。在新方案下未知状态不再以本地未知队列行的形式长期存在而是收敛为受限的会话级防护测试用例App.test.tsx中[data-testidprompt-admission-unknown]与promptAdmissionUncertain的语义表明保留的是锁定重复提交级别的保护而非可恢复/可丢弃的本地行副本。从源码结构看ChatPane.tsx 中仍保留着 admission-unknown 的状态条渲染含continueEditingUnknownPrompt/discardUnknownPromptPayload两个动作但其行为已被测试约束为锁定重复提交 限定到分配的 session与旧的本地 unknown 队列行 手动恢复/丢弃模型已是两套东西——这印证了设计文档描述的正是这一演进方向。测试验证边界行为被测试固化仓库中的测试用例 App.test.tsx 从三个角度固化了上述边界行为见 App prompt send failure retry 描述组L33355 起does not mark delivery unknown when lazy session creation fails before prompt admissionL33356当createSession在 admission 派发前失败时sendPrompt不应被调用编辑器不被清空editorCommit不触发也不出现 admission-unknown 标记——与dispatch 前失败恢复草稿规则一致keeps an unknown lazy-session admission scoped to its allocated sessionL33383onAdmissionStarted之后连接断开unknown 状态保留但限定在已分配的 session 内并调用promptAdmissionUncertain上报locks duplicate submission when prompt admission is unknownL33426admission 结果未知时编辑器被禁用disabled true不出现failed-prompt-retry按钮且再次点击操作不会重复调用sendPrompt——杜绝了未知状态下重发导致重复执行的风险。这三个用例分别对应设计文档的三条规则dispatch 前失败安全恢复、unknown 状态不扩散、以及绝不因本地猜测造成重复提交。总结后端权威队列显示方案用一个简单的不变式解决了复杂的重复条目问题本地行只在请求在途期间存活最终状态一律以 daemon 快照为准。由此派生出三条清晰的失败恢复规则失败时机daemon 是否可能已接受处理方式dispatch 前如媒体上传失败不可能恢复草稿回编辑器dispatch 后响应丢失可能移除本地行不恢复等 daemon 快照/事件决定去留后续刷新/查询失败——移除本地行不单方面复活实现上useQueuedPrompts.ts 通过refreshPendingPrompts → syncServerQueuedPrompts、reconcileMidTurnMessages → applyMidTurnSnapshot → pruneMissingMidTurnRows两条链路保证了权威快照的同步通过admissionStarted标志划分了失败恢复的边界并通过 App.test.tsx 的用例将行为固化。这套设计保证了 Web Shell 在弱网、断连、重连等不确定环境下既不会向用户展示重复条目也不会因本地猜测造成重复提交。【免费下载链接】qwen-codeAn open-source AI coding agent that lives in your terminal.项目地址: https://gitcode.com/GitHub_Trending/qw/qwen-code创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表