@roll-agent/relay-protocol 0.0.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.
- package/README.md +72 -0
- package/dist/conformance.d.ts +329 -0
- package/dist/conformance.js +429 -0
- package/dist/index.d.ts +1050 -0
- package/dist/index.js +343 -0
- package/dist/schema/roll-relay-protocol-v1.schema.json +2914 -0
- package/fixtures/v1/invalid-encrypted-metadata-leak.json +13 -0
- package/fixtures/v1/invalid-extra-field.json +6 -0
- package/fixtures/v1/invalid-gap-recovery.json +7 -0
- package/fixtures/v1/invalid-request-id.json +7 -0
- package/fixtures/v1/invalid-unknown-message.json +4 -0
- package/fixtures/v1/invalid-unknown-method.json +7 -0
- package/fixtures/v1/invalid-unknown-version.json +6 -0
- package/fixtures/v1/manifest.json +458 -0
- package/fixtures/v1/valid-device-connect.json +6 -0
- package/fixtures/v1/valid-runtime-ack.json +5 -0
- package/fixtures/v1/valid-runtime-encrypted.json +10 -0
- package/fixtures/v1/valid-runtime-event.json +16 -0
- package/fixtures/v1/valid-runtime-gap.json +7 -0
- package/fixtures/v1/valid-runtime-request.json +10 -0
- package/fixtures/v1/valid-runtime-response.json +8 -0
- package/package.json +51 -0
package/README.md
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# `@roll-agent/relay-protocol`
|
|
2
|
+
|
|
3
|
+
Browser-safe 的 Roll Companion Relay Wire 契约。
|
|
4
|
+
|
|
5
|
+
它不是 Cloud 服务、Browser SDK 或 Companion 进程;安装或导入本包不会建立连接、打开端口
|
|
6
|
+
或启动后台任务。
|
|
7
|
+
|
|
8
|
+
## 谁安装
|
|
9
|
+
|
|
10
|
+
| 使用方 | 是否直接安装 | 用途 |
|
|
11
|
+
|---|---:|---|
|
|
12
|
+
| Browser Web App | 是 | 构造和校验 Relay frame |
|
|
13
|
+
| Cloud Relay Server | 是 | 校验、路由和持久化 Relay frame |
|
|
14
|
+
| Local Companion Host | 是 | 与 Cloud 使用同一 Wire 契约 |
|
|
15
|
+
| Local-only Desktop GUI | 否 | 直接使用 Runtime Protocol,不经过 Relay |
|
|
16
|
+
| Runtime / `roll chat` | 否 | 使用 `@roll-agent/protocol` 或进程内调用 |
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pnpm add @roll-agent/relay-protocol
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
本包提供:
|
|
23
|
+
|
|
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。
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
import {
|
|
34
|
+
RELAY_PROTOCOL_VERSION,
|
|
35
|
+
relayMessageSchema,
|
|
36
|
+
workspaceIdSchema,
|
|
37
|
+
} from "@roll-agent/relay-protocol";
|
|
38
|
+
import {
|
|
39
|
+
runRelayProtocolConformance,
|
|
40
|
+
runtimeRelayProtocolConformanceAdapter,
|
|
41
|
+
} from "@roll-agent/relay-protocol/conformance";
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
`@roll-agent/relay-protocol/schema` 导出 JSON Schema Draft 2020-12,
|
|
45
|
+
`@roll-agent/relay-protocol/fixtures/v1/*` 导出 golden fixtures。
|
|
46
|
+
|
|
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 存在后补齐,不能伪造历史版本。
|
|
53
|
+
|
|
54
|
+
## 边界
|
|
55
|
+
|
|
56
|
+
本包不包含 Transport、WebSocket、账号/设备数据库、本地 Policy、加密实现或 Cloud
|
|
57
|
+
部署代码。运行时代码只依赖 Browser-safe 的 `@roll-agent/protocol` 与 `zod`。
|
|
58
|
+
|
|
59
|
+
Browser 与 Cloud Relay 不能为了获得 Wire Schema 而安装 `@roll-agent/companion`。
|
|
60
|
+
TypeScript/JavaScript 实现直接使用本包;其他语言使用本包发布的 JSON Schema、fixtures
|
|
61
|
+
与 conformance cases。
|
|
62
|
+
|
|
63
|
+
当前只冻结 Relay Wire `"1.0"`。其中 `approval.candidate` 是现有 Approval 专属方法;
|
|
64
|
+
通用 typed interaction 与逻辑 `interactionId` 必须在后续 Relay Wire version 中定义,
|
|
65
|
+
不能静默扩张 `"1.0"`。
|
|
66
|
+
|
|
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。
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
import { RELAY_PROTOCOL_VERSION, type RelayAckDisposition, type RelayAckState, type RelayErrorCode, type RelayProtocolVersion, type RelayRequestMethod, type RelayRequestMethodDisposition, type RelayRequestReplayClassification, type RelayRuntimeRequest } from "./index.ts";
|
|
2
|
+
export interface RelayFrameConformanceCase {
|
|
3
|
+
readonly id: string;
|
|
4
|
+
readonly fixtureName: `${"valid" | "invalid"}-${string}.json`;
|
|
5
|
+
readonly valid: boolean;
|
|
6
|
+
readonly frame: unknown;
|
|
7
|
+
}
|
|
8
|
+
export declare const RELAY_FRAME_CONFORMANCE_CASES: readonly [{
|
|
9
|
+
readonly id: "device-connect";
|
|
10
|
+
readonly fixtureName: "valid-device-connect.json";
|
|
11
|
+
readonly valid: true;
|
|
12
|
+
readonly frame: {
|
|
13
|
+
readonly type: "device.connect";
|
|
14
|
+
readonly protocolVersion: "1.0";
|
|
15
|
+
readonly deviceId: "00000000-0000-4000-8000-000000000506";
|
|
16
|
+
readonly pairingToken: "pairing-token-with-sufficient-length";
|
|
17
|
+
};
|
|
18
|
+
}, {
|
|
19
|
+
readonly id: "runtime-request";
|
|
20
|
+
readonly fixtureName: "valid-runtime-request.json";
|
|
21
|
+
readonly valid: true;
|
|
22
|
+
readonly frame: {
|
|
23
|
+
readonly type: "runtime.request";
|
|
24
|
+
readonly requestId: "00000000-0000-4000-8000-000000000505";
|
|
25
|
+
readonly workspaceId: "00000000-0000-4000-8000-000000000507";
|
|
26
|
+
readonly method: "thread.snapshot";
|
|
27
|
+
readonly params: {
|
|
28
|
+
readonly threadId: "00000000-0000-4000-8000-000000000502";
|
|
29
|
+
readonly limit: 100;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
}, {
|
|
33
|
+
readonly id: "runtime-response";
|
|
34
|
+
readonly fixtureName: "valid-runtime-response.json";
|
|
35
|
+
readonly valid: true;
|
|
36
|
+
readonly frame: {
|
|
37
|
+
readonly type: "runtime.response";
|
|
38
|
+
readonly requestId: "00000000-0000-4000-8000-000000000505";
|
|
39
|
+
readonly workspaceId: "00000000-0000-4000-8000-000000000507";
|
|
40
|
+
readonly result: {
|
|
41
|
+
readonly accepted: true;
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
}, {
|
|
45
|
+
readonly id: "runtime-event";
|
|
46
|
+
readonly fixtureName: "valid-runtime-event.json";
|
|
47
|
+
readonly valid: true;
|
|
48
|
+
readonly frame: {
|
|
49
|
+
readonly type: "runtime.event";
|
|
50
|
+
readonly workspaceId: "00000000-0000-4000-8000-000000000507";
|
|
51
|
+
readonly relaySequence: 0;
|
|
52
|
+
readonly event: {
|
|
53
|
+
readonly protocolVersion: "1.0";
|
|
54
|
+
readonly runtimeInstanceId: "00000000-0000-4000-8000-000000000501";
|
|
55
|
+
readonly sequence: 0;
|
|
56
|
+
readonly timestamp: "2026-07-30T00:00:00.000Z";
|
|
57
|
+
readonly threadId: "00000000-0000-4000-8000-000000000502";
|
|
58
|
+
readonly turnId: "00000000-0000-4000-8000-000000000503";
|
|
59
|
+
readonly event: {
|
|
60
|
+
readonly type: "turn.completed";
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
}, {
|
|
65
|
+
readonly id: "runtime-ack";
|
|
66
|
+
readonly fixtureName: "valid-runtime-ack.json";
|
|
67
|
+
readonly valid: true;
|
|
68
|
+
readonly frame: {
|
|
69
|
+
readonly type: "runtime.ack";
|
|
70
|
+
readonly workspaceId: "00000000-0000-4000-8000-000000000507";
|
|
71
|
+
readonly throughRelaySequence: 0;
|
|
72
|
+
};
|
|
73
|
+
}, {
|
|
74
|
+
readonly id: "runtime-gap";
|
|
75
|
+
readonly fixtureName: "valid-runtime-gap.json";
|
|
76
|
+
readonly valid: true;
|
|
77
|
+
readonly frame: {
|
|
78
|
+
readonly type: "runtime.gap";
|
|
79
|
+
readonly workspaceId: "00000000-0000-4000-8000-000000000507";
|
|
80
|
+
readonly fromRelaySequence: 0;
|
|
81
|
+
readonly throughRelaySequence: 2;
|
|
82
|
+
readonly recovery: "thread.snapshot";
|
|
83
|
+
};
|
|
84
|
+
}, {
|
|
85
|
+
readonly id: "runtime-encrypted";
|
|
86
|
+
readonly fixtureName: "valid-runtime-encrypted.json";
|
|
87
|
+
readonly valid: true;
|
|
88
|
+
readonly frame: {
|
|
89
|
+
readonly type: "runtime.encrypted";
|
|
90
|
+
readonly workspaceId: "00000000-0000-4000-8000-000000000507";
|
|
91
|
+
readonly envelopeId: "00000000-0000-4000-8000-000000000508";
|
|
92
|
+
readonly payloadKind: "request";
|
|
93
|
+
readonly requestId: "00000000-0000-4000-8000-000000000505";
|
|
94
|
+
readonly algorithm: "example-aead";
|
|
95
|
+
readonly nonce: "opaque-nonce";
|
|
96
|
+
readonly ciphertext: "opaque-ciphertext";
|
|
97
|
+
};
|
|
98
|
+
}, {
|
|
99
|
+
readonly id: "unknown-version";
|
|
100
|
+
readonly fixtureName: "invalid-unknown-version.json";
|
|
101
|
+
readonly valid: false;
|
|
102
|
+
readonly frame: {
|
|
103
|
+
readonly type: "device.connect";
|
|
104
|
+
readonly protocolVersion: "9.9";
|
|
105
|
+
readonly deviceId: "00000000-0000-4000-8000-000000000506";
|
|
106
|
+
readonly pairingToken: "pairing-token-with-sufficient-length";
|
|
107
|
+
};
|
|
108
|
+
}, {
|
|
109
|
+
readonly id: "unknown-message";
|
|
110
|
+
readonly fixtureName: "invalid-unknown-message.json";
|
|
111
|
+
readonly valid: false;
|
|
112
|
+
readonly frame: {
|
|
113
|
+
readonly type: "runtime.unknown";
|
|
114
|
+
readonly workspaceId: "00000000-0000-4000-8000-000000000507";
|
|
115
|
+
};
|
|
116
|
+
}, {
|
|
117
|
+
readonly id: "unknown-method";
|
|
118
|
+
readonly fixtureName: "invalid-unknown-method.json";
|
|
119
|
+
readonly valid: false;
|
|
120
|
+
readonly frame: {
|
|
121
|
+
readonly type: "runtime.request";
|
|
122
|
+
readonly requestId: "00000000-0000-4000-8000-000000000505";
|
|
123
|
+
readonly workspaceId: "00000000-0000-4000-8000-000000000507";
|
|
124
|
+
readonly method: "runtime.futureMethod";
|
|
125
|
+
readonly params: {};
|
|
126
|
+
};
|
|
127
|
+
}, {
|
|
128
|
+
readonly id: "invalid-id";
|
|
129
|
+
readonly fixtureName: "invalid-request-id.json";
|
|
130
|
+
readonly valid: false;
|
|
131
|
+
readonly frame: {
|
|
132
|
+
readonly type: "runtime.request";
|
|
133
|
+
readonly requestId: "not-a-uuid";
|
|
134
|
+
readonly workspaceId: "00000000-0000-4000-8000-000000000507";
|
|
135
|
+
readonly method: "thread.list";
|
|
136
|
+
readonly params: {};
|
|
137
|
+
};
|
|
138
|
+
}, {
|
|
139
|
+
readonly id: "extra-field";
|
|
140
|
+
readonly fixtureName: "invalid-extra-field.json";
|
|
141
|
+
readonly valid: false;
|
|
142
|
+
readonly frame: {
|
|
143
|
+
readonly type: "runtime.ack";
|
|
144
|
+
readonly workspaceId: "00000000-0000-4000-8000-000000000507";
|
|
145
|
+
readonly throughRelaySequence: 0;
|
|
146
|
+
readonly unexpected: true;
|
|
147
|
+
};
|
|
148
|
+
}, {
|
|
149
|
+
readonly id: "invalid-gap-recovery";
|
|
150
|
+
readonly fixtureName: "invalid-gap-recovery.json";
|
|
151
|
+
readonly valid: false;
|
|
152
|
+
readonly frame: {
|
|
153
|
+
readonly type: "runtime.gap";
|
|
154
|
+
readonly workspaceId: "00000000-0000-4000-8000-000000000507";
|
|
155
|
+
readonly fromRelaySequence: 0;
|
|
156
|
+
readonly throughRelaySequence: 2;
|
|
157
|
+
readonly recovery: "event.replay";
|
|
158
|
+
};
|
|
159
|
+
}, {
|
|
160
|
+
readonly id: "encrypted-metadata-leak";
|
|
161
|
+
readonly fixtureName: "invalid-encrypted-metadata-leak.json";
|
|
162
|
+
readonly valid: false;
|
|
163
|
+
readonly frame: {
|
|
164
|
+
readonly type: "runtime.encrypted";
|
|
165
|
+
readonly workspaceId: "00000000-0000-4000-8000-000000000507";
|
|
166
|
+
readonly envelopeId: "00000000-0000-4000-8000-000000000508";
|
|
167
|
+
readonly payloadKind: "request";
|
|
168
|
+
readonly requestId: "00000000-0000-4000-8000-000000000505";
|
|
169
|
+
readonly algorithm: "example-aead";
|
|
170
|
+
readonly nonce: "opaque-nonce";
|
|
171
|
+
readonly ciphertext: "opaque-ciphertext";
|
|
172
|
+
readonly plaintext: {
|
|
173
|
+
readonly secret: "must-not-be-visible";
|
|
174
|
+
};
|
|
175
|
+
};
|
|
176
|
+
}];
|
|
177
|
+
export interface RelayNegotiationConformanceCase {
|
|
178
|
+
readonly id: string;
|
|
179
|
+
readonly peerVersions: readonly string[];
|
|
180
|
+
readonly expected: RelayProtocolVersion | undefined;
|
|
181
|
+
}
|
|
182
|
+
export declare const RELAY_NEGOTIATION_CONFORMANCE_CASES: readonly [{
|
|
183
|
+
readonly id: "same-version";
|
|
184
|
+
readonly peerVersions: readonly ["1.0"];
|
|
185
|
+
readonly expected: "1.0";
|
|
186
|
+
}, {
|
|
187
|
+
readonly id: "unknown-before-supported";
|
|
188
|
+
readonly peerVersions: readonly ["9.9", "1.0"];
|
|
189
|
+
readonly expected: "1.0";
|
|
190
|
+
}, {
|
|
191
|
+
readonly id: "unknown-only";
|
|
192
|
+
readonly peerVersions: readonly ["9.9"];
|
|
193
|
+
readonly expected: undefined;
|
|
194
|
+
}];
|
|
195
|
+
export interface RelayMethodRegistryConformanceCase {
|
|
196
|
+
readonly id: string;
|
|
197
|
+
readonly value: string;
|
|
198
|
+
readonly expected: RelayRequestMethodDisposition | undefined;
|
|
199
|
+
}
|
|
200
|
+
export declare const RELAY_METHOD_REGISTRY_CONFORMANCE_CASES: readonly RelayMethodRegistryConformanceCase[];
|
|
201
|
+
export interface RelayMethodConformanceCase {
|
|
202
|
+
readonly id: string;
|
|
203
|
+
readonly method: RelayRequestMethod;
|
|
204
|
+
readonly kind: "params" | "result";
|
|
205
|
+
readonly valid: boolean;
|
|
206
|
+
readonly value: unknown;
|
|
207
|
+
}
|
|
208
|
+
export declare const RELAY_METHOD_CONFORMANCE_CASES: readonly [{
|
|
209
|
+
readonly id: "approval-candidate-params";
|
|
210
|
+
readonly method: "approval.candidate";
|
|
211
|
+
readonly kind: "params";
|
|
212
|
+
readonly valid: true;
|
|
213
|
+
readonly value: {
|
|
214
|
+
readonly threadId: "00000000-0000-4000-8000-000000000502";
|
|
215
|
+
readonly turnId: "00000000-0000-4000-8000-000000000503";
|
|
216
|
+
readonly approvalId: "00000000-0000-4000-8000-000000000504";
|
|
217
|
+
readonly decision: "approve";
|
|
218
|
+
};
|
|
219
|
+
}, {
|
|
220
|
+
readonly id: "approval-candidate-empty-reason";
|
|
221
|
+
readonly method: "approval.candidate";
|
|
222
|
+
readonly kind: "params";
|
|
223
|
+
readonly valid: false;
|
|
224
|
+
readonly value: {
|
|
225
|
+
readonly threadId: "00000000-0000-4000-8000-000000000502";
|
|
226
|
+
readonly turnId: "00000000-0000-4000-8000-000000000503";
|
|
227
|
+
readonly approvalId: "00000000-0000-4000-8000-000000000504";
|
|
228
|
+
readonly decision: "reject";
|
|
229
|
+
readonly reason: "";
|
|
230
|
+
};
|
|
231
|
+
}, {
|
|
232
|
+
readonly id: "approval-candidate-result";
|
|
233
|
+
readonly method: "approval.candidate";
|
|
234
|
+
readonly kind: "result";
|
|
235
|
+
readonly valid: true;
|
|
236
|
+
readonly value: {
|
|
237
|
+
readonly accepted: true;
|
|
238
|
+
};
|
|
239
|
+
}];
|
|
240
|
+
export interface RelayReplayConformanceCase {
|
|
241
|
+
readonly id: string;
|
|
242
|
+
readonly existing: RelayRuntimeRequest;
|
|
243
|
+
readonly candidate: RelayRuntimeRequest;
|
|
244
|
+
readonly expected: RelayRequestReplayClassification;
|
|
245
|
+
}
|
|
246
|
+
export declare const RELAY_REPLAY_CONFORMANCE_CASES: readonly RelayReplayConformanceCase[];
|
|
247
|
+
export interface RelayAckConformanceCase extends RelayAckState {
|
|
248
|
+
readonly id: string;
|
|
249
|
+
readonly expected: RelayAckDisposition;
|
|
250
|
+
}
|
|
251
|
+
export declare const RELAY_ACK_CONFORMANCE_CASES: readonly [{
|
|
252
|
+
readonly id: "initial-advance";
|
|
253
|
+
readonly acknowledgedThrough: -1;
|
|
254
|
+
readonly advertisedThrough: 0;
|
|
255
|
+
readonly incomingThrough: 0;
|
|
256
|
+
readonly expected: "advance";
|
|
257
|
+
}, {
|
|
258
|
+
readonly id: "advance-contiguous-prefix";
|
|
259
|
+
readonly acknowledgedThrough: 0;
|
|
260
|
+
readonly advertisedThrough: 2;
|
|
261
|
+
readonly incomingThrough: 2;
|
|
262
|
+
readonly expected: "advance";
|
|
263
|
+
}, {
|
|
264
|
+
readonly id: "equal-duplicate-ack";
|
|
265
|
+
readonly acknowledgedThrough: 2;
|
|
266
|
+
readonly advertisedThrough: 2;
|
|
267
|
+
readonly incomingThrough: 2;
|
|
268
|
+
readonly expected: "duplicate";
|
|
269
|
+
}, {
|
|
270
|
+
readonly id: "stale-duplicate-ack";
|
|
271
|
+
readonly acknowledgedThrough: 2;
|
|
272
|
+
readonly advertisedThrough: 2;
|
|
273
|
+
readonly incomingThrough: 1;
|
|
274
|
+
readonly expected: "duplicate";
|
|
275
|
+
}, {
|
|
276
|
+
readonly id: "ack-beyond-advertised";
|
|
277
|
+
readonly acknowledgedThrough: 0;
|
|
278
|
+
readonly advertisedThrough: 1;
|
|
279
|
+
readonly incomingThrough: 2;
|
|
280
|
+
readonly expected: "invalid";
|
|
281
|
+
}, {
|
|
282
|
+
readonly id: "fractional-ack";
|
|
283
|
+
readonly acknowledgedThrough: 0;
|
|
284
|
+
readonly advertisedThrough: 1;
|
|
285
|
+
readonly incomingThrough: 0.5;
|
|
286
|
+
readonly expected: "invalid";
|
|
287
|
+
}, {
|
|
288
|
+
readonly id: "ack-below-sentinel";
|
|
289
|
+
readonly acknowledgedThrough: -2;
|
|
290
|
+
readonly advertisedThrough: 0;
|
|
291
|
+
readonly incomingThrough: 0;
|
|
292
|
+
readonly expected: "invalid";
|
|
293
|
+
}];
|
|
294
|
+
export declare const RELAY_ENCRYPTED_VISIBLE_METADATA_FIELDS: readonly ["type", "workspaceId", "envelopeId", "payloadKind", "requestId", "relaySequence", "algorithm", "nonce", "ciphertext"];
|
|
295
|
+
export interface RelayErrorConformanceCase {
|
|
296
|
+
readonly id: string;
|
|
297
|
+
readonly code: RelayErrorCode;
|
|
298
|
+
readonly retryable: boolean;
|
|
299
|
+
}
|
|
300
|
+
export declare const RELAY_ERROR_CONFORMANCE_CASES: {
|
|
301
|
+
id: string;
|
|
302
|
+
code: "INVALID_PARAMS" | "RELAY_PROTOCOL_VERSION_UNSUPPORTED" | "RELAY_INVALID_FRAME" | "RELAY_REQUEST_ID_CONFLICT" | "WORKSPACE_NOT_FOUND" | "RELAY_ENCRYPTION_REQUIRED" | "ENCRYPTED_PAYLOAD_INVALID" | "LocalApprovalDeniedError" | "LocalConfirmationRequiredError" | "COMPANION_ERROR";
|
|
303
|
+
retryable: false;
|
|
304
|
+
}[];
|
|
305
|
+
export interface RelayProtocolConformanceAdapter {
|
|
306
|
+
validateFrame(value: unknown): boolean;
|
|
307
|
+
negotiate(peerVersions: readonly string[]): RelayProtocolVersion | undefined;
|
|
308
|
+
getRequestMethodDisposition(value: string): string | undefined;
|
|
309
|
+
validateMethodValue(method: RelayRequestMethod, kind: "params" | "result", value: unknown): boolean;
|
|
310
|
+
classifyReplay(existing: RelayRuntimeRequest, candidate: RelayRuntimeRequest): RelayReplayConformanceObservation;
|
|
311
|
+
classifyAck(state: RelayAckState): RelayAckDisposition;
|
|
312
|
+
getErrorRetryability(code: RelayErrorCode): boolean;
|
|
313
|
+
}
|
|
314
|
+
export interface RelayReplayConformanceObservation {
|
|
315
|
+
readonly disposition: string;
|
|
316
|
+
readonly errorCode?: string;
|
|
317
|
+
}
|
|
318
|
+
export declare const runtimeRelayProtocolConformanceAdapter: RelayProtocolConformanceAdapter;
|
|
319
|
+
export interface RelayProtocolConformanceFailure {
|
|
320
|
+
readonly caseId: string;
|
|
321
|
+
readonly expected: string;
|
|
322
|
+
readonly actual: string;
|
|
323
|
+
}
|
|
324
|
+
export interface RelayProtocolConformanceResult {
|
|
325
|
+
readonly protocolVersion: typeof RELAY_PROTOCOL_VERSION;
|
|
326
|
+
readonly passed: boolean;
|
|
327
|
+
readonly failures: readonly RelayProtocolConformanceFailure[];
|
|
328
|
+
}
|
|
329
|
+
export declare function runRelayProtocolConformance(adapter: RelayProtocolConformanceAdapter): RelayProtocolConformanceResult;
|