Conversation
muzimu217
left a comment
There was a problem hiding this comment.
实现质量很扎实——registry 的上限与淘汰(per-session 20 oldest-first、全局 1024)、list() 返回结构化克隆防突变、remote 前缀清理(remote:<hostKey>: 且带 local:s1 前缀混淆负例)、abort/会话删除/sidecar 崩溃/断连四个生命周期都收口了,145 行测试覆盖也到位。四点意见,前三点会实质影响合并:
1.(仓库惯例缺口)零 spec/E2E 登记。 本 PR 新增了控制面操作 agent/askTool/pending、核心工具 pi_asktool_pending、IPC 通道 askToolPending,但 docs/spec/ 一个文件都没动。对照同域先例 #945:只加一个设置项就同步了 5 份 spec + ADR 0203 + 213 行 E2E driver。按 AGENTS 约定(行为变更必须 spec + E2E 场景登记),至少需要:控制面操作清单所在的 spec、01-ipc-protocol.md 的通道登记、e2e-plan 的场景条目(暂跑不了就按惯例写 E2E: NOT RUN 块并给替代验证)。
2. CI 尚未触发(checks 为空)——如果是首次贡献需要维护者批一次 workflow run;跑起来之前各类门禁都还没验证过。
3.(行为变化确认)toAskToolRequest 的 toolCallId 兜底从 input.parentToolCallId ?? "" 改为 ?? input.id。 注释说 RACP 响应按 input.id 键控,方向应该是对的;但该字段同时被渲染层消费(答案挂接/工具行匹配),顶层 ask 以前拿到的是 ""——建议确认渲染层没有依赖旧空值的匹配分支;若有渲染层快照/匹配测试最好补一条。
4.(隐私面确认)list() 不带 sessionId 时跨所有会话(含 remote)返回问题原文。 控制面是本机 127.0.0.1 信任边界,但问题文本可能带用户上下文——建议要么默认按会话过滤、要么在 spec 里把"跨会话列举"写成显式语义,二选一即可。
7fa7342 to
aa23caf
Compare
…e review Register what vastsa#1014 added and close the four review points: - 01-ipc-protocol.md (en + zh-CN): list the pi-desktop/agent/askTool/pending channel and pi_asktool_pending in the 13d tool list, and document the cross-session listing semantics (mirroring plans/pending) plus the registry's process-memory lifetime. - 04-e2e-test-plan.md (en + zh-CN): add E2E-MCP-pending-asktool-questions-are-readable after E2E-220 with a NOT RUN record (reason, alternative validation, remaining risk) and extend the traceability matrix row. - permission-inline.test.mjs: pin that a renderer ask with a non-empty toolCallId is cleared by its own tool_end, guarding the parentToolCallId ?? input.id fallback the review flagged. - native-pi-sessions / session-collaboration-ipc harnesses: declare the new ../pending-asks dependency the strict IPC whitelist load rejects. Validation: docs:check (81 pairs, 516 pages), the seven touched test files 80/80, lint:biome, typecheck desktop+shared, check:pr-base. Full desktop suite: 2922 pass, 3 pre-existing environment failures (browser-cdp, bundled-plugins, plugin-work-panel-views) that also fail on a clean upstream/main checkout.
|
Thank you for the review — all four points are addressed in 1. Spec / E2E registration (done)
2. CI (requested) 3. 4. Cross-session Validation on
|
|
当前 PR 与最新 |
The desktop renderer receives every `asktool_request` as an in-memory
`AgentEventEnvelope`, so the requestId lives only in the renderer's zustand
store. The MCP control plane can already answer such a question
(`agent/askTool/resolve`) but had no way to read it back, which left remote
clients unable to discover what an Agent is waiting for: `plans/pending` has a
read operation, `agent/askTool/pending` did not.
Add a process-memory registry of pending asks in Electron main, fed by the same
envelopes the renderer sees, and expose it through a new read operation and
core tool:
- `pending-asks.ts`: registry keyed by session, deduped by requestId, bounded
per session (oldest pruned first) and globally across session buckets.
Structural clones on read; process memory only, never persisted or logged.
- `agent/askTool/pending` operation + `pi_asktool_pending` tool, mirroring the
existing `plans/pending` spec shape.
- Ingested from the local sidecar, the native agent event path and the remote
event bridge; cleared on resolve, abort, session delete, agent_end, tool_end,
session archive, and when a remote host connection closes (a disconnected
host can never resolve its asks, and no later event will arrive to settle
them).
Validation (from this request worktree, on top of latest origin/main):
- `pnpm check:pr-base` PASS
- `pnpm build:js` PASS
- `node --test apps/desktop/test/{mcp-control,pending-asks,remote-event-bridge,remote-host-connection}.test.mjs`
36/36 PASS
- `pnpm --filter @pi-desktop/desktop typecheck` PASS
- `pnpm --filter @pi-desktop/shared typecheck` PASS
- `pnpm lint:biome` PASS
Not run: the E2E suites that drive a live Electron app. The full
`pnpm --filter @pi-desktop/desktop test` run also fails on
`apps/desktop/test/settings-remote-hosts.test.mjs`, an untouched pre-existing
assertion in this tree; that file is unrelated to this change.
…e review Register what vastsa#1014 added and close the four review points: - 01-ipc-protocol.md (en + zh-CN): list the pi-desktop/agent/askTool/pending channel and pi_asktool_pending in the 13d tool list, and document the cross-session listing semantics (mirroring plans/pending) plus the registry's process-memory lifetime. - 04-e2e-test-plan.md (en + zh-CN): add E2E-MCP-pending-asktool-questions-are-readable after E2E-220 with a NOT RUN record (reason, alternative validation, remaining risk) and extend the traceability matrix row. - permission-inline.test.mjs: pin that a renderer ask with a non-empty toolCallId is cleared by its own tool_end, guarding the parentToolCallId ?? input.id fallback the review flagged. - native-pi-sessions / session-collaboration-ipc harnesses: declare the new ../pending-asks dependency the strict IPC whitelist load rejects. Validation: docs:check (81 pairs, 516 pages), the seven touched test files 80/80, lint:biome, typecheck desktop+shared, check:pr-base. Full desktop suite: 2922 pass, 3 pre-existing environment failures (browser-cdp, bundled-plugins, plugin-work-panel-views) that also fail on a clean upstream/main checkout.
aa23caf to
67ead61
Compare
|
Rebased onto the latest The only conflict was the import block in Re-validation on
The branch also picked up #1080's crash classification from Ready for your re-check; CI approval for a workflow run is still pending on this fork PR whenever you get to it. |
Summary
The desktop renderer receives every
asktool_requestas an in-memoryAgentEventEnvelope, so therequestIdlives only in the renderer's zustandstore. The MCP control plane can already answer such a question
(
agent/askTool/resolve) but had no way to read it back:plans/pending— has a read operationagent/askTool/resolve— has a write operationagent/askTool/pending— missingA remote client (phone app driving a paired desktop through the control plane)
therefore cannot discover what an Agent is waiting for, and cannot tell a
stopped session from a working one. This adds the missing read side.
What changed
apps/desktop/electron/main/pending-asks.ts(new): process-memoryregistry of pending asks, keyed by session, deduped by
requestId, boundedper session (oldest pruned first) and globally across session buckets.
list()returns structural clones. Nothing is persisted, logged, or writteninto the transcript — state dies with the process, matching the runtime's own
pending-request lifetime.
agent/askTool/pendingoperation +pi_asktool_pendingcore tool,declared exactly like the existing
plans/pendingspec (read, inputargument
sessionIdoptional filter).and the remote event bridge.
agent_end,tool_end,session.archived, sidecar crash, and remote-host connection close.Why the cleanup paths matter
A disconnected remote host can never resolve its asks, and no later event will
arrive to settle them —
input.resolvedandsession.archivedboth ride thesame dead stream. Without clearing on
close()the dead entries stay visible inunfiltered listings and their buckets are never reclaimed, so both bounds are
enforced: per session, and across session buckets.
Affected contracts
packages/shared/src/protocol.ts: newIPC.invoke.askToolPendingchannel.readoperation (agent/askTool/pending).No existing operation, channel, or payload shape changes.
boundaries.
Validation (from the request worktree, on top of latest
origin/main)pnpm check:pr-baseorigin/main(03e03d4cc) is an ancestor of HEADpnpm build:jsnode --test apps/desktop/test/{mcp-control,pending-asks,remote-event-bridge,remote-host-connection}.test.mjspnpm --filter @pi-desktop/desktop typecheckpnpm --filter @pi-desktop/shared typecheckpnpm lint:biomeNot run / remaining risk
test:e2e:*). Theyneed a full desktop session; the coverage above is unit + type + build level.
pnpm --filter @pi-desktop/desktop testalso fails in this tree onapps/desktop/test/settings-remote-hosts.test.mjs— a pre-existing assertionthat this change does not touch (it expects an
aria-controlsattribute thecurrent page does not emit). Reported here so the failing suite is not
mistaken for a regression from this PR.
That matches the runtime's own pending-request lifetime, and a client that
needs the truth re-reads it after reconnect.
Compatibility / migration
None required. Additive read operation and additive IPC channel; the registry is
empty until an
asktool_requestarrives, and every pre-existing path behavesbyte-for-byte as before.