feat(sdk): Add standalone session APIs - #10294
Conversation
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
eb92154 to
da904d7
Compare
|
Please do not rebase or force-push to an active PR as it invalidates existing review comments. Note for future reference, the bots always squash all changes into a single commit automatically as part of the integration. 中文请勿对活跃的 PR 执行 rebase 或 force-push,因为这会使已有的评审评论失效。另外,供日后参考:作为集成流程的一部分,机器人始终会自动将所有改动压缩(squash)为单个提交。 |
|
✅ Qwen Triage finished — CI landed green on ✅ Qwen Triage 已完成 —— |
|
Thanks for the PR! Template looks good ✓ Problem: grounded, not theoretical. The daemon-side standalone lifecycle ( Direction: aligned. This is PR4 of a planned sequence — the routes, error codes ( Size: core-module gate not applicable — all code lives in Approach: scope feels right. One new leaf module keeps the standalone types and runtime validators out of the already-large general daemon type file; HTTP ownership stays in Risk: no elevated risk signals — none of the changed files match the revert-correlated high-risk paths. Moving on to code review. 🔍 中文说明感谢贡献! 模板完整 ✓ 问题:有实际依据,不是理论性问题。daemon 侧的 standalone 生命周期( 方向:对齐。这是既定序列中的 PR4——路由、错误码( 规模:核心模块门禁不适用——全部代码位于 方案:范围合理。新增的叶子模块把 standalone 类型和运行时校验器与已经很大的通用 daemon 类型文件隔离;HTTP 仍归 风险:无升级风险信号——改动文件均未命中与 revert 相关的高风险路径。 进入代码审查 🔍 — Qwen Code · qwen3.8-max Reviewed at |
Code reviewIndependent proposal. Given "SDK surface for Comparison. The PR matches that proposal point for point — and goes further where I might have cut corners: every new JSON response is runtime-validated, and the recovery union distinguishes
Follow-up commit ( Two non-blocking notes carried over from the first pass:
Create-recovery flowsequenceDiagram
participant P1 as Caller
participant P2 as DaemonClient (SDK)
participant P3 as Daemon
P1->>P2: createStandaloneSession
P2->>P2: generate UUID when caller gives none
P2->>P3: POST standalone-sessions (sessionId, never cwd)
alt definite result
P3-->>P2: 200 session JSON, or a definite HTTP error
P2->>P2: runtime-validate the response
P2-->>P1: DaemonStandaloneSession
else unknown outcome (transport failure, timeout, structured code, malformed success)
P2->>P3: exactly one GET standalone-sessions-id lookup
alt 202
P3-->>P2: recovery state creating
else 200
P3-->>P2: recovery state existing
else 404 standalone_session_not_found
P3-->>P2: recovery state absent
end
P2-->>P1: outcome-unknown error carrying recovery context
end
Files changed (10)
Test evidence — the PR's own CIThe full suite ran once on this PR already — the author dispatched it via Final CI results for
One row per check name (latest run); skipped checks omitted; failures sort first. / 每个检查名一行(取最新一次运行),省略 skipped,失败项排在最前。 What the earlier full-suite run on The not-this-PR call is structural, not a vibe: the diff is confined to Nothing user-visible to drive in a terminal here (SDK-only change); real-scenario testing is N/A on this CI path. Sandboxed verification of the one remaining behavioural claim is in flight: the 中文说明代码审查:我的独立方案(capability 门控的 后续提交 测试证据:完整套件此前已在上一 head( 沙箱验证仍在进行: — Qwen Code · qwen3.8-max Reviewed at |
|
Confidence: 4/5 — clean, contract-verified review, now with the follow-up commit addressing every automated-review pin; approval is deferred only because this head's own CI is still running. Stepping back: this PR keeps getting better without getting bigger. The base surface was already the right shape — capability-gated, fail-closed, runtime-validated, wire-checked against the merged daemon routes rather than the PR's own mocks. Then the automated review pass produced 21 mutation-tested suggestions — the unglamorous kind, "this behavior is pinned by no test" — and the author's response is exactly what you want to see: every thread answered with a commit that adds real pins (fake-timer timeout proof, exact-identity protocol errors, generated-UUID recovery on the true no-id path, watermark/epoch seeding, replay negatives, the workspace fallback branch) and weakens nothing. The single production change in that commit is a genuine bug fix: the public Two things a maintainer should know:
The sandboxed Verdict: approve — and since this head's CI is still running, approval is deferred until CI lands green on 中文说明总体评价:这个 PR 在不断变好的同时没有膨胀。基础接口本来就是正确的形态——capability 门控、失败关闭、运行时校验,线上形状对照的是已合入的 daemon 路由而非 PR 自带 mock。随后自动审查给出了 21 条基于变异测试的建议(都是"该行为没有任何测试钉住"这类不显眼的问题),作者的回应正是理想的样子:每条意见都用一个提交落实,新增的是真实钉桩(fake-timer 超时证明、精确身份协议错误、真正走无 sessionId 分支的生成 UUID 恢复、水位/纪元种子、replay 负例、workspace 回退分支),没有削弱任何东西。该提交中唯一的生产改动是一个真实 bug 修复:公开的 两件维护者需要知道的事:
沙箱 结论:批准——由于本 head 的 CI 仍在运行,批准延迟到套件在 — Qwen Code · qwen3.8-max Reviewed at |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Reviewed. Suggestions are inline.
中文说明
已审查。 建议见行内评论。
— qwen3.8-max via Qwen Code /review (v0.22.2)
chiga0
left a comment
There was a problem hiding this comment.
Tier: Deep — 新 wire 协议 + 错误层次 + 恢复状态机
已验证内容
UUID-before-dispatch 模式
createStandaloneSession 在发出 POST 之前就已生成/规范化 UUID(requestedSessionId ?? crypto.randomUUID() → .toLowerCase()),确保在任何失败路径下都能用同一个 UUID 做精确查询恢复。这是正确设计。
Recovery 逻辑
recoverStandaloneCreation 做单次精确 lookup(GET /standalone/sessions/{sessionId}),返回四种状态:
creating:lookup 返回含state字段的响应existing:lookup 返回完整 summaryabsent:404 standalone_session_not_foundunknown:lookup 本身失败(非 404)
catch 条件正确:DaemonHttpError && !isStandaloneCreationOutcomeUnknown → 直接抛出(明确拒绝);其余(transport error、protocol error from parseStandaloneSession、structured unknown-outcome code)→ 触发 recovery。
UUID 规范化
所有路由均调用 sessionId.toLowerCase(),测试中 UPPER_SESSION_ID case 覆盖了这一路径。
Capability gate
createStandaloneSession 在 UUID 生成前显式调用 requireCapability,standaloneJsonRequest 内部也会调用,各自符合语义。
验证函数
parseStandaloneSession、parseStandaloneLookup、parseStandaloneListPage 等解析函数设计一致,均抛 DaemonStandaloneProtocolError。
测试覆盖(已运行部分)
测试覆盖:UUID 生成 vs 调用方提供、规范化、transport 错误、timeout、structured outcome unknown、malformed success、409 明确拒绝、全路由族。
CI 全跳过
所有 CI checks(含 build-cli)状态均为 SKIPPED,无构建/测试运行证据。测试本身结构合理,但未在 CI 中执行过。
CI Bot 建议汇总(均为 test coverage 类,无逻辑 bug)
CI bot 提出了 15 项建议,全部为测试覆盖缺口,主要包括:
- R1-1:
isStandaloneCreationOutcomeUnknown导出函数对消费者容易误用——消费者从createStandaloneSessioncatch 到的错误是DaemonStandaloneCreationOutcomeUnknownError(不是DaemonHttpError),该函数对其返回false。消费者应使用instanceof DaemonStandaloneCreationOutcomeUnknownError,但函数名可能引发混淆。 - R1-3:
recovery.state === 'unknown'(lookup 本身失败)没有测试覆盖,对应 mutation 可存活。 - R1-4/R1-5/R1-6/R1-7:
getStandaloneSession、exportStandaloneSession的 capability gate 无负向测试;listStandaloneSessionsPage的cursor/size/archiveState缺省时的 URL 参数省略无测试覆盖,mutation 可存活。 - R1-2:公开表面 drift fence 漏掉 5 个类型(
DaemonUnarchiveStandaloneSessionsResult、DaemonStandaloneBatchError、DaemonStandaloneFields、DaemonStandaloneSessionCreating、DaemonStandaloneWorkingDirectory)。 - R1-8:
loadStandaloneSession的timeoutMs转发无测试验证实际生效。
以上均为建议级别,无阻塞项。
|
@qwen-code /triage |
|
Sandboxed verification: ✅ passed — merge-ready (agent verdict) - workflow run Ran the PR in an isolated, token-free container: A/B against the base build, mock-free harness assertions, targeted gates. Advisory evidence for human reviewers — not a review, an approval, or a CI check. Scripted assertions: 1802 passed · 0 failed · 1802 total Flakiness gate: ✅ 3 changed test file(s) x 5 identical rounds, no divergence 中文 — 判定:✅ 通过 · 可合入(agent 判定)沙箱验证在隔离、无凭证的容器中执行了该 PR 的代码(与 base 构建 A/B 对照、无 mock harness 断言、定向门禁)。仅作为评审证据,不构成评审、批准或 CI 检查。 脚本断言:1802 通过 · 0 失败 · 1802 总计 抖动门:✅ 3 changed test file(s) x 5 identical rounds, no divergence Verification reportPR #10294 — feat(sdk): Add standalone session APIsVerdict: 中文摘要
Central claim and A/BCentral claim (from the PR): the SDK exposes a capability-gated ( The surface is purely additive, so the A/B has two controls: (a) the API is absent at base (
Witness: Wire oracle (harness-1, 79/79, built head dist over real sockets against a fake daemon encoding the #10179 route semantics — strict body/query allowlists returning 400
Reattach strategy (harness-2, 23/23): witness Reviewer Test Plan walkthrough
Mutation matrix (PR guards vs PR tests)Witness:
No survivors; no layered-guard combination row needed (M4a/M4b guard disjoint method sets, not one hazard from two directions). FindingsF1 (Suggestion, non-blocking) — test name overstates its fixture. F2 (Suggestion, non-blocking) — create's capability probe is pinned only indirectly. M4b (removing Not covered
MethodologyEnvironment: CI verify container (node:22-bookworm), merge-ref checkout (HEAD = merge commit). Harnesses in this artifact dir drive the built head dist ( Flakiness gate logEvidence imagesHarness scripts and raw logs are in the workflow run artifacts (7-day retention). — Qwen Code · sandboxed verification |
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
|
Review feedback addressed in f9860e5 Handled all 21 new inline suggestions in one focused batch. The SDK outcome-unknown guard now recognizes its public wrapper, and the expanded tests pin public exports, capability gates, list-query omission, timeout forwarding, exact/canonical session identity, generated-UUID recovery, unknown lookup recovery, batch validation, restore strategy, replay cursor/epoch state, attachment hydration, and replay completeness/degradation semantics. Verification completed:
All 21 handled threads have replies and are being resolved. |
|
Triage re-run completed without a new review.
The stage comments above were updated with the latest result. View workflow run. 上方各阶段评论已更新为最新结果。查看工作流运行。 |
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. |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
LGTM, looks ready to ship — CI landed green after the review. ✅
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Partially reviewed — gaps disclosed. Suggestions are inline.
Not reviewed: reverse audit — did not converge within the reverse-audit round cap of 5.
Deferred under the convergence posture (round 2, not a blocker) — recorded, not requested in this round:
packages/sdk-typescript/src/daemon/DaemonSessionClient.ts:202 — [review] replaySnapshotComplete true branch never exercised on standalone loadpackages/sdk-typescript/src/daemon/standalone-sessions.ts:398 — [review] recovery 404 classification unpinned for foreign body codespackages/sdk-typescript/src/daemon/DaemonClient.ts:2608 — [review] standalone list pageSize unclamped unlike workspace twinpackages/sdk-typescript/test/unit/DaemonClientStandalone.test.ts:367 — [review] repair-directory body assertion vacuous via ?? '{}'packages/sdk-typescript/test/unit/DaemonClientStandalone.test.ts:633 — [review] liveMergeFailed/truncated list-page validation unpinnedpackages/sdk-typescript/test/unit/DaemonClientStandalone.test.ts:662 — [review] workingDirectory warnings validation unpinned for rejectionpackages/sdk-typescript/test/unit/DaemonClientStandalone.test.ts:623 — [review] top-level asRecord rejection unpinned across parsers
中文说明
仅完成部分审查,审查缺口已披露。 建议见行内评论。
未审查:反向审计——在 5 轮的反审轮数上限内未收敛。
收敛姿态下延后(第 2 轮,非阻断)——已记录,本轮不要求修改:共 7 条(原文未翻译,列表见上方英文部分)。
— qwen3.8-max via Qwen Code /review (v0.22.2)
| }); | ||
| }); | ||
|
|
||
| it('rejects an exact lookup response for a different session id', async () => { |
There was a problem hiding this comment.
[Suggestion] The exact-identity response check (the expected-id argument of requireSessionId) has a mismatch test only for this 200/summary lookup branch. The same defense on the create, load/resume, repair, and rename parse call sites (DaemonClient.ts:2575/2779/2663/2678) and in this lookup's 202-creating branch has no mismatch test anywhere. Dropping or mis-passing the expected-id argument at any of those sites leaves the whole suite green — measured: each single-site mutation left 91/91 tests passing. A daemon, cache, or proxy answering one of those routes with a different session's payload would then be accepted silently, replaying the wrong session's history/state or applying a rename/directory result to the wrong record. Mirror this test for the remaining sites: respond with a fixture whose sessionId differs (e.g. ...446655440001) for create, load, resume, repair, rename, and for a 202 creating payload, and assert rejection — on create the protocol error is wrapped, so assert DaemonStandaloneCreationOutcomeUnknownError (or its originalError) there; the other routes reject with DaemonStandaloneProtocolError directly. Each added test must go red when the expectedSessionId/normalized argument is removed from the corresponding parse call site.
中文说明
精确身份响应校验(requireSessionId 的 expected-id 参数)只在这个 200/summary 查询分支上有不匹配测试。create、load/resume、repair、rename 各解析调用点(DaemonClient.ts:2575/2779/2663/2678)以及本查询的 202-creating 分支上的同一防御没有任何不匹配测试。删除或错传这些调用点的 expected-id 参数,整个测试套件仍然全绿——实测:每个单点突变后 91/91 测试全部通过。此时若 daemon、缓存或代理对这些路由之一返回另一个 session 的载荷,将被静默接受:适配器会回放错误 session 的历史/状态,或把重命名/目录修复结果应用到错误的记录上。请仿照本测试补齐其余调用点:对 create、load、resume、repair、rename 以及 202 creating 载荷,返回 sessionId 不同(如 ...446655440001)的 fixture 并断言拒绝——create 上的协议错误会被包装,需断言 DaemonStandaloneCreationOutcomeUnknownError(或其 originalError);其他路由直接以 DaemonStandaloneProtocolError 拒绝。每个新增测试必须在从对应解析调用点移除 expectedSessionId/normalized 参数时变红。
— qwen3.8-max via Qwen Code /review (v0.22.2)
| }); | ||
| }); | ||
|
|
||
| it('preserves exact lookup 202 creating responses', async () => { |
There was a problem hiding this comment.
[Suggestion] The requireSessionId(..., expectedSessionId) check in this lookup's state === 'creating' branch is exercised only with a matching session id; no fixture feeds a foreign id with state: 'creating'. Dropping the branch's expected-id argument leaves the suite green — measured: with the check downgraded to an unchecked requireString read, the committed suite stays green while a foreign-id 202 probe flips from rejecting to resolving. A stale cache entry or router bug answering GET /standalone/sessions/:id with another session's creating payload would then resolve silently, and getStandaloneSession reports creating for a session that is not the caller's. Add a mismatch case answering getStandaloneSession(SESSION_ID) with jsonResponse(202, { sessionId: '550e8400-e29b-41d4-a716-446655440001', state: 'creating' }) and asserting rejection with DaemonStandaloneProtocolError. The added test must go red when the requireSessionId check in the creating branch of parseStandaloneLookup is replaced with an unchecked requireString read.
中文说明
本查询 state === 'creating' 分支中的 requireSessionId(..., expectedSessionId) 校验只用匹配的 session id 执行过;没有任何 fixture 用 state: 'creating' 传入外来 id。删除该分支的 expected-id 参数,测试套件仍然全绿——实测:把该校验降级为不带校验的 requireString 读取后,已提交的套件依然全绿,而外来 id 的 202 探测从拒绝变为成功解析。此时若过期缓存或路由错误对 GET /standalone/sessions/:id 返回另一个 session 的 creating 载荷,将被静默解析,getStandaloneSession 会对不属于调用方的 session 报告 creating。请新增一个不匹配用例:对 getStandaloneSession(SESSION_ID) 返回 jsonResponse(202, { sessionId: '550e8400-e29b-41d4-a716-446655440001', state: 'creating' }) 并断言以 DaemonStandaloneProtocolError 拒绝。当 parseStandaloneLookup creating 分支中的 requireSessionId 校验被替换为不带校验的 requireString 读取时,新增测试必须变红。
— qwen3.8-max via Qwen Code /review (v0.22.2)
| expect(loaded.replaySnapshotComplete).toBe(false); | ||
| expect(loaded.replayPartial).toBe(true); | ||
| expect(loaded.replayError).toBe('journal read failed'); |
There was a problem hiding this comment.
[Suggestion] This standalone load test pins every restored-payload field forwarded by createStandaloneRestoredClient except historyHasMore and historyAnchorRecordId — no standalone fixture sets them, so that forwarding branch is unpinned (the existing pins exercise only the workspace load path). Dropping the two fields from the standalone destructure/forwarding leaves the whole suite green — measured: the full sdk suite passes 1661/1661 under that mutant. A standalone load whose persisted history precedes the replay page would then report historyHasMore: false with no historyAnchorRecordId, so adapters stop offering backward pagination and the restored standalone transcript is silently truncated. Add historyHasMore: true, historyAnchorRecordId: 'record-anchor' to this fixture and assert both on the loaded client. The new assertions must go red if the historyHasMore/historyAnchorRecordId forwarding is removed from createStandaloneRestoredClient.
中文说明
这个 standalone load 测试为 createStandaloneRestoredClient 转发的每个 restored 载荷字段做了断言,唯独缺了 historyHasMore 和 historyAnchorRecordId——没有任何 standalone fixture 设置这两个字段,因此该转发分支没有被测试钉住(现有的断言只覆盖 workspace load 路径)。从 standalone 的解构/转发中删除这两个字段,整个套件仍然全绿——实测:该突变下完整 sdk 套件 1661/1661 全部通过。此时若 standalone load 的持久化历史早于 replay 分页,将报告 historyHasMore: false 且不携带 historyAnchorRecordId,适配器将不再提供向前翻页,恢复出的 standalone 会话记录会被静默截断。请在本 fixture 中加入 historyHasMore: true, historyAnchorRecordId: 'record-anchor',并在 loaded client 上断言这两个字段。当从 createStandaloneRestoredClient 中移除 historyHasMore/historyAnchorRecordId 转发时,新增断言必须变红。
— qwen3.8-max via Qwen Code /review (v0.22.2)
| ).toHaveLength(1); | ||
| }); | ||
|
|
||
| it('reports unknown recovery when the exact lookup also fails', async () => { |
There was a problem hiding this comment.
[Suggestion] This test only exercises an HTTP 500 from the recovery lookup; the transport-level arm of recoverStandaloneCreation's catch — a TypeError thrown by the lookup fetch itself — has no test in any direction. That arm is the common real-world shape: a create POST that hits connection reset is treated as outcome-unknown precisely because the network is failing, so the follow-up lookup failing at transport level too is expected. Narrowing the catch to rethrow non-DaemonHttpErrors leaves the suite green — measured: 91/91 pass under the mutant — so createStandaloneSession rejects with a raw TypeError, isStandaloneCreationOutcomeUnknown(error) is false for it, and an adapter keying retry decisions on that documented guard retries the create, colliding with a session the daemon may already be creating. Add a variant where the recovery lookup fetch throws new TypeError('connection reset') (with the create POST also throwing), asserting the rejection is DaemonStandaloneCreationOutcomeUnknownError with recovery: { state: 'unknown', sessionId: SESSION_ID } and recovery.error being the lookup's TypeError. The new test must go red if recoverStandaloneCreation's catch is narrowed to handle only error instanceof DaemonHttpError.
中文说明
本测试只覆盖了恢复查询返回 HTTP 500 的情形;recoverStandaloneCreation catch 的传输层分支——查询 fetch 本身抛出 TypeError——在任何方向上都没有测试。该分支恰恰是现实中的常见形态:create POST 遇到 connection reset 时正因为网络正在失败才被判定为结果未知,所以随后的精确查询也在传输层失败是预期内的情况。把 catch 收窄为重新抛出非 DaemonHttpError 错误,测试套件仍然全绿——实测:该突变下 91/91 全部通过——于是 createStandaloneSession 会以裸 TypeError 拒绝,isStandaloneCreationOutcomeUnknown(error) 对其返回 false,依赖这个公开守卫做重试决策的适配器会重试创建,从而与 daemon 可能正在创建的 session 发生冲突。请新增一个变体:恢复查询的 fetch 抛出 new TypeError('connection reset')(create POST 也抛出异常),断言拒绝值是 DaemonStandaloneCreationOutcomeUnknownError,且 recovery: { state: 'unknown', sessionId: SESSION_ID }、recovery.error 是查询的 TypeError。当 recoverStandaloneCreation 的 catch 被收窄为只处理 error instanceof DaemonHttpError 时,新增测试必须变红。
— qwen3.8-max via Qwen Code /review (v0.22.2)
Review closeout — verified at head
|
yiliang114
left a comment
There was a problem hiding this comment.
Approving. The four outstanding threads are suggestion-level test-pinning asks; the production defenses they target (expected-sessionId checks at every parse site, history-anchor forwarding, generic recovery catch) are all verified present and correct at head f9860e5. CI fully green, MERGEABLE.
|
Released in v0.22.3. |




What this PR does
This PR adds the TypeScript SDK surface for the
standalone_sessions_v1daemon API. It provides capability-gated lifecycle methods for create, list, exact lookup, load, resume, directory repair, rename, export, archive, unarchive, and delete; exposes narrow standalone response and recovery types; validates every new JSON response before returning it; and keeps session reattachment on an explicit standalone or workspace restore strategy.Create generates a UUID before dispatch when the caller does not provide one. A structured outcome-unknown response, transport failure, timeout, or malformed success triggers exactly one exact lookup with that UUID and returns recovery context without retrying creation.
This PR builds on the standalone daemon API merged in #10179 and now targets
maindirectly.Why it's needed
PR #10179 exposes the standalone lifecycle over REST, but SDK consumers would otherwise need to construct private routes, duplicate response validation, and risk retrying an outcome-unknown create. This change gives browser and Node consumers one fail-closed API that cannot supply a workspace selector or fall back to the primary workspace.
Reviewer Test Plan
How to verify
Run the TypeScript SDK tests and confirm the standalone request-shape suite covers every lifecycle route, capability absence, caller and generated UUIDs, exact
202/200/404recovery, transport timeout, malformed responses, and workspace-versus-standalone reattachment. Run the SDK and repository builds and confirm the browser bundle remains free of Node built-ins and below the 215 KiB budget. The expected result is that every standalone method probesstandalone_sessions_v1, sends nocwdorworkspaceCwd, validates its response, and never retries create automatically.Evidence (Before & After)
N/A — SDK API, types, and tests only; no user-visible or TUI change.
Tested on
Environment (optional)
macOS, Node.js v26.0.0, local npm workspace install. The repository supports Node.js 22 and later.
Risk & Scope
Linked Issues
Part of #8908. Builds on #10179.
中文说明
本 PR 做了什么
本 PR 为
standalone_sessions_v1daemon API 增加 TypeScript SDK 接口。它提供经过 capability 校验的完整生命周期方法,包括创建、列表、精确查询、加载、恢复、目录修复、重命名、导出、归档、取消归档和删除;暴露精简的 standalone 响应与恢复类型;在返回每个新增 JSON 响应前进行运行时校验;并让 session 重新连接始终使用明确的 standalone 或 workspace 恢复策略。当调用方未提供 UUID 时,创建方法会在发出请求前生成 UUID。结构化的 outcome-unknown 响应、传输失败、超时或格式错误的成功响应只会触发一次使用该 UUID 的精确查询,并向调用方返回恢复上下文,不会重试创建。
本 PR 基于已由 #10179 合并的 standalone daemon API,现已直接以
main为目标分支。为什么需要
PR #10179 通过 REST 暴露了 standalone 生命周期,但如果没有本 PR,SDK 使用方仍需自行拼接私有路由、重复实现响应校验,并可能在创建结果未知时错误重试。本改动为浏览器和 Node 使用方提供一个 fail-closed API,调用方无法传入 workspace selector,也不会回退到 primary workspace。
Reviewer 测试计划
如何验证
运行 TypeScript SDK 测试,确认 standalone 请求形状测试覆盖每个生命周期路由、capability 缺失、调用方提供和 SDK 生成 UUID、精确
202/200/404恢复、传输超时、格式错误响应,以及 workspace 与 standalone 的不同重新连接路径。运行 SDK 和仓库构建,确认浏览器 bundle 不包含 Node 内置模块且低于 215 KiB 预算。预期结果是每个 standalone 方法都会检查standalone_sessions_v1,不发送cwd或workspaceCwd,校验响应,并且绝不会自动重试创建。证据(Before & After)
N/A——仅包含 SDK API、类型与测试,没有用户可见或 TUI 变化。
已测试平台
环境(可选)
macOS、Node.js v26.0.0、本地 npm workspace 安装。仓库支持 Node.js 22 及以上版本。
风险与范围
关联 Issue
#8908 的一部分。基于已合并的 #10179。