Skip to content

feat(acp): 实现协议级请求取消 $/cancel_request 与 -32800 Cancelled 错误码 #148

Description

@YoungSx

结论

协议级请求取消 $/cancel_request 与配套错误码 -32800 (Cancelled) 完全未实现。我们只有整轮取消 session/cancel。后果不对称:收不到无妨(规范允许忽略),但我们自己发出去的请求也没法取消

证据链

1. 规范:这是 Protocol Level 的独立机制,与 session/cancel 不同层

v1 schema ## Protocol Level/tmp/acp-v1-schema.md:1639)与 ### $/cancel_request:1651):

Notifications whose methods start with '$/' are messages which are protocol implementation dependent and might not be implementable in all clients or agents. ... If an agent or client receives notifications starting with '$/' it is free to ignore the notification.

$/cancel_request

Cancels an ongoing request.
This is a notification sent by the side that sent a request to cancel that request.
Upon receiving this notification, the receiver:

  1. MAY cancel the corresponding request activity and all nested activities
  2. MAY send any pending notifications.
  3. MUST send one of these responses for the original request:
    • Valid response with appropriate data (partial results or cancellation marker)
    • Error response with code -32800 (Cancelled)

CancelRequestNotification 只有一个必填字段 requestId: RequestId

同一机制在 v2 保留(/tmp/acp-v2-schema.md:1110 同名节,属于 Protocol Level 段 :1098)。

2. 我们侧:方法、错误码、收发三处全无

$ grep -rn '32800' src/ | wc -l
0
$ grep -rn '\$/cancel\|cancel_request\|CancelRequest' src/SalmonEgg.Acp/ | wc -l
0

src/SalmonEgg.Acp/JsonRpc/JsonRpcErrorCode.cs 完整枚举了标准码(-32700/-32600/-32601/-32602/-32603)与 ACP 扩展码(-32000 AuthenticationRequired ~ -32005 CapabilityNotSupported),没有 -32800。而且:

public static bool IsStandardErrorCode(int code)
{
    return code >= -32700 && code <= -32603;
}

public static bool IsAcpErrorCode(int code)
{
    return code >= -32099 && code <= -32000;
}

-32800 落在这两个区间之外,GetErrorMessage(-32800) 会返回 "Unknown error (code: -32800)"。也就是说即便对端按规范回了 -32800,我们也只会把它当无名错误呈现。

3. 我们现有的只是整轮取消,粒度不同

src/SalmonEgg.Acp/Client/AcpClient.cs:690-694 发的是 session/cancel

"session/cancel requires 'sessionId'.");
...
"session/cancel",

它按 sessionId 取消整个 prompt turn,无法取消单个在途请求。入站侧 HandleNotificationAcpClient.cs:1143-1154)只有一个 case:

switch (notification.Method)
{
    case "session/update":
        HandleSessionUpdate(notification);
        break;
    default:
        // Unknown notification type.
        break;
}

$/cancel_request 会静默落入 default——这一半符合规范(明文允许忽略 $/ 通知)。

4. 真正的缺陷在出站侧

我们发给 agent 的请求(session/prompt 之外的 session/listsession/loadterminal/* 等)一旦 CancellationToken 被触发,按规范应当发 $/cancel_request 通知对端;现在没有这条路,只能本地放弃等待,对端继续跑到底。这会浪费对端算力,并可能让副作用(文件写入、命令执行)在用户已取消后仍然发生。

影响

  • 用户取消操作后,agent 侧仍在执行;有副作用的请求(如 terminal/create 后续链路)无法及时止住。
  • 对端按规范回 -32800 时我们呈现为 "Unknown error (code: -32800)",不可读、也无法据此区分「被取消」与「真失败」。按 AGENTS docs(config): align migration spec with additive-only reality #99 的口径,被取消不是故障,不应落在会保持到下次成功操作的故障面上。

建议范围

  1. JsonRpcErrorCode 增补 Cancelled = -32800,并修正 IsStandardErrorCode / IsAcpErrorCode 的区间判定或新增单独判定(注意 -32800 属 JSON-RPC 保留区但不在现有两段内,别硬塞进现有区间破坏语义);GetErrorMessage 补映射。
  2. 出站:AcpClient 的请求发送路径在 CancellationToken 触发时发 $/cancel_request(携带原 requestId),随后仍需等待/清理对端的终态响应(规范要求对端 MUST 回一个响应,我们的 pending 表要能收得下 -32800)。
  3. 入站(可选,规范允许忽略):若要支持,需能取消我们正在处理的 client 侧请求(fs/*terminal/*session/request_permission),并按规范回 -32800。现有 TrackPendingInboundRequest / RemovePendingInboundTracking 已有 pending 表可复用。
  4. 呈现层:-32800 归类为「已取消」,不进故障面。

验证要求

  • 出站取消:断言线上真的发出了 $/cancel_requestrequestId 与原请求一致(断言报文,不只断言本地状态)。
  • 对端回 -32800 时,不在 UI 形成滞留故障提示;GetErrorMessage(-32800) 不再返回 Unknown。
  • 每一种在用传输各跑一遍(stdio / WebSocket,含经桥中转那条)——按 AGENTS docs(config): align migration spec with additive-only reality #99 的教训,共享层与传输层的判据必须分清,否则半个修复会被另一半掩盖。
  • 反向验证:拆掉发送逻辑后报文断言必须转红。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions