39 lines
3.1 KiB
Markdown
39 lines
3.1 KiB
Markdown
# RFC: 让 JSON-RPC 完成结果与传输方向单一化
|
||
|
||
Status: proposed
|
||
|
||
[English](2026-07-19-make-jsonrpc-directional.md) | 中文
|
||
|
||
## 问题
|
||
|
||
JSON-RPC 桥接层把两个端点都建模为对称的对等端,但实际协议具有固定方向。TypeScript 服务端接收请求并发出响应或通知,其传输层却还实现了未使用的出站请求和入站通知分发。Python SDK 发送请求并接收响应或通知,却还会把未使用的服务端入站请求放入队列,并公开响应辅助方法。
|
||
|
||
`session/prompt` 还会用两种协议结构报告同一个已结束轮次。服务端先发出 `session.finished`,再返回常量 `{ accepted: true }`;Python SDK 丢弃该响应,转而等待通知以取得状态。响应只有在处理函数返回后才会写入,因此在同一条有序流上,通知必然先于这个常量响应。
|
||
|
||
这些未使用的双向能力引入了待处理请求表、生成 ID、请求队列、关闭时的拒绝路径、响应辅助方法和第二套完成等待逻辑,却没有任何生产调用方使用。
|
||
|
||
## 提案
|
||
|
||
按实际角色收窄两个端点。TypeScript 传输层只保留入站请求、出站响应和出站通知。Python 客户端只保留出站请求以及入站响应或通知。删除两侧与实际方向相反的请求机制。
|
||
|
||
在 `agent.whenIdle()` 完成后,由 `session/prompt` 直接返回 `{ status, reason }` 作为轮次结果。删除 `session.finished`、常量接纳响应以及 Python 中响应后的完成等待循环。`session.event` 与 subagent 通知仍在响应前流式发出,持久会话事件仍是最终响应重建的真源。
|
||
|
||
## 备选方案
|
||
|
||
**为未来方法保留通用的对称 JSON-RPC 对等端。** 服务端发起的请求将来可能用于交互式权限,但当前没有类型化方法或生产消费方。该功能完成设计后,预发布协议可以增加所需的最小方向,无需提前保留未使用的对等端能力。
|
||
|
||
**为流式客户端保留 `session.finished`。** 轮次结束不是增量数据:请求响应已经标识同一个边界,并且在有序流中位于先前所有通知之后。第二条终止通知会产生两种结果表示,迫使客户端进行协调。
|
||
|
||
## 验收标准
|
||
|
||
- TypeScript 端点无法发起请求,也不消费通知。
|
||
- Python 端点无法发起通知,也不消费服务端请求。
|
||
- 轮次结束后,`session/prompt` 返回权威的 `ok`、`error` 或 `aborted` 状态及其原因。
|
||
- 轮次中发出的会话事件与 subagent 生命周期通知都先于响应到达。
|
||
- 同一会话的重叠拒绝、分帧、多字节输入、处理器错误、flush、关闭顺序与最终响应重建保持原有行为。
|
||
- TypeScript 桥接测试、Python SDK 测试、构建后 JSON-RPC 覆盖、快照和生成的 API 文档全部通过。
|
||
|
||
## 风险
|
||
|
||
本提案会刻意收窄预发布协议格式。仅监听 `session.finished` 的原始客户端,以及使用未使用对称传输方法的嵌入方,都必须改为读取请求响应。未来若需要服务端发起请求,应新增类型化协议,而不是复用休眠的通用机制。
|