
DeepSeek Harness Web 停止操作语义演进session.cancel如何保留待处理 Queue【免费下载链接】deepseek-harnessDeepSeek Harness: Everything is a Plugin.项目地址: https://gitcode.com/gh_mirrors/de/deepseek-harness导读本文以 DeepSeek Harness 仓库中已实施的 Agent Note2026-07-31-web-stop-preserves-queue.zh.md为主线剖析 Web 停止按钮从广义取消演变为保留待处理 Queue 的协作式取消这一决策的完整过程。你将理解session.cancel与agent.cancel的调用链、keepInbox选项的底层语义、AgentLoop 在取消停稳后的 FIFO 交接机制以及该改动如何在不影响 ACP、TUI 等其他客户端的前提下仅调整 Web Host 端点。问题Web 停止按钮的语义混淆在 DeepSeek Harness 中Web 客户端的停止按钮原本直接调用session.cancel而该端点此前映射到广义的agent.cancel({ kind: user })。这里存在一个关键的语义错位在活动轮次active turn期间普通 composer 提交的内容已经被接纳为可独立寻址的 Queue 入队项Queue occurrence即用户意图在队列中拥有独立身份当用户只想停止当前这一轮生成时广义取消却会把所有已入队的待处理项一并丢弃这实质上是将轮次中断turn interruption与Queue 的显式删除操作混为一谈。更致命的是浏览器无法通过重发可见行来修复这一损失浏览器并不拥有这些行的实时InboxItemId、唤醒策略wake policy或认领竞态claim race如果贸然重发还可能重复执行 Host 已经认领的工作造成语义重复与竞态。决策让session.cancel成为保留式停止针对上述问题仓库的决策是将session.cancel重新定义为Web Host API 面向普通会话的活动轮次停止操作其行为分两种情况对由会话支撑的 subagent以agent-busy拒绝对普通会话调用agent.cancel({ kind: user }, { keepInbox: true })——在协作式中止当前轮次的同时保留待处理的 inbox 工作。该映射在 packages/api/session-controller/src/commands.ts 中有直接实现/** * param request - Session whose active Agent turn is cancelled. * returns acknowledgement that cancellation was requested. */ cancel(request: SessionCancelRequest): SessionCancelValue { // ... agent.cancel({ kind: user }, { keepInbox: true }) // ... }同文件中subagent 场景的agent-busy拒绝commands.ts#L331也印证了会话支撑的 subagent 不接受这种停止的策略reject(agent-busy, prompt rejected, { reason: String(error) })值得强调的是底层的keepInbox选项同时保留 queued 与 steering 两类入队项而 Web 的 Queue 投影projection继续只暴露 queued 入队项——steering 虽然被保留但不会在 Web QueueDock 中渲染这为后续语义收敛留出了空间。底层原理keepInbox在 Agent 层如何生效keepInbox是Agent.cancel的选项之一定义在 packages/core/agent/src/runtime-types.ts/** Options for {link Agent.cancel}. */ export interface CancelOptions { /** * Preserve queued and steering inbox items instead of discarding them. The * active turn is still aborted, but un-started and pending work survives for a * later turn and no canceled inbox splice is logged. */ keepInbox?: boolean | undefined }而ReactLoopAgent默认 Agent 驱动器在 packages/core/agent-loop/src/agent.ts 中实现了取消逻辑cancel(cause: AgentCancelCause, options: CancelOptions {}): void { if (!options.keepInbox) { this.inbox.clear() if (this.phase.kind ! idle) this.phase.wakeRequested false } if (this.phase.kind ! idle) this.phase.abort.abort(cause) }这段代码清晰地展示了两种取消路径的分野不带keepInbox广义取消先inbox.clear()清空所有待处理工作再中止活动轮次同时把wakeRequested置回false即取消后不会被唤醒带keepInbox保留式取消跳过清空直接以cause中止活动轮次——活动轮次照样被中止但未启动与待处理的工作保留下来供后续轮次继续消费且不会记录被取消的 inbox splice。Agent.cancel的 JSDocruntime-types.ts#L84-L91进一步明确了约定清除 queued 与 steering 工作——除非传入keepInbox——并中止活动轮次或轮次间任务。第一个 cause 对该活动生效若无活动取消为 no-op且不会武装后续工作。交接机制AgentLoop 如何推进保留的 Queue保留 Queue 只是第一步关键还在于取消停稳后如何推进下一个入队项。仓库的决策是AgentLoop 不会启动并发的替代轮次而是遵循一条严格的交接时序关闭并 flush 被中断的轮次协作式取消会如实等待活动工作结算quiescence绝不提前开新轮次通过现有 FIFO 驱动器认领下一个可唤醒的 queued 入队项认领会发出agent/inbox/dequeue事件使 Host 的权威session/queue快照退役已认领行同时让剩余队尾保持可见浏览器既不重发、也不提升任何行——认领完全由 Host 侧驱动。值得注意的是从 agent.ts 的wakeDriver实现可以看出唤醒请求wake在中止到空闲的窗口内会被 latch挂起待取消收敛converge to idle后再回放// Maintenance and aborted drivers cannot deliver the wake: latch it for // replay at convergence. Live drivers claim queued work themselves; // disposal never latches, so teardown waits on no model turn. const reason this.phase.abort.signal.reason as AgentCancelCause | undefined if (reason?.kind ! disposed (this.phase.kind maintenance || wakeAfterAbort)) { this.phase.wakeRequested true }这保证了取消中提交的唤醒输入不会丢失会在下个空闲期被唤醒驱动器消费。一个可预期的延迟是忽略取消uncooperative的活动工作会推迟这一交接直到该工作真正结算——这是协作式取消换来的语义准确性。影响范围只改 Web 客户端的端点该映射的收敛性设计体现在改动面最小层策略Web Hostsession.cancel端点使用keepInbox: true保留式取消本次改动Agent.cancel()默认约定仍是广义取消行为不变ACP 客户端保留既有取消策略TUI 客户端保留既有取消策略AgentHandle.dispose()拆卸期间仍会清除待处理工作移除 Queue 行仍是丢弃单个待处理入队项的显式 Web 操作也就是说本次改动没有为广义取消与保留式取消增加额外的 wire 协议选项而是直接改变了 Web 停止按钮的策略想要丢弃单个待处理项用户仍使用逐行删除per-row delete控件。考虑过的替代方案仓库文档明确记录了四个候选方案及其否决理由理解这些权衡有助于把握该决策的边界停止按钮继续使用广义取消——否决停止一次生成不应销毁已独立排队的用户意图且 Queue 已拥有显式删除操作取消后由浏览器重发下一行——否决Host 拥有入队项标识与认领顺序客户端重新提交可能重复工作、重排 FIFO或与权威出队产生竞态被取消工作达到完全停稳之前启动下一轮次——否决两个轮次会并发修改同一会话日志并共享 Agent 拥有的资源协作式取消应如实等待活动工作结算为广义取消与保留式取消添加协议选项——否决在 Web 产品提供独立的停止并清空 Queue交互之前此选项没有必要现有停止按钮只需一项策略逐行删除已提供丢弃控件。验证AgentLoop 测试与 Web 端到端场景该改动拥有两层验证见 packages/core/agent-loop/tests/cancel.spec.tsAgentLoop 覆盖测试保持一个活动模型流将两个可唤醒轮次排队使用keepInbox取消并固定断言以下不变量先中止、后完成的轮次原因aborted-then-completed turn reasonsFIFO 用户消息顺序不存在 discard 事件证明入队项未被丢弃最终达到空闲idle状态。测试还覆盖了若干边界情况例如keepInbox不会恢复已被唤醒 send 认领的工作keepInbox在活动轮次中止后**停放park**排队工作keepInbox会 latch 落在中止到空闲窗口内的唤醒 send不带keepInbox的取消会连同 latched wake 一起清空 inbox。无密钥 Web 场景通过 HTTP/SSE 驱动已组装的组合built composition停止一个卡住的轮次观察队尾保持可见时下一个 queued 入队项开始执行再停止该轮次观察最后一个 queued 入队项完成。其**可访问性快照accessibility snapshot**固定了中间态的 Queue 保留状态防止该行为在未来回归。后果与后续展望实施后的行为收益明确Web 停止会保留已接纳的排队意图并在取消如实结算后自动推进用户无需重新输入Queue 行在不配合取消的活动工作收尾期间可能保持可见——这是协作式取消的真实代价由同一 inbox 选项保留的外部 steering可以进入下一个已接纳轮次尽管 Web 不会在 QueueDock 中渲染 steering未来的批量清空交互需要显式的产品操作如停止并清空 Queue按钮而不是继续过载停止按钮。这套设计体现了一个可复用的模式当停止与删除语义需要分离时优先在 Host 端点层收敛策略、保留协议层的默认约定并通过 FIFO 认领 权威快照让客户端保持被动从而在最小改动面内获得无竞态、可验证的行为改进。【免费下载链接】deepseek-harnessDeepSeek Harness: Everything is a Plugin.项目地址: https://gitcode.com/gh_mirrors/de/deepseek-harness创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考