fix(desktop): 右栏 detached 队列改为每会话有序 intent 组,登记命令不被后到命令顶掉 (#2409) - #2491
fix(desktop): 右栏 detached 队列改为每会话有序 intent 组,登记命令不被后到命令顶掉 (#2409)#2491gardenZzz wants to merge 4 commits into
Conversation
|
| Filename | Overview |
|---|---|
| apps/desktop/src/main/right-sidebar-window/controller.ts | 引入按会话队列和 ACK 驱动交付,但 detached→attached 的整桶重放仍会在完成至 ACK 的窗口内重复执行桶头。 |
| apps/desktop/src/renderer/components/layout/SidebarWindowLayout.tsx | 改为串行执行后发送 ACK,但 finally 无条件确认失败命令,可能永久丢失未完成的 intent。 |
| apps/desktop/src/renderer/features/right-sidebar/lib/executeSidebarCommand.ts | 新增 Promise 链以保证 renderer 内命令严格串行,并保留单条命令的 rejection 给调用方。 |
| apps/desktop/src/main/right-sidebar-window/ipc.ts | 新增仅接受当前 sidebar webContents 的 ACK handler,并将确认转交 controller。 |
| apps/desktop/src/main/right-sidebar-window/tests/controller.test.ts | 覆盖队列保序、合并、切换会话和 ACK 推进,但未覆盖 renderer 执行失败后不应确认消费的场景。 |
Sequence Diagram
sequenceDiagram
participant M as Main Controller
participant S as Detached Renderer
participant A as Attached Renderer
M->>S: 发送 deferred 桶头
S->>S: 串行执行命令
alt 执行成功
S->>M: ACK
M->>M: shift 桶头
else 执行失败
S->>S: 记录错误
S->>M: finally 仍发送 ACK
M->>M: shift 未成功消费的桶头
end
opt ACK 到达前切回 attached
M->>A: 重放包含桶头的整桶
end
Prompt To Fix All With AI
### Issue 1
apps/desktop/src/renderer/components/layout/SidebarWindowLayout.tsx:117-123
**失败命令仍被确认消费**
当 deferred 命令在页签 hydration、创建、关闭或状态写入期间执行失败时,`catch` 只记录错误,而 `finally` 仍发送 ACK;main 随后移除尚未成功消费的桶头,导致对应的打开、关闭或聚焦 intent 永久丢失且无法在重开窗口后恢复。
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Reviews (7): Last reviewed commit: "fix(desktop): 切 attach 时整桶含未 ack 桶头转交主窗,..." | Re-trigger Greptile
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 66b0a617d7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
66b0a61 to
f7ff206
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f7ff2063f2
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
f7ff206 to
3840a04
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3840a0413b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@gardenZzz 👋 这个 PR 还有 2 条 review conversation 没 resolve(apps/desktop/src/main/right-sidebar-window/controller.ts / apps/desktop/src/renderer/components/layout/SidebarWindowLayout.tsx),auto-review 因此暂时跳过、没法继续审查 / 合并。 如果你已经按评论改完或回应了,请到对应 thread 上点 Resolve conversation;全部 resolve 后,下一轮 auto-review 会自动重新审查这个 PR。 |
…akecindy#2409) detached 且侧栏窗口关闭/未 ready 时,同会话的 deferred intent 只保留一条: enqueueDeferredCommand 直接 set 覆盖,登记类命令(如 open-subagents-tab 历史静默登记)可能被随后同会话的另一条 allowOpen:false 命令顶掉,导致 这次登记丢失。Subagent 记录本身持久化在 SQLite,重进任务会重新登记, 所以是阶段性页签入口缺失,而非数据丢失。 改为 Map<hostSessionId, RsbWindowCommand[]>,每会话保留一组有序 intent: - 不同语义命令保序追加,绝不互相覆盖; - Orca 页签单例 coalescing 保持旧语义:带定位的 ensure(focus/searchJump) 覆盖尾部 ensure(最新聚焦意图胜出),无定位 generic ensure 在尾部已是 ensure 时被吸收(等价重复,或不如尾部更具体的 worker/search intent, 保护具体 intent 不被抹掉),尾部是 close 等非 ensure 命令时照常追加; - Subagent 静默登记合并:SUBAGENT_TAB_REGISTER_ONLY 是固定常量 (revealSidebar=false、无 focus 参数)。生产路径 openSubagentsTab 用 `?? null` 写 focus 字段、IPC 保留 null,故 null 与 undefined 都视为 「无 focus」;detached 关窗期间每次 agent_task_update 都会再次入队, 连续等价静默登记只保留一条,避免队列无限堆积、开窗时重复执行;带 focus 的登记与静默登记语义不同,保序保留; - detached / attached 两条 flush 复用同一套 drainCurrentSessionDeferred 按序全部下发,避免路径分叉。 renderer 侧串行消费:main 批量下发的 deferred intent 带顺序语义(如 close 后接 generic ensure),但 MainLayout / SidebarWindowLayout 的 onCommand 若以 void executeSidebarCommand 并发启动,close 在真正删除页签前让出 执行权、后到的 ensure 会看到旧页签直接返回,最终状态违背最新 intent。 新增 enqueueSidebarCommand:单条 promise 链把命令排成严格串行,同一 renderer 内按到达顺序逐条完成;两个 onCommand 消费点改用它。同步更新 orcaRemoteRoutingInvariants 不变量断言到 enqueueSidebarCommand。 现有 MAX_DEFERRED_SESSIONS 跨 session 淘汰保留(经查证经公开 API 实际 不可达——setContext 切换 session 时已清掉其它会话桶,属防御性兜底)。 测试:48 条 controller 单测 + 2 条 executeSidebarCommand 串行消费测试 + orcaRemoteRoutingInvariants 全过;desktop typecheck 通过。全量 test:unit 交由 fork client-ci。 Signed-off-by: GardenX <20606485+gardenZzz@users.noreply.github.com>
3840a04 to
a1061e4
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a1061e4795
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
此 PR 命中产品 UI 路径(MainLayout / SidebarWindowLayout / executeSidebarCommand)及核心架构路径,已自动创建维护者确认流程。 当前状态:⏳ 等待维护者确认 维护者确认方式:直接在 PR 上 Approve 即放行;如需修改请用 Request Changes,作者修改后重新 Approve 即可。 关联讨论:见下方讨论 issue。 讨论 issue:#2500 |
…2491) Codex P1:drain 先删整桶再 IPC 时,串行消费者只启动首条;关窗销毁 BrowserWindow 会让未开始的尾部 intent 永久丢失。 改为 detached 路径一次只下发桶头、ack 后才 shift;关窗仅清在途标记, 桶内未确认 intent 可在重开后继续交付。attached 路径仍整桶 drain(主 renderer 常驻)。补两条关窗/重开回归与既有多命令 flush 的 ack 断言。 Signed-off-by: GardenX <20606485+gardenZzz@users.noreply.github.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3c0119c9e8
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
- setDetached(false):drop 已下发未 ack 的桶头再 drain 剩余,避免子窗与主窗双执行 - routeCommand:同 session 有 deferred 在途/尾部时直播命令入同一桶,避免无参 ack 误推进 - 补两条回归:切 attached 不重发桶头;A 在途时 B 排队、C 不被误 shift Signed-off-by: GardenX <20606485+gardenZzz@users.noreply.github.com>
子窗即将销毁,其 store 与未完成 commandChain 不作数;在途未 ack 桶头 也必须 drain 给主 host,不能 drop。保留「deferred 在途时直播入桶」防 无参 ack 误推进。 Signed-off-by: GardenX <20606485+gardenZzz@users.noreply.github.com>
| void enqueueSidebarCommand(cmd) | ||
| .catch((err) => log.warn('sidebar command failed', err)) | ||
| .finally(() => { | ||
| void window.electronAPI.rightSidebarWindow.ackCommand().catch((err) => { | ||
| log.warn('sidebar command ack failed', err); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
当 deferred 命令在页签 hydration、创建、关闭或状态写入期间执行失败时,catch 只记录错误,而 finally 仍发送 ACK;main 随后移除尚未成功消费的桶头,导致对应的打开、关闭或聚焦 intent 永久丢失且无法在重开窗口后恢复。
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src/renderer/components/layout/SidebarWindowLayout.tsx
Line: 117-123
Comment:
**失败命令仍被确认消费**
当 deferred 命令在页签 hydration、创建、关闭或状态写入期间执行失败时,`catch` 只记录错误,而 `finally` 仍发送 ACK;main 随后移除尚未成功消费的桶头,导致对应的打开、关闭或聚焦 intent 永久丢失且无法在重开窗口后恢复。
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 11563be021
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const isGeneric = command.focusWorkerSessionId === undefined && command.searchJump === undefined; | ||
| if (last?.type === 'ensure-orca-workers-tab') { | ||
| if (isGeneric) return; | ||
| bucket[bucket.length - 1] = command; |
There was a problem hiding this comment.
| ipcMain.handle(MAKER_INVOKE.RSB_WINDOW_ACK_COMMAND, (event) => { | ||
| // 仅子窗口可确认 detached deferred 消费;主窗误调忽略。 | ||
| const sidebarWc = controller.getSidebarWebContents(); | ||
| if (!sidebarWc || event.sender !== sidebarWc) { |
There was a problem hiding this comment.
这个新增 IPC 只比较 event.sender,因此来自同一 sidebar WebContents 的非顶层 frame 也会被当作合法确认;一旦该 frame 能触发此通道,就可提前推进桶头并让尚未消费的 deferred intent 永久丢失。请同时要求 event.senderFrame === sidebarWc.mainFrame(或复用仓库的顶层 Renderer guard),并补充子 frame 被拒绝的测试。
AGENTS.md reference: AGENTS.md:L30-L31
Useful? React with 👍 / 👎.
|
@gardenZzz 👋 这个 PR 还有 3 条 review conversation 没 resolve(apps/desktop/src/renderer/components/layout/SidebarWindowLayout.tsx / apps/desktop/src/main/right-sidebar-window/controller.ts / apps/desktop/src/main/right-sidebar-window/ipc.ts),auto-review 因此暂时跳过、没法继续审查 / 合并。 如果你已经按评论改完或回应了,请到对应 thread 上点 Resolve conversation;全部 resolve 后,下一轮 auto-review 会自动重新审查这个 PR。 |
这次改了什么
摘要
修复 #2409:右栏处于 detached 模式且侧栏窗口关闭 / 未 ready 时,同会话的「登记类」命令(如
open-subagents-tab历史静默登记)可能被随后同会话的另一条allowOpen: false的命令顶掉,导致这次登记丢失。原因:
deferredCommands是Map<hostSessionId, RsbWindowCommand>,每个会话只保留一条;enqueueDeferredCommand直接set覆盖(仅对ensure-orca-workers-tab无参重复帧做了去重豁免)。窗口再打开时只执行后到的那条。变更类型
fix缺陷修复范围
deferredCommands改为Map<hostSessionId, RsbWindowCommand[]>:每个 host session 保留一组有序 intent,不同语义命令保序追加、绝不互相覆盖;ensure-orca-workers-tab(focusWorkerSessionId/searchJump)覆盖尾部 ensure(最新聚焦意图胜出);无定位 generic ensure 在尾部已是 ensure 时被吸收(等价重复,或不如尾部更具体的 worker/search intent,保护具体 intent 不被抹掉);尾部是close-orca-workers-tab等非 ensure 命令时照常追加(ensure 在 close 后有真实语义);drainCurrentSessionDeferred,按序全部下发,避免路径分叉;MAX_DEFERRED_SESSIONS跨 session 淘汰逻辑(经查证经公开 API 实际不可达——setContext切换 session 时已清掉其它会话桶,属防御性兜底,不改动)。openSubagentsTab的 attached-only 裁决语义。docs/dev-rules/remote-and-mobile-adaptation.md§ PR 门禁):packages/device-link不承载 RSB command 通道,隧道不转发该队列。apps/mobile无右栏子窗口。UI 变化
不涉及:纯 main 层队列内部实现 + renderer 命令串行化,无视觉/交互/文案变化。
引用的设计规范:不涉及
怎么验证的
自动验证
手工验证
不涉及(无 UI 变化;全量
test:unit交由 fork client-ci 验证)。未执行的验证
无。
风险
风险分类
影响与回滚
Fixes #2409