docs(design): DaemonTransport abstraction — pluggable transport for SDK#5026
docs(design): DaemonTransport abstraction — pluggable transport for SDK#5026chiga0 wants to merge 6 commits into
Conversation
… for SDK Design doc for making DaemonClient transport-agnostic via a fetch-level DaemonTransport interface. Enables REST+SSE, ACP HTTP+SSE, and ACP WebSocket transports without breaking existing consumers. Key decisions: - Abstract at fetch level (not method-dispatch) to preserve DaemonClient's 67 per-method HTTP branching unchanged - Zero breaking changes: transport is optional, defaults to current REST - Solves the store-split problem: one provider, one store, ChatView + TerminalView always in sync regardless of transport - Prerequisite error taxonomy (DaemonError.kind) before transport swap - No auto-fallback in v1 (explicit transport selection) Generated with AI Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
|
Thanks for the design doc, @chiga0 — this is a well-structured proposal. Template note: PR body uses custom headings (Summary / What reviewers should weigh in on / Test plan) instead of the PR template sections (What this PR does / Why it's needed / Reviewer Test Plan / Risk & Scope / Linked Issues / 中文说明). The design doc itself covers all the substance, so not blocking on this — but future PRs should follow the template for consistency. On direction: The store-split problem is real and well-diagnosed. Third-party integrations needing ~8 files of parallel provider infrastructure to swap transports is a genuine SDK design gap. CHANGELOG shows active ACP work ( On approach: Fetch-level abstraction is the right seam. Method-dispatch over 67 methods would be untenable, and the doc makes a convincing case against it. The error taxonomy as prerequisite (PR 0) is justified — provider branches on HTTP status codes today, so One question worth considering before implementation: the ~2750 total lines across 4 PRs is substantial. If PR 2 (AcpHttpTransport) turns out to need significant deviation from the design, would the interface need to change too? Having a rough prototype before finalizing the interface might de-risk the later PRs. Moving on to design review. 🔍 中文说明感谢设计文档,@chiga0 — 结构清晰,问题描述到位。 模板提示: PR 正文使用了自定义标题,未遵循 PR 模板 的章节结构(What this PR does / Why it's needed / Reviewer Test Plan / Risk & Scope / Linked Issues / 中文说明)。设计文档本身已覆盖全部内容,不因此阻断——但后续 PR 请遵循模板。 方向: store-split 问题是真实的,诊断清晰。第三方集成需要约 8 个文件的并行 provider 基础设施来替换传输层,是 SDK 的设计缺口。CHANGELOG 显示 ACP 相关的活跃开发,方向对齐。 方案: fetch 层抽象是正确的切入点。67 个方法上做 method-dispatch 不可行,文档论证充分。Error taxonomy 作为前置条件合理。4-PR 拆分粒度合理。 一个建议:4 个 PR 合计约 2750 行,体量不小。如果 PR 2(AcpHttpTransport)实现时需要偏离设计,接口是否也需要调整?建议在定稿接口前做一个粗略原型,降低后续 PR 的风险。 进入设计审查 🔍 — Qwen Code · qwen3.7-max |
Design doc reviewThe design doc is thorough and well-organized — problem statement, architecture diagrams, interface definition, alternatives, breaking-change audit, risks. This is the kind of design doc that makes implementation PRs easier to review. A few observations from reading it closely:
ACP → HTTP status synthesis. The design says AcpHttpTransport "synthesizes TransportResponse" from JSON-RPC responses. But DaemonClient branches on specific HTTP status codes (202 vs 200 for prompt, 204 vs 404 for delete, etc.). The transport will need a non-trivial mapping layer from JSON-RPC results/errors to plausible HTTP statuses. The doc acknowledges this implicitly but doesn't spell out the mapping. This is probably the highest-risk area in PR 2 — worth prototyping early. Connection lifecycle not detailed. RestSseTransport is stateless (no lifecycle), but AcpWsTransport owns a WebSocket with reconnection, health-check, and teardown semantics that differ significantly from REST. The doc mentions Overall: the design is sound. The fetch-level seam is the right choice, the error taxonomy prerequisite is justified, and the breaking-change analysis is convincing. The open questions are implementation details best resolved during the PR 0–1 implementation, not in the design doc. TestingN/A — this PR adds a single design document ( 中文说明设计文档审查设计文档结构清晰、内容完整——问题陈述、架构图、接口定义、替代方案、破坏性变更审计、风险分析。这类设计文档让后续实现 PR 更容易审查。 几点细看后的观察:
ACP → HTTP 状态码合成。 设计说 AcpHttpTransport 从 JSON-RPC 响应"合成 TransportResponse"。但 DaemonClient 对特定 HTTP 状态码有分支逻辑(202 vs 200 for prompt, 204 vs 404 for delete 等)。传输层需要一个从 JSON-RPC 结果/错误到合理 HTTP 状态码的映射层,文档未详细展开。这可能是 PR 2 中风险最高的部分——值得提前做原型。 连接生命周期未详述。 RestSseTransport 无状态,但 AcpWsTransport 拥有 WebSocket,涉及重连、健康检查、拆除语义。文档提到了 总结: 设计合理。fetch 层接缝选择正确,error taxonomy 前置条件合理,破坏性变更分析有说服力。开放性问题最好在 PR 0–1 实现中解决。 测试不适用——本 PR 仅添加一份设计文档,无代码变更、无行为变更。 — Qwen Code · qwen3.7-max |
ReflectionThis is a clean design-doc PR — one file, zero code changes, zero risk to ship. The store-split problem is real: third-party integrations that need ACP WebSocket today face a choice between building ~8 files of parallel infrastructure (and getting a crash-prone dual-store setup) or forking the SDK. Neither is acceptable for a public SDK. The proposed solution — a fetch-level The alternatives section is particularly strong. Three alternatives considered and rejected with concrete reasons, including the dual-provider approach that already exists in the codebase and causes the exact problem this design aims to solve. The ACP → HTTP status synthesis is the riskiest implementation detail for PR 2, and the WS connection lifecycle needs more design work before PR 3. Neither blocks this design doc — they're implementation concerns for the follow-up PRs. This doc earns its place. Approving as a design foundation for the implementation PRs. 中文说明总结这是一个干净的设计文档 PR——一个文件,零代码变更,零发布风险。 store-split 问题是真实的:今天需要 ACP WebSocket 的第三方集成面临两种选择——构建约 8 个文件的并行基础设施(导致易崩溃的双 store),或者 fork SDK。对于公共 SDK 来说都不可接受。提议的方案——在 DaemonClient 内部的 fetch 层添加 DaemonTransport 接口——是正确的切入点。保持所有 67 个现有方法不变,维护单 store 不变量,让传输层成为可插拔的实现细节。 替代方案部分尤为扎实。三个替代方案被考虑并拒绝,理由具体,包括代码库中已存在且导致了此设计要解决的问题的双 provider 方案。 ACP → HTTP 状态码合成是 PR 2 实现中风险最高的细节,WS 连接生命周期在 PR 3 前需要更多设计工作。两者都不阻断当前设计文档——它们是后续 PR 的实现关注点。 此文档实至名归。作为实现 PR 的设计基础予以批准。 — Qwen Code · qwen3.7-max |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
LGTM — solid design doc, good foundation for the implementation PRs. ✅
Code Coverage Summary
CLI Package - Full Text ReportCore Package - Full Text ReportFor detailed HTML reports, please see the 'coverage-reports-22.x-ubuntu-latest' artifact from the main CI run. |
…r-engineering v1→v2 changes based on multi-round adversarial audit (6 agents, 27 findings): - Drop error taxonomy prerequisite (transports map to HTTP status internally) - Drop provider changes (transport injected via DaemonClient constructor) - Drop 4-PR split → single PR for interface + extraction - Fix 6 direct _fetch call sites missed in v1 - Add connected: boolean for disconnect detection - Add DaemonTransportClosedError - Reframe motivation: transport pluggability, not store-split fix - Correct line estimate: ~178 lines (not ~20) Generated with AI Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
- Server advertises transports in GET /capabilities (additive field) - DaemonTransport.negotiate() one-shot static factory (WS > HTTP > REST) - Runtime fallback: consumer-driven via DaemonTransportClosedError, not silent internal switch (WS teardown destroys sessions — must be explicit) - Optional AutoReconnectTransport wrapper for opt-in reconnect - All new features are additive/opt-in, zero impact on existing code Generated with AI Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Consolidate 4 PRs into 1: interface + RestSse + AcpWs + AcpHttp + auto-detect + fallback all in one PR. Generated with AI Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
设计方案审计对 1. 抽象层选择:fetch-level 是否正确? ✓结论:正确。 fetch-level 是最佳切面。 验证了当前 如果选 method-dispatch(
2. 接口设计:
|
| 变更点 | 影响 | 评估 |
|---|---|---|
DaemonClientOptions 新增 transport? |
纯 additive | ✓ |
private _fetch 移除 |
非公开 API | ✓ |
RestSseTransport 提取 SSE 逻辑 |
内部重构 | ✓ |
fetchWithTimeout 委托给 transport.fetch |
行为等价 | ✓ |
GET /capabilities 新增 transports 字段 |
客户端忽略未知字段 | ✓ |
new DaemonClient({ baseUrl, token }) 不带 transport = 构造 RestSseTransport = 当前 REST 行为。完全等价。
4. Runtime fallback 设计:consumer-driven 是否正确? ✓✓
这是设计中最好的决策之一。
Transport 不静默切换协议,而是 fail loudly(DaemonTransportClosedError),由 consumer 决定重建策略。理由充分:
- WS teardown 会触发 server-side
registry.delete→conn.destroy→ 所有 session 被销毁 - 静默 fallback 会隐藏这个数据丢失
session/load可以 re-attach 到现有 bridge session(transcript 保留),但 in-flight prompt 被 abort
AutoReconnectTransport 作为 opt-in wrapper 也是对的——不需要 auto-reconnect 的 consumer 直接 catch error 自己处理。
5. 实现计划:单 PR ~1300 行是否可行? ✓(1 个风险)
从 4 PR 合并为 1 PR 是正确的——这些变更是一个连贯的抽象层引入,拆成 4 个小 PR 反而增加 review 负担。
风险:URL→JSON-RPC mapping 表的维护
AcpWsTransport 需要维护一个 /session/:id/prompt → {method: "session/prompt", params: {sessionId: id, ...body}} 的映射表。daemon 新增路由时如果忘了更新 transport,调用会静默失败(JSON-RPC method not found)。
建议:
- 映射表放在
AcpWsTransport.ts文件顶部,一目了然 - 考虑添加
// AUTO-GENERATED from dispatch.ts route registry注释 + 简单的脚本校验 - 或者在
DaemonTransport测试中添加一个 "all DaemonClient methods have a mapping" 的穷举测试
6. 风险矩阵补充
文档的 §8 Risks 覆盖了主要风险,补充 2 个:
风险 A:Synthesized Response 的 headers 保真度
当前 DaemonClient 的某些方法读取 Response headers:
Retry-Afterheader(rate limiting)Content-Typeheader(SSE 验证)
WS transport 合成的 Response 需要正确模拟这些 headers。特别是 subscribeEvents 在 REST 路径下检查 content-type: text/event-stream——如果 WS transport 的 subscribeEvents 不走 fetch,这不是问题(WS transport 的 subscribeEvents 直接 yield DaemonEvent)。但如果有其他方法检查 response headers,合成 Response 需要提供正确的 headers。
建议:在 DaemonTransport.fetch 契约中补充 "Synthesized Response MUST include content-type header matching the original daemon response"。
风险 B:negotiate() 的 WS upgrade 探测
negotiate() 通过实际尝试 WS upgrade 来检测可用性。如果 daemon 支持 WS 但连接因防火墙/代理被阻断,negotiate() 会 timeout 然后 fallback 到 REST。这个 timeout 时间(默认?)需要合理——太短可能误判,太长延迟启动。
建议:negotiate() 接受可选的 probeTimeoutMs 参数,默认 3-5s。并在 JSDoc 中说明 fallback 行为。
总结
| 维度 | 评估 |
|---|---|
| 抽象层选择 | ✓ fetch-level 是正确切面 |
| 接口设计 | ✓ 完备,2 个建议(generator 中断语义 + type 可扩展性) |
| 向后兼容 | ✓ 零破坏性变更,已验证 |
| Runtime fallback | ✓✓ consumer-driven 是最佳决策 |
| 实现计划 | ✓ 单 PR 可行,注意 mapping 表维护 |
| 风险覆盖 | ✓ 主要风险已识别,补充 2 个(Response headers + negotiate timeout) |
结论:方案设计合理,建议通过。 4 个建议项均为 non-blocking,可在实现 PR 中逐步完善。核心架构决策(fetch-level 抽象、subscribeEvents 分离、consumer-driven fallback)都是正确的。
此审计由 QoderWork AI 生成
设计审计:方向认可,但 v4 不建议直接按单个实现 PR 推进我对照了当前 SDK / webui provider / SSE replay 代码看了一遍。结论是:fetch-level 主要问题
建议拆分我建议把实现拆成更小、更可验证的 PR:
核心方向我支持;需要收敛的是 scope 和生命周期契约。现在直接上 single ~1300 line PR,review 会被 ACP 映射、provider lifecycle、fallback 和 replay 语义绑在一起,风险偏高。 |
… semantics Address review findings (keep single PR, no split): - Fix doc header: v2 → v4, update TL;DR to match ~1300 lines scope - Add Provider injection point: DaemonWorkspaceProvider gains optional transport prop (~5 lines), forwarded to DaemonClient constructor - Fix event id contract: DaemonEvent.id is optional (synthetic frames like stream_error may omit it); monotonicity required only when present - Add abort/cancel contract: transport MUST propagate signal abort to wire (WS → session/cancel RPC, HTTP → abort fetch) - Add generator disconnect contract: transport MUST throw DaemonTransportClosedError on all pending generators when connection dies - Add lastEventId replay declaration requirement per transport - Add DaemonCapabilities.transports type + negotiate probeTimeoutMs Generated with AI Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
|
Re: 两条审计评论 已在 commit ed72efe 中修复所有 6 个问题,保持单 PR 方案不拆分:
关于"建议拆回 4 PR":保持单 PR。这些变更是一个连贯的抽象层引入,拆成小 PR 增加 review 上下文切换成本。 |
Follow-up after ed72efeThanks for the update. This version addresses most of the previous concrete gaps: the doc header/scope now matches v4, provider injection is acknowledged, I still think there are a few remaining issues to resolve before treating this as implementation-ready:
Core direction still looks right. These are mainly consistency and lifecycle-closure issues so the implementation PR does not start from a half-specified fallback/replay contract. |
1. Abort semantics: method-specific (prompt abort → session/cancel RPC; ordinary request abort → reject only, no side effects) 2. Add supportsReplay: boolean to interface (REST=true, WS=false) 3. RestSseTransport constructor: add baseUrl, token, _fetch (not just _fetch) 4. Fix stale contradictions: remove "follow-up PR" / "separate PR" wording, align §5.2 with provider injection, update §7 verification for single PR 5. Fix DaemonCapabilities location: types.ts not DaemonClient.ts 6. Runtime fallback: provider does NOT auto-rebuild; consumer/AutoReconnectTransport catches DaemonTransportClosedError and rebuilds explicitly Generated with AI Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
|
Re: Follow-up after ed72efe 5 个问题全部修复 (commit bd78fb4):
|
🧪 Verification: DaemonTransport abstraction design doc — SKIP (docs-only, no runtime surface) + factual audit against latest
|
| # | Doc claim | Against main 5854e28 |
|---|---|---|
| 1 | this._fetch = globalThis.fetch default, injectable via DaemonClientOptions.fetch |
✅ DaemonClient.ts:329 — opts.fetch ?? globalThis.fetch.bind(globalThis) |
| 2 | "67 public methods" (and "all other 66 work through fetch") | main moves fast |
| 3 | subscribeEvents has inline SSE logic: content-type validation, connect-phase timeout, parseSseStream |
✅ all three present inline (Accept: text/event-stream header, connect AbortController composed with caller signal, content-type check, yield* parseSseStream(...)) |
| 4 | Exactly 6 methods bypass fetchWithTimeout via direct this._fetch: prompt, promptNonBlocking, recapSession, btwSession, shellCommand, subscribeEvents |
✅ exact match — I mapped every this._fetch( call site to its enclosing method; those six, no more, no fewer |
| 5 | prompt() branches 202 vs 200 |
✅ if (res.status === 202) with temporary-SSE non-blocking path |
| 6 | deleteWorkspaceAgent() 204 vs 404 with body inspection |
✅ 204 early-return; 404 inspected for structured agent_not_found vs bare-404 (proxy/old-daemon) — doc's characterization is precise |
| 7 | respondToPermission() 200 vs 404 race detection |
✅ returns true on 200, false on 404 ("lost the race" comment in source) |
| 8 | DaemonHttpError public API |
✅ DaemonClient.ts:190 |
| 9 | DaemonSessionClient delegates to DaemonClient |
✅ thin delegation wrapper |
| 10 | Both providers construct DaemonClient internally |
✅ DaemonWorkspaceProvider.tsx:44, DaemonSessionProvider.tsx:271 — exact files the implementation table targets |
| 11 | Consumer counts: webui 25 / web-shell 4 / vscode-ide-companion 1 | ✅ within counting-method tolerance (I measure 24–27 / 2–6 / exactly 1 depending on symbol set) |
| 12 | GET /capabilities exists in packages/cli/src/serve/server.ts |
✅ route present (+ capabilities.ts module) — the proposed transports field is additive as claimed |
| 13 | "WS teardown destroys all owned sessions server-side (registry.delete → conn.destroy)" |
✅ exact chain — connectionRegistry.ts:387-392: delete() calls conn.destroy() then evicts; ACP-side conn reaping calls registry.delete |
| 14 | session/load re-attaches to existing bridge session |
✅ dispatch.ts handles session/load; registry comments document attach semantics |
| 15 | DaemonStoreContext exists (the TerminalView in §1.2 is the third party's component, not ours) |
✅ DaemonSessionProvider.tsx:100 |
| 16 | "All type exports (100+)" unchanged | ✅ ~357 identifiers re-exported from daemon/index.ts |
| 17 | parseSseStream is the SSE decode path |
✅ sse.ts, consumed at DaemonClient.ts:1985 |
| 18 | DaemonClientOptions fields (baseUrl, token?, fetch?, fetchTimeoutMs?) all kept |
✅ all present today |
The three hardest-to-fake claims — the six named _fetch bypass sites, the registry.delete → conn.destroy teardown chain, and the exact provider construction sites — are all precisely accurate. This doc was written against the real code, not from memory.
Findings (doc nits, none blocking)
- Duplicate section number: there are two
### 2.5sections ("Provider injection point" and "RestSseTransport"); numbering then continues at 2.6 — one needs renumbering. - Method-count drift: "67 public methods" is already 72 on
main. Suggest "~70 (grows with main)" phrasing, and re-derive the 6-bypass list at implementation time (it's exact today). RestSseTransport.connected ≡ truevs the interface contract: theDaemonTransportcontract saysconnectedis "False after connection drop or dispose()", but the sketch pinsreadonly connected = true("REST is stateless"). An implementer following the sketch violates the contract afterdispose(). Either carve out a documented exception for stateless transports or make it a getter that flips on dispose.- The runtime-fallback section's data-loss rationale (consumer-driven rebuild because server-side conn teardown destroys owned sessions) matches the actual server behavior I verified in Qwen-Code still tries to access Google's IP #13 — the design's most safety-relevant argument stands on real semantics.
Verdict (merge reference)
As a design document this is accurate against the code it proposes to change — every mechanical claim I could check holds on latest main, including the subtle ones. The three nits above are editorial. From a verification standpoint there is nothing runtime to gate on; if the design direction is acceptable to the maintainers, the doc is in good shape to land as the design-first artifact. (The implementation PR, when it comes, is where the tmux protocol applies — §7's verification list maps cleanly onto it, and I'd suggest adding "vote/permission round-trip over each transport" to its E2E matrix since respondToPermission's 404-race semantics are transport-sensitive.)
🇨🇳 中文版(点击展开)
🧪 验证:DaemonTransport 抽象层设计文档 — SKIP(纯文档、无运行时表面)+ 对照最新 main 的事实审计 — ✅ 准确
裁定:SKIP(运行时意义上)——本 PR 只新增一个 markdown 文件(docs/design/daemon-transport-abstraction/README.md,+473/−0,6 个 commit)。该分支构建出的 CLI 与 main 行为逐字节相同,因此我在代码类 PR(#4947、#4161、#4971)上使用的"构建 + tmux 实测"流程在这里只会是走过场。设计文档真正可能出错的地方,是它对现有系统的描述——基于误读代码库的设计会在实现阶段塌掉。所以我把文档中所有可核查的现状事实声明逐条对照了最新 main(5854e2832b,审查时拉取)。
声明审计(核查 18 条)
| # | 文档声明 | 对照 main 5854e28 |
|---|---|---|
| 1 | this._fetch = globalThis.fetch 为默认值、可经 DaemonClientOptions.fetch 注入 |
✅ DaemonClient.ts:329 |
| 2 | "67 个公开方法"(及"其余 66 个方法走 fetch") | main 前进很快 |
| 3 | subscribeEvents 含内联 SSE 逻辑:content-type 校验、连接阶段超时、parseSseStream |
✅ 三者俱在 |
| 4 | 恰好 6 个方法绕过 fetchWithTimeout 直调 this._fetch:prompt、promptNonBlocking、recapSession、btwSession、shellCommand、subscribeEvents |
✅ 完全命中——我把每个 this._fetch( 调用点映射回所属方法;正是这六个,不多不少 |
| 5 | prompt() 202 vs 200 分支 |
✅ |
| 6 | deleteWorkspaceAgent() 204 vs 404 + body 检查 |
✅ 404 区分结构化 agent_not_found 与裸 404——文档的刻画很精确 |
| 7 | respondToPermission() 200 vs 404 竞态检测 |
✅ 源码注释即"lost the race" |
| 8 | DaemonHttpError 公开 API |
✅ |
| 9 | DaemonSessionClient 委托 DaemonClient |
✅ |
| 10 | 两个 Provider 都在内部构造 DaemonClient |
✅ DaemonWorkspaceProvider.tsx:44、DaemonSessionProvider.tsx:271——与实现表针对的文件一致 |
| 11 | 消费方计数:webui 25 / web-shell 4 / vscode-ide-companion 1 | ✅ 在计数口径容差内(我测得 24–27 / 2–6 / 恰好 1) |
| 12 | GET /capabilities 存在于 packages/cli/src/serve/server.ts |
✅ 路由在(另有 capabilities.ts)——拟新增的 transports 字段确为增量式 |
| 13 | "WS 拆除会在服务端销毁所有归属会话(registry.delete → conn.destroy)" |
✅ 链路完全一致——connectionRegistry.ts:387-392 |
| 14 | session/load 重新挂接既有 bridge 会话 |
✅ dispatch.ts 处理 session/load |
| 15 | DaemonStoreContext 存在(§1.2 的 TerminalView 是第三方组件示例,非本仓库) |
✅ DaemonSessionProvider.tsx:100 |
| 16 | "全部类型导出(100+)"保持不变 | ✅ daemon/index.ts 重导出约 357 个标识符 |
| 17 | parseSseStream 为 SSE 解码路径 |
✅ |
| 18 | DaemonClientOptions 字段(baseUrl、token?、fetch?、fetchTimeoutMs?)全保留 |
✅ |
三条最难"凭印象写对"的声明——6 个具名 _fetch 绕过点、registry.delete → conn.destroy 拆除链、Provider 构造点的确切文件——全部精确吻合。这份文档是对着真实代码写的,不是凭记忆。
发现(文档小问题,均不阻塞)
- 章节号重复: 有两个
### 2.5("Provider injection point" 与 "RestSseTransport"),其后直接续 2.6——需要重排。 - 方法数漂移: "67 个公开方法"在
main上已是 72。建议改为"约 70(随 main 增长)",并在实现时重新推导 6 个绕过点清单(今日仍精确)。 RestSseTransport.connected ≡ true与接口契约的张力:DaemonTransport契约写明connected在"连接断开或 dispose() 后为 false",但草图将其钉死为readonly connected = true("REST 无状态")。照草图实现会在dispose()后违反契约。建议要么为无状态传输明确豁免,要么改为随 dispose 翻转的 getter。- 运行时回退一节的数据丢失论证(因服务端连接拆除会销毁归属会话,故回退必须由消费方显式驱动)与我在第 13 条核实的真实服务端行为一致——设计中最关乎安全的论点立足于真实语义。
结论(合并参考)
作为设计文档,它对其拟改动的代码的描述是准确的——所有可机械核查的声明在最新 main 上全部成立,包括细节最刁钻的几条。上述三个小问题属编辑性质。验证角度没有可把关的运行时行为;若维护者认可设计方向,该文档可以作为 design-first 产物落地。(后续实现 PR 才是 tmux 流程的用武之地——§7 的验证清单可直接映射过去;建议在其 E2E 矩阵中补一项"每种传输下的权限投票往返",因为 respondToPermission 的 404 竞态语义对传输层敏感。)
|
设计文档 PR 的实现已在 #5040 落地。wenshao 的本地验证发现了 6 个实现层面的问题,正在修复中。 |
Summary
Design doc for making
DaemonClienttransport-agnostic via a fetch-levelDaemonTransportinterface.DaemonClient— one provider, one store, pluggable transporttransportis an optional addition toDaemonClientOptionsWhat reviewers should weigh in on
DaemonError.kind) the right prerequisite, or can we defer it?AcpWsTransportship in the same PR as the interface, or as a follow-up?Test plan
🤖 Generated with Qwen Code