@roll-agent/relay-protocol 0.1.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/README.md +134 -39
  2. package/dist/conformance.d.ts +571 -4
  3. package/dist/conformance.js +677 -8
  4. package/dist/control.d.ts +188 -0
  5. package/dist/control.js +180 -0
  6. package/dist/index.d.ts +3991 -287
  7. package/dist/index.js +676 -77
  8. package/dist/reference-adapter.d.ts +56 -0
  9. package/dist/reference-adapter.js +122 -0
  10. package/dist/schema/roll-relay-browser-session-v1.schema.json +23 -0
  11. package/dist/schema/roll-relay-control-v1.schema.json +127 -0
  12. package/dist/schema/roll-relay-protocol-v1.1.schema.json +3791 -0
  13. package/dist/schema/roll-relay-protocol-v1.schema.json +1 -1
  14. package/fixtures/control/v1.0/invalid-browser-session-trailing-whitespace.json +4 -0
  15. package/fixtures/control/v1.0/invalid-browser-session-uppercase-scheme.json +4 -0
  16. package/fixtures/control/v1.0/invalid-browser-session-url.json +4 -0
  17. package/fixtures/control/v1.0/invalid-browser-session-ws.json +4 -0
  18. package/fixtures/control/v1.0/invalid-control-extra-field.json +6 -0
  19. package/fixtures/control/v1.0/invalid-session-ready-wire-version.json +8 -0
  20. package/fixtures/control/v1.0/manifest.json +52 -0
  21. package/fixtures/control/v1.0/valid-browser-session.json +4 -0
  22. package/fixtures/control/v1.0/valid-session-error.json +5 -0
  23. package/fixtures/control/v1.0/valid-session-ready.json +8 -0
  24. package/fixtures/control/v1.0/valid-workspace-status.json +5 -0
  25. package/fixtures/v1.1/invalid-approval-projection-raw-input-leak.json +19 -0
  26. package/fixtures/v1.1/invalid-authentication-local-only.json +12 -0
  27. package/fixtures/v1.1/invalid-file-picker-local-only.json +12 -0
  28. package/fixtures/v1.1/invalid-interaction-cancelled-reason-leak.json +10 -0
  29. package/fixtures/v1.1/invalid-interaction-resolved-result-leak.json +18 -0
  30. package/fixtures/v1.1/invalid-legacy-approval-candidate.json +7 -0
  31. package/fixtures/v1.1/invalid-legacy-approval-respond.json +7 -0
  32. package/fixtures/v1.1/invalid-n-minus-one-device-connect.json +6 -0
  33. package/fixtures/v1.1/invalid-non-normal-sensitivity.json +21 -0
  34. package/fixtures/v1.1/invalid-runtime-event-tool-input-leak.json +22 -0
  35. package/fixtures/v1.1/invalid-runtime-event-tool-output-leak.json +21 -0
  36. package/fixtures/v1.1/invalid-user-input-projection-secret-leak.json +22 -0
  37. package/fixtures/v1.1/manifest.json +673 -0
  38. package/fixtures/v1.1/valid-device-connect.json +6 -0
  39. package/fixtures/v1.1/valid-interaction-cancelled.json +9 -0
  40. package/fixtures/v1.1/valid-interaction-candidate-user-input.json +25 -0
  41. package/fixtures/v1.1/valid-interaction-request-approval.json +17 -0
  42. package/fixtures/v1.1/valid-interaction-request-user-input.json +40 -0
  43. package/fixtures/v1.1/valid-interaction-resolved.json +9 -0
  44. package/fixtures/v1.1/valid-runtime-ack.json +5 -0
  45. package/fixtures/v1.1/valid-runtime-encrypted-interaction.json +10 -0
  46. package/fixtures/v1.1/valid-runtime-event-runtime-n-minus-one.json +16 -0
  47. package/fixtures/v1.1/valid-runtime-event.json +16 -0
  48. package/fixtures/v1.1/valid-runtime-gap.json +7 -0
  49. package/fixtures/v1.1/valid-runtime-request.json +10 -0
  50. package/fixtures/v1.1/valid-runtime-response.json +8 -0
  51. package/package.json +16 -3
package/README.md CHANGED
@@ -9,7 +9,8 @@ Browser-safe 的 Roll Companion Relay Wire 契约。
9
9
 
10
10
  | 使用方 | 是否直接安装 | 用途 |
11
11
  |---|---:|---|
12
- | Browser Web App | 是 | 构造和校验 Relay frame |
12
+ | 普通 Browser Web App | 否 | 安装 `@roll-agent/relay-client`,不直接处理 frame |
13
+ | 自定义 Browser Transport | 是 | 实现 Relay frame、ACK/gap 与恢复 |
13
14
  | Cloud Relay Server | 是 | 校验、路由和持久化 Relay frame |
14
15
  | Local Companion Host | 是 | 与 Cloud 使用同一 Wire 契约 |
15
16
  | Local-only Desktop GUI | 否 | 直接使用 Runtime Protocol,不经过 Relay |
@@ -19,54 +20,148 @@ Browser-safe 的 Roll Companion Relay Wire 契约。
19
20
  pnpm add @roll-agent/relay-protocol
20
21
  ```
21
22
 
22
- 本包提供:
23
+ 普通第三方 Web App 应安装 `@roll-agent/relay-client`;本包面向 Cloud Relay、Companion 和确实
24
+ 需要自定义 Transport 的高级实现者。
23
25
 
24
- - 显式冻结的 Relay Wire version、message/method registry;
25
- - `DeviceId`、`WorkspaceId`、Relay `requestId` / `envelopeId` Schema;
26
- - `device.connect`、request/response/event/ack/gap/encrypted frame Schema;
27
- - method-specific Params/Result parser;
28
- - 以 `(workspaceId, requestId)` 为幂等键的 `new/replay/conflict` 分类;
29
- - 稳定 Relay error code 与 retryability 映射;
30
- - JSON Schema、跨语言 fixtures 和可复用 conformance cases。
26
+ ## Control 1.0 与方向合同
27
+
28
+ Browser Session 的 HTTP 返回和 WebSocket 控制面从独立 subpath 导入,不属于
29
+ `relayMessageSchemaV11` 数据面 union:
31
30
 
32
31
  ```ts
33
32
  import {
34
- RELAY_PROTOCOL_VERSION,
35
- relayMessageSchema,
36
- workspaceIdSchema,
37
- } from "@roll-agent/relay-protocol";
33
+ RELAY_BROWSER_WSS_MESSAGE_TYPES_BY_DIRECTION,
34
+ RELAY_COMPANION_WSS_MESSAGE_TYPES_BY_DIRECTION,
35
+ parseRelayBrowserFirstControlFrame,
36
+ relayBrowserControlMessageSchema,
37
+ relaySessionDescriptorSchema,
38
+ } from "@roll-agent/relay-protocol/control";
39
+
40
+ const session = relaySessionDescriptorSchema.parse(await response.json());
41
+ const ready = parseRelayBrowserFirstControlFrame(firstWebSocketFrame);
42
+ relayBrowserControlMessageSchema.parse(laterControlFrame);
43
+ ```
44
+
45
+ `session.ready` 必须是 Browser WebSocket 收到的第一帧,并固定声明 Control 1.0、Wire 1.1、
46
+ Relay 绑定的 Workspace 和在线状态。Browser 不能在请求中自行指定 `workspaceId`。
47
+ Ticket 无效、过期、重复消费或 Origin 不匹配时,Relay 必须在 HTTP upgrade 阶段拒绝连接;
48
+ 这些错误属于 `RELAY_BROWSER_HANDSHAKE_ERROR_CODES`,不能伪装成已认证连接中的
49
+ `session.error`。后者只承载 `session.ready` 之后的会话错误。
50
+
51
+ 方向 allowlist 固定为:Browser→Relay 只允许 Wire 1.1 `runtime.request` 与 `runtime.ack`;
52
+ Relay→Companion 同样只允许这两类。Relay→Browser 允许 Control 帧以及 response/event/gap/
53
+ Interaction 帧;Companion→Relay 还包含首帧 `device.connect`。`runtime.ack` 是 Wire 数据面,
54
+ 不是 Control ACK。P0 不提供 E2EE,因此这些 P0 WSS allowlist 明确不含 `runtime.encrypted`。
55
+
56
+ ## 版本
57
+
58
+ 支持矩阵是 `["1.1", "1.0"]`。Wire 1.1 新增 typed Interaction;Wire 1.0 的 registry、
59
+ Schema、fixtures 和 Approval fallback 保持冻结。
60
+
61
+ 为了让现有 Companion 和 Browser 不被 minor upgrade 静默升级,历史上没有版本后缀的
62
+ `RELAY_PROTOCOL_VERSION`、`relayMessageSchema`、`relayRequestMethodSchemas`、parser 和 type
63
+ 仍固定指向 Wire 1.0。新代码应使用 `LATEST_RELAY_PROTOCOL_VERSION` 和显式的 `*V10` /
64
+ `*V11` / `*ForVersion` API。
65
+
66
+ ```ts
38
67
  import {
39
- runRelayProtocolConformance,
40
- runtimeRelayProtocolConformanceAdapter,
41
- } from "@roll-agent/relay-protocol/conformance";
68
+ LATEST_RELAY_PROTOCOL_VERSION,
69
+ parseRelayMessageForVersion,
70
+ relayMessageSchemaV11,
71
+ } from "@roll-agent/relay-protocol";
72
+
73
+ LATEST_RELAY_PROTOCOL_VERSION; // "1.1"
74
+ const frame = parseRelayMessageForVersion("1.1", input);
75
+ relayMessageSchemaV11.parse(frame);
42
76
  ```
43
77
 
44
- `@roll-agent/relay-protocol/schema` 导出 JSON Schema Draft 2020-12,
45
- `@roll-agent/relay-protocol/fixtures/v1/*` 导出 golden fixtures。
78
+ `CompanionRelayBridge.connect(transport)` 这一历史一参入口仍只表示 Wire 1.0。支持 Wire 1.1
79
+ 的 Host 必须使用显式协商版本的新入口;不得让旧调用自动选择 latest。
46
80
 
47
- `runRelayProtocolConformance()` 同时检查 frame、version 选择、完整 method registry 及其
48
- `query` / `mutation` / `local-only` disposition、duplicate/conflict 与错误码形状、基于调用方
49
- 已证明连续投递前缀的 ACK 边界、gap recovery、加密 metadata 和 Relay error retryability。
50
- Transport 必须自行保证发送失败后不会越过序号缺口;Companion Bridge 会终止失败的
51
- transport generation 并在重连后重放。当前只有 `"1.0"`,因此只能验证同版本与未知版本
52
- fail-closed;真实 `N/N-1` 矩阵必须等下一版 Relay Wire 存在后补齐,不能伪造历史版本。
81
+ ## Wire 1.1 Interaction
53
82
 
54
- ## 边界
83
+ Wire 1.1 增加 `interaction.request`、`interaction.resolved`、
84
+ `interaction.cancelled` 三种 Companion→Browser frame。Browser 通过 mutation
85
+ `interaction.candidate` 提交候选;`approval.candidate` 只存在于冻结的 Wire 1.0。
86
+
87
+ 远端候选不是独立授权事实源。Runtime policy 先决定 auto/confirm/deny;只有 confirm 才产生
88
+ 可响应 Interaction,deny 不会被远端越过。官方 Companion 只再验证 request policy、Workspace、
89
+ responder 与绝对 deadline,不增加电脑端二次审批。低层自定义 Host 可以进一步收紧,但不能
90
+ 放宽 Runtime 决议。
91
+
92
+ 安全投影只允许:
55
93
 
56
- 本包不包含 Transport、WebSocket、账号/设备数据库、本地 Policy、加密实现或 Cloud
57
- 部署代码。运行时代码只依赖 Browser-safe 的 `@roll-agent/protocol` 与 `zod`。
94
+ - Approval:`approvalId`、`agentName`、`toolName`、可选 `explanation`;
95
+ - User Input:五类安全表单 control 及其 bounded 字段;
96
+ - resolved/cancelled:Interaction identity,不回显 Runtime Result 或原始取消原因;
97
+ - Timeline:安全消息、状态和 Tool 完成摘要;Tool input/output delta 与 Approval preview 会被剥离。
58
98
 
59
- Browser 与 Cloud Relay 不能为了获得 Wire Schema 而安装 `@roll-agent/companion`。
60
- TypeScript/JavaScript 实现直接使用本包;其他语言使用本包发布的 JSON Schema、fixtures
61
- 与 conformance cases。
99
+ Runtime JSON-RPC `id`、原始 Tool input/output、secret、完整 User Input Result、本地授权信息
100
+ 以及 Authentication/File Picker projector 都不能进入 Companion→Browser 投影。Browser→Companion 的
101
+ `interaction.candidate` 是 User Input Result 唯一允许的入站位置,并且必须关联原始表单重新校验。
102
+
103
+ Wire 1.1 Snapshot 不能重建一个仍可响应的 `interactionId`。Browser Session 重连时,Cloud
104
+ Relay 必须保留并重新投递尚未 resolved/cancelled 的 `interaction.request`;客户端不得从
105
+ `approvalId` 或 Snapshot 自行合成 Interaction identity。
106
+
107
+ Wire 1.1 的 pull 查询遵守同一边界:`thread.open` / `thread.snapshot` 必须把 Approval preview
108
+ 投影为可选 explanation、移除本地 reason,并把 Operation display 与 outcome reason 脱敏;
109
+ Host 对前两种结果调用 `projectRelayThreadSnapshotV11(value)`,对 `operation.get` 调用
110
+ `projectRelayOperationGetResultV11(value)`。两个 projector 遇到畸形 Runtime 结果都会抛错并
111
+ fail closed。第一方 `CompanionRelayBridgeV11` 已自动应用它们;自定义 Host 仍必须在构造
112
+ `runtime.response` 前显式调用,不能把 Runtime 原始结果直接发送。
113
+
114
+ 有意保留的内容包括完整 transcript 消息、Thread 标题/模型/时间元数据、安全 timeline 摘要,
115
+ 以及 `thread.capabilities.manifest` 中可能出现的 cwd、平台、Agent、Skill、Tool Schema、规则
116
+ 标识与 VCS 元数据。它们不是公开信息,Relay 与 Browser 宿主仍需按敏感数据保护。
117
+
118
+ 冻结的 Wire 1.0 没有这些安全投影,只适用于处在等价本地信任边界内的 legacy peer。它不是
119
+ 面向不受信 Cloud/Browser 的降级协议;需要远程投影的 Host 必须协商 1.1,失败时拒绝连接。
120
+
121
+ ## Browser reference adapter
122
+
123
+ `@roll-agent/relay-protocol/reference-adapter` 提供最小、纯内存的 typed reference adapter:
124
+
125
+ ```ts
126
+ import { createRelayBrowserReferenceAdapter } from
127
+ "@roll-agent/relay-protocol/reference-adapter";
128
+
129
+ const adapter = createRelayBrowserReferenceAdapter({ protocolVersion: "1.1" });
130
+ const update = adapter.receive(frame);
131
+ const candidateRequest = adapter.createCandidate({
132
+ workspaceId,
133
+ interactionId,
134
+ method: "approval.request",
135
+ candidate: { decision: "reject", reason: "用户取消" },
136
+ });
137
+ ```
138
+
139
+ Adapter 只做 Schema 校验、pending correlation 和 candidate frame 构造。它不提供账号身份、
140
+ controller 选举、可靠投递、WebSocket、持久 outbox 或 Interaction WAL;这些 responder
141
+ context 必须由宿主注入。
142
+
143
+ ## Schema、fixtures 与 conformance
144
+
145
+ - `@roll-agent/relay-protocol/schema` 与 `/schema/v1.0`:冻结的 Wire 1.0 JSON Schema;
146
+ - `@roll-agent/relay-protocol/schema/v1.1`:Wire 1.1 JSON Schema;
147
+ - `@roll-agent/relay-protocol/control`:Control 1.0、Browser Session 和 WSS 方向 Schema;
148
+ - `@roll-agent/relay-protocol/control/schema`:Control 1.0 JSON Schema;
149
+ - `@roll-agent/relay-protocol/control/session-schema`:Browser Session JSON Schema;
150
+ - `@roll-agent/relay-protocol/control/fixtures/*`:Control/Session golden fixtures;
151
+ - `@roll-agent/relay-protocol/fixtures/v1/*`:字节冻结的 Wire 1.0 golden fixtures;
152
+ - `@roll-agent/relay-protocol/fixtures/v1.1/*`:Wire 1.1 Interaction 与安全负例;
153
+ - `@roll-agent/relay-protocol/conformance`:可复用的 N/N-1 suite。
154
+
155
+ 历史 `runRelayProtocolConformance(adapter)` 一参调用固定执行 Wire 1.0 suite;新实现使用
156
+ `runRelayProtocolConformanceForVersion(version, adapter)` 显式选择 1.1 或 1.0。Suite 覆盖
157
+ 版本协商、完整 method registry、duplicate/conflict、ACK/gap、Interaction 生命周期、加密
158
+ metadata 和安全 sentinel。
159
+
160
+ ## 边界
62
161
 
63
- 当前只冻结 Relay Wire `"1.0"`。其中 `approval.candidate` 是现有 Approval 专属方法;
64
- 通用 typed interaction 与逻辑 `interactionId` 必须在后续 Relay Wire version 中定义,
65
- 不能静默扩张 `"1.0"`。
162
+ 本包不包含 Transport、WebSocket、账号/设备数据库、本地 Policy、加密实现或 Cloud 部署
163
+ 代码。运行时代码只依赖 Browser-safe 的 `@roll-agent/protocol` 与 `zod`。Browser 与 Cloud
164
+ Relay 不能为了获得 Wire Schema 而安装 `@roll-agent/companion`。
66
165
 
67
- Relay version 冻结外层 envelope、message type 与 recognized method registry。
68
- `local-only` 方法(当前为 `initialize`)只能由 Companion 在本地处理,不得转发给 Runtime;
69
- `query` / `mutation` 才是远程请求分类。既有 Runtime method 的 Params/Result 继续属于按
70
- Workspace 协商的 Runtime Protocol 契约;`relayRequestMethodSchemas` 是当前
71
- `@roll-agent/protocol` 依赖版本的 typed 视图,不应被解释为 Relay `"1.0"` 单独复制的一套
72
- Runtime Schema。
166
+ Relay `requestId`、逻辑 `interactionId`、Runtime JSON-RPC `id`、Runtime mutation
167
+ `requestId` 与 Relay `relaySequence` 是不同的类型和生命周期,不能互相复用。