linkshell-cli 0.5.42 → 0.6.1

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 (135) hide show
  1. package/dist/cli/src/commands/host.d.ts +30 -0
  2. package/dist/cli/src/commands/host.js +278 -0
  3. package/dist/cli/src/commands/host.js.map +1 -0
  4. package/dist/cli/src/commands/pair.d.ts +1 -0
  5. package/dist/cli/src/commands/pair.js +51 -0
  6. package/dist/cli/src/commands/pair.js.map +1 -0
  7. package/dist/cli/src/index.js +69 -0
  8. package/dist/cli/src/index.js.map +1 -1
  9. package/dist/cli/src/utils/daemon.d.ts +1 -1
  10. package/dist/cli/src/utils/daemon.js +3 -2
  11. package/dist/cli/src/utils/daemon.js.map +1 -1
  12. package/dist/cli/tsconfig.tsbuildinfo +1 -1
  13. package/dist/host/src/drivers/acp/connection.d.ts +61 -0
  14. package/dist/host/src/drivers/acp/connection.js +121 -0
  15. package/dist/host/src/drivers/acp/connection.js.map +1 -0
  16. package/dist/host/src/drivers/acp/driver.d.ts +110 -0
  17. package/dist/host/src/drivers/acp/driver.js +438 -0
  18. package/dist/host/src/drivers/acp/driver.js.map +1 -0
  19. package/dist/host/src/drivers/acp/mapper.d.ts +49 -0
  20. package/dist/host/src/drivers/acp/mapper.js +411 -0
  21. package/dist/host/src/drivers/acp/mapper.js.map +1 -0
  22. package/dist/host/src/drivers/auth.d.ts +7 -0
  23. package/dist/host/src/drivers/auth.js +57 -0
  24. package/dist/host/src/drivers/auth.js.map +1 -0
  25. package/dist/host/src/drivers/claude/driver.d.ts +76 -0
  26. package/dist/host/src/drivers/claude/driver.js +331 -0
  27. package/dist/host/src/drivers/claude/driver.js.map +1 -0
  28. package/dist/host/src/drivers/claude/transcript.d.ts +335 -0
  29. package/dist/host/src/drivers/claude/transcript.js +516 -0
  30. package/dist/host/src/drivers/claude/transcript.js.map +1 -0
  31. package/dist/host/src/drivers/codex/app-server.d.ts +36 -0
  32. package/dist/host/src/drivers/codex/app-server.js +144 -0
  33. package/dist/host/src/drivers/codex/app-server.js.map +1 -0
  34. package/dist/host/src/drivers/codex/driver.d.ts +89 -0
  35. package/dist/host/src/drivers/codex/driver.js +452 -0
  36. package/dist/host/src/drivers/codex/driver.js.map +1 -0
  37. package/dist/host/src/drivers/codex/mapper.d.ts +61 -0
  38. package/dist/host/src/drivers/codex/mapper.js +623 -0
  39. package/dist/host/src/drivers/codex/mapper.js.map +1 -0
  40. package/dist/host/src/drivers/codex/settings.d.ts +51 -0
  41. package/dist/host/src/drivers/codex/settings.js +107 -0
  42. package/dist/host/src/drivers/codex/settings.js.map +1 -0
  43. package/dist/host/src/drivers/images.d.ts +11 -0
  44. package/dist/host/src/drivers/images.js +34 -0
  45. package/dist/host/src/drivers/images.js.map +1 -0
  46. package/dist/host/src/drivers/nesting.d.ts +6 -0
  47. package/dist/host/src/drivers/nesting.js +25 -0
  48. package/dist/host/src/drivers/nesting.js.map +1 -0
  49. package/dist/host/src/drivers/registry.d.ts +21 -0
  50. package/dist/host/src/drivers/registry.js +30 -0
  51. package/dist/host/src/drivers/registry.js.map +1 -0
  52. package/dist/host/src/drivers/types.d.ts +105 -0
  53. package/dist/host/src/drivers/types.js +2 -0
  54. package/dist/host/src/drivers/types.js.map +1 -0
  55. package/dist/host/src/fs.d.ts +69 -0
  56. package/dist/host/src/fs.js +198 -0
  57. package/dist/host/src/fs.js.map +1 -0
  58. package/dist/host/src/gateway.d.ts +55 -0
  59. package/dist/host/src/gateway.js +263 -0
  60. package/dist/host/src/gateway.js.map +1 -0
  61. package/dist/host/src/host.d.ts +51 -0
  62. package/dist/host/src/host.js +133 -0
  63. package/dist/host/src/host.js.map +1 -0
  64. package/dist/host/src/hub.d.ts +89 -0
  65. package/dist/host/src/hub.js +592 -0
  66. package/dist/host/src/hub.js.map +1 -0
  67. package/dist/host/src/index.d.ts +10 -0
  68. package/dist/host/src/index.js +10 -0
  69. package/dist/host/src/index.js.map +1 -0
  70. package/dist/host/src/ports.d.ts +24 -0
  71. package/dist/host/src/ports.js +201 -0
  72. package/dist/host/src/ports.js.map +1 -0
  73. package/dist/host/src/rpc/client.d.ts +9 -0
  74. package/dist/host/src/rpc/client.js +42 -0
  75. package/dist/host/src/rpc/client.js.map +1 -0
  76. package/dist/host/src/rpc/server.d.ts +52 -0
  77. package/dist/host/src/rpc/server.js +293 -0
  78. package/dist/host/src/rpc/server.js.map +1 -0
  79. package/dist/host/src/screen.d.ts +30 -0
  80. package/dist/host/src/screen.js +230 -0
  81. package/dist/host/src/screen.js.map +1 -0
  82. package/dist/host/src/shell-env.d.ts +8 -0
  83. package/dist/host/src/shell-env.js +39 -0
  84. package/dist/host/src/shell-env.js.map +1 -0
  85. package/dist/host/src/store.d.ts +75 -0
  86. package/dist/host/src/store.js +265 -0
  87. package/dist/host/src/store.js.map +1 -0
  88. package/dist/host/src/terminals.d.ts +55 -0
  89. package/dist/host/src/terminals.js +367 -0
  90. package/dist/host/src/terminals.js.map +1 -0
  91. package/dist/shared-protocol/src/index.d.ts +3345 -3345
  92. package/dist/wire/src/crypto.d.ts +65 -0
  93. package/dist/wire/src/crypto.js +253 -0
  94. package/dist/wire/src/crypto.js.map +1 -0
  95. package/dist/wire/src/index.d.ts +8 -0
  96. package/dist/wire/src/index.js +9 -0
  97. package/dist/wire/src/index.js.map +1 -0
  98. package/dist/wire/src/model.d.ts +704 -0
  99. package/dist/wire/src/model.js +163 -0
  100. package/dist/wire/src/model.js.map +1 -0
  101. package/dist/wire/src/peer.d.ts +42 -0
  102. package/dist/wire/src/peer.js +143 -0
  103. package/dist/wire/src/peer.js.map +1 -0
  104. package/dist/wire/src/relay-client.d.ts +82 -0
  105. package/dist/wire/src/relay-client.js +259 -0
  106. package/dist/wire/src/relay-client.js.map +1 -0
  107. package/dist/wire/src/relay.d.ts +481 -0
  108. package/dist/wire/src/relay.js +129 -0
  109. package/dist/wire/src/relay.js.map +1 -0
  110. package/dist/wire/src/rpc.d.ts +4170 -0
  111. package/dist/wire/src/rpc.js +332 -0
  112. package/dist/wire/src/rpc.js.map +1 -0
  113. package/dist/wire/src/shell.d.ts +2 -0
  114. package/dist/wire/src/shell.js +62 -0
  115. package/dist/wire/src/shell.js.map +1 -0
  116. package/dist/wire/src/updates.d.ts +3325 -0
  117. package/dist/wire/src/updates.js +210 -0
  118. package/dist/wire/src/updates.js.map +1 -0
  119. package/package.json +8 -3
  120. package/src/commands/host.ts +297 -0
  121. package/src/commands/pair.ts +52 -0
  122. package/src/index.ts +74 -0
  123. package/src/utils/daemon.ts +4 -3
  124. package/dist/cli/src/commands/hook.d.ts +0 -6
  125. package/dist/cli/src/commands/hook.js +0 -120
  126. package/dist/cli/src/commands/hook.js.map +0 -1
  127. package/dist/cli/src/runtime/acp/agent-workspace-git.d.ts +0 -63
  128. package/dist/cli/src/runtime/acp/agent-workspace-git.js +0 -297
  129. package/dist/cli/src/runtime/acp/agent-workspace-git.js.map +0 -1
  130. package/dist/cli/src/runtime/acp-relay.d.ts +0 -23
  131. package/dist/cli/src/runtime/acp-relay.js +0 -73
  132. package/dist/cli/src/runtime/acp-relay.js.map +0 -1
  133. package/dist/cli/src/runtime/hook-permission-server.d.ts +0 -36
  134. package/dist/cli/src/runtime/hook-permission-server.js +0 -147
  135. package/dist/cli/src/runtime/hook-permission-server.js.map +0 -1
@@ -0,0 +1,481 @@
1
+ import { z } from "zod";
2
+ import { SecureChannel, type Identity, type PublicIdentity } from "./crypto.js";
3
+ export declare const RELAY_PATH = "/v2/connect";
4
+ export declare const publicIdentitySchema: z.ZodObject<{
5
+ id: z.ZodString;
6
+ signKey: z.ZodString;
7
+ boxKey: z.ZodString;
8
+ }, "strip", z.ZodTypeAny, {
9
+ id: string;
10
+ signKey: string;
11
+ boxKey: string;
12
+ }, {
13
+ id: string;
14
+ signKey: string;
15
+ boxKey: string;
16
+ }>;
17
+ export declare const peerRoleSchema: z.ZodEnum<["machine", "device"]>;
18
+ export type PeerRole = z.infer<typeof peerRoleSchema>;
19
+ /** A machine as a device sees it in the gateway's list. */
20
+ export declare const machineEntrySchema: z.ZodObject<{
21
+ id: z.ZodString;
22
+ signKey: z.ZodString;
23
+ boxKey: z.ZodString;
24
+ } & {
25
+ name: z.ZodString;
26
+ platform: z.ZodOptional<z.ZodString>;
27
+ online: z.ZodBoolean;
28
+ /** How this device may reach it: it paired, or both belong to the same account. */
29
+ via: z.ZodEnum<["paired", "account"]>;
30
+ }, "strip", z.ZodTypeAny, {
31
+ id: string;
32
+ name: string;
33
+ online: boolean;
34
+ signKey: string;
35
+ boxKey: string;
36
+ via: "account" | "paired";
37
+ platform?: string | undefined;
38
+ }, {
39
+ id: string;
40
+ name: string;
41
+ online: boolean;
42
+ signKey: string;
43
+ boxKey: string;
44
+ via: "account" | "paired";
45
+ platform?: string | undefined;
46
+ }>;
47
+ export type MachineEntry = z.infer<typeof machineEntrySchema>;
48
+ export declare const deviceEntrySchema: z.ZodObject<{
49
+ id: z.ZodString;
50
+ signKey: z.ZodString;
51
+ boxKey: z.ZodString;
52
+ } & {
53
+ name: z.ZodString;
54
+ online: z.ZodBoolean;
55
+ pairedAt: z.ZodOptional<z.ZodNumber>;
56
+ }, "strip", z.ZodTypeAny, {
57
+ id: string;
58
+ name: string;
59
+ online: boolean;
60
+ signKey: string;
61
+ boxKey: string;
62
+ pairedAt?: number | undefined;
63
+ }, {
64
+ id: string;
65
+ name: string;
66
+ online: boolean;
67
+ signKey: string;
68
+ boxKey: string;
69
+ pairedAt?: number | undefined;
70
+ }>;
71
+ export type DeviceEntry = z.infer<typeof deviceEntrySchema>;
72
+ export declare const clientFrameSchema: z.ZodDiscriminatedUnion<"t", [z.ZodObject<{
73
+ t: z.ZodLiteral<"auth">;
74
+ role: z.ZodEnum<["machine", "device"]>;
75
+ identity: z.ZodObject<{
76
+ id: z.ZodString;
77
+ signKey: z.ZodString;
78
+ boxKey: z.ZodString;
79
+ }, "strip", z.ZodTypeAny, {
80
+ id: string;
81
+ signKey: string;
82
+ boxKey: string;
83
+ }, {
84
+ id: string;
85
+ signKey: string;
86
+ boxKey: string;
87
+ }>;
88
+ signature: z.ZodString;
89
+ name: z.ZodString;
90
+ platform: z.ZodOptional<z.ZodString>;
91
+ /** Account access token, when signed in. */
92
+ token: z.ZodOptional<z.ZodString>;
93
+ }, "strip", z.ZodTypeAny, {
94
+ role: "machine" | "device";
95
+ name: string;
96
+ t: "auth";
97
+ identity: {
98
+ id: string;
99
+ signKey: string;
100
+ boxKey: string;
101
+ };
102
+ signature: string;
103
+ platform?: string | undefined;
104
+ token?: string | undefined;
105
+ }, {
106
+ role: "machine" | "device";
107
+ name: string;
108
+ t: "auth";
109
+ identity: {
110
+ id: string;
111
+ signKey: string;
112
+ boxKey: string;
113
+ };
114
+ signature: string;
115
+ platform?: string | undefined;
116
+ token?: string | undefined;
117
+ }>, z.ZodObject<{
118
+ t: z.ZodLiteral<"req">;
119
+ id: z.ZodNumber;
120
+ method: z.ZodString;
121
+ params: z.ZodOptional<z.ZodUnknown>;
122
+ }, "strip", z.ZodTypeAny, {
123
+ method: string;
124
+ id: number;
125
+ t: "req";
126
+ params?: unknown;
127
+ }, {
128
+ method: string;
129
+ id: number;
130
+ t: "req";
131
+ params?: unknown;
132
+ }>, z.ZodObject<{
133
+ t: z.ZodLiteral<"to">;
134
+ to: z.ZodString;
135
+ d: z.ZodString;
136
+ }, "strip", z.ZodTypeAny, {
137
+ t: "to";
138
+ to: string;
139
+ d: string;
140
+ }, {
141
+ t: "to";
142
+ to: string;
143
+ d: string;
144
+ }>, z.ZodObject<{
145
+ t: z.ZodLiteral<"ping">;
146
+ }, "strip", z.ZodTypeAny, {
147
+ t: "ping";
148
+ }, {
149
+ t: "ping";
150
+ }>]>;
151
+ export type ClientFrame = z.infer<typeof clientFrameSchema>;
152
+ export declare const serverFrameSchema: z.ZodDiscriminatedUnion<"t", [z.ZodObject<{
153
+ t: z.ZodLiteral<"challenge">;
154
+ nonce: z.ZodString;
155
+ }, "strip", z.ZodTypeAny, {
156
+ t: "challenge";
157
+ nonce: string;
158
+ }, {
159
+ t: "challenge";
160
+ nonce: string;
161
+ }>, z.ZodObject<{
162
+ t: z.ZodLiteral<"ready">;
163
+ userId: z.ZodOptional<z.ZodString>;
164
+ email: z.ZodOptional<z.ZodString>;
165
+ }, "strip", z.ZodTypeAny, {
166
+ t: "ready";
167
+ email?: string | undefined;
168
+ userId?: string | undefined;
169
+ }, {
170
+ t: "ready";
171
+ email?: string | undefined;
172
+ userId?: string | undefined;
173
+ }>, z.ZodObject<{
174
+ t: z.ZodLiteral<"res">;
175
+ id: z.ZodNumber;
176
+ result: z.ZodOptional<z.ZodUnknown>;
177
+ error: z.ZodOptional<z.ZodObject<{
178
+ code: z.ZodString;
179
+ message: z.ZodString;
180
+ }, "strip", z.ZodTypeAny, {
181
+ code: string;
182
+ message: string;
183
+ }, {
184
+ code: string;
185
+ message: string;
186
+ }>>;
187
+ }, "strip", z.ZodTypeAny, {
188
+ id: number;
189
+ t: "res";
190
+ error?: {
191
+ code: string;
192
+ message: string;
193
+ } | undefined;
194
+ result?: unknown;
195
+ }, {
196
+ id: number;
197
+ t: "res";
198
+ error?: {
199
+ code: string;
200
+ message: string;
201
+ } | undefined;
202
+ result?: unknown;
203
+ }>, z.ZodObject<{
204
+ t: z.ZodLiteral<"event">;
205
+ name: z.ZodString;
206
+ data: z.ZodUnknown;
207
+ }, "strip", z.ZodTypeAny, {
208
+ name: string;
209
+ t: "event";
210
+ data?: unknown;
211
+ }, {
212
+ name: string;
213
+ t: "event";
214
+ data?: unknown;
215
+ }>, z.ZodObject<{
216
+ t: z.ZodLiteral<"from">;
217
+ from: z.ZodObject<{
218
+ id: z.ZodString;
219
+ signKey: z.ZodString;
220
+ boxKey: z.ZodString;
221
+ }, "strip", z.ZodTypeAny, {
222
+ id: string;
223
+ signKey: string;
224
+ boxKey: string;
225
+ }, {
226
+ id: string;
227
+ signKey: string;
228
+ boxKey: string;
229
+ }>;
230
+ via: z.ZodEnum<["paired", "account"]>;
231
+ d: z.ZodString;
232
+ }, "strip", z.ZodTypeAny, {
233
+ t: "from";
234
+ via: "account" | "paired";
235
+ d: string;
236
+ from: {
237
+ id: string;
238
+ signKey: string;
239
+ boxKey: string;
240
+ };
241
+ }, {
242
+ t: "from";
243
+ via: "account" | "paired";
244
+ d: string;
245
+ from: {
246
+ id: string;
247
+ signKey: string;
248
+ boxKey: string;
249
+ };
250
+ }>, z.ZodObject<{
251
+ t: z.ZodLiteral<"undeliverable">;
252
+ to: z.ZodString;
253
+ reason: z.ZodString;
254
+ }, "strip", z.ZodTypeAny, {
255
+ reason: string;
256
+ t: "undeliverable";
257
+ to: string;
258
+ }, {
259
+ reason: string;
260
+ t: "undeliverable";
261
+ to: string;
262
+ }>, z.ZodObject<{
263
+ t: z.ZodLiteral<"pong">;
264
+ }, "strip", z.ZodTypeAny, {
265
+ t: "pong";
266
+ }, {
267
+ t: "pong";
268
+ }>, z.ZodObject<{
269
+ t: z.ZodLiteral<"error">;
270
+ code: z.ZodString;
271
+ message: z.ZodString;
272
+ }, "strip", z.ZodTypeAny, {
273
+ code: string;
274
+ message: string;
275
+ t: "error";
276
+ }, {
277
+ code: string;
278
+ message: string;
279
+ t: "error";
280
+ }>]>;
281
+ export type ServerFrame = z.infer<typeof serverFrameSchema>;
282
+ /** Control methods and their results. */
283
+ export interface RelayMethods {
284
+ /** Machine: open a pairing window. The QR carries `secret`; the code is for typing. */
285
+ "pair.offer": {
286
+ params: {
287
+ secretHash?: string;
288
+ };
289
+ result: {
290
+ code: string;
291
+ expiresAt: number;
292
+ };
293
+ };
294
+ /** Machine: accept or refuse a claim it received as a `pair.request` event. */
295
+ "pair.decide": {
296
+ params: {
297
+ requestId: string;
298
+ accept: boolean;
299
+ };
300
+ result: Record<string, never>;
301
+ };
302
+ /** Device: claim a pairing by code (typed) or by machine id (scanned). */
303
+ "pair.claim": {
304
+ params: {
305
+ code?: string;
306
+ machineId?: string;
307
+ proof: string;
308
+ };
309
+ result: {
310
+ machine: MachineEntry;
311
+ };
312
+ };
313
+ "machines.list": {
314
+ params: Record<string, never>;
315
+ result: {
316
+ machines: MachineEntry[];
317
+ };
318
+ };
319
+ "machines.forget": {
320
+ params: {
321
+ machineId: string;
322
+ };
323
+ result: Record<string, never>;
324
+ };
325
+ "devices.list": {
326
+ params: Record<string, never>;
327
+ result: {
328
+ devices: DeviceEntry[];
329
+ };
330
+ };
331
+ "devices.revoke": {
332
+ params: {
333
+ deviceId: string;
334
+ };
335
+ result: Record<string, never>;
336
+ };
337
+ }
338
+ export type RelayMethod = keyof RelayMethods;
339
+ /** Events the gateway pushes. */
340
+ export interface RelayEvents {
341
+ /** To a machine: a device wants to pair. */
342
+ "pair.request": {
343
+ requestId: string;
344
+ device: PublicIdentity & {
345
+ name: string;
346
+ };
347
+ proof: string;
348
+ code: string;
349
+ };
350
+ /** To a machine: pairing finished (accepted or not). */
351
+ "pair.done": {
352
+ requestId: string;
353
+ accepted: boolean;
354
+ device?: DeviceEntry;
355
+ };
356
+ /** A reachable peer came online or went offline. */
357
+ presence: {
358
+ id: string;
359
+ online: boolean;
360
+ };
361
+ /** To a device: the list of reachable machines changed (paired, revoked, account). */
362
+ "machines.changed": Record<string, never>;
363
+ }
364
+ /**
365
+ * What `linkshell pair` puts in the QR code, kept short so the code stays
366
+ * scannable: the gateway, the machine's signing key (its id derives from it,
367
+ * and every channel is checked against it), a one-time secret and the code.
368
+ * The machine's name and box key come from the gateway; a wrong box key can't
369
+ * break a channel's secrecy because the ephemeral keys are signed.
370
+ */
371
+ export interface PairingLink {
372
+ gateway: string;
373
+ signKey: string;
374
+ secret: string;
375
+ code: string;
376
+ }
377
+ export declare const PAIRING_LINK_PREFIX = "linkshell://pair?";
378
+ export declare function encodePairingLink(link: PairingLink): string;
379
+ export declare function decodePairingLink(text: string): PairingLink | undefined;
380
+ /**
381
+ * Frames inside `to` / `from`. A device opens channel `ch` with `hello`, the
382
+ * machine answers `welcome`; both sign their ephemeral key with their
383
+ * long-term key, so neither can be impersonated by the gateway. After that
384
+ * every frame is `data`, sealed with the channel keys.
385
+ */
386
+ export declare const tunnelFrameSchema: z.ZodDiscriminatedUnion<"k", [z.ZodObject<{
387
+ k: z.ZodLiteral<"hello">;
388
+ ch: z.ZodString;
389
+ eph: z.ZodString;
390
+ sig: z.ZodString;
391
+ }, "strip", z.ZodTypeAny, {
392
+ k: "hello";
393
+ ch: string;
394
+ eph: string;
395
+ sig: string;
396
+ }, {
397
+ k: "hello";
398
+ ch: string;
399
+ eph: string;
400
+ sig: string;
401
+ }>, z.ZodObject<{
402
+ k: z.ZodLiteral<"welcome">;
403
+ ch: z.ZodString;
404
+ eph: z.ZodString;
405
+ sig: z.ZodString;
406
+ }, "strip", z.ZodTypeAny, {
407
+ k: "welcome";
408
+ ch: string;
409
+ eph: string;
410
+ sig: string;
411
+ }, {
412
+ k: "welcome";
413
+ ch: string;
414
+ eph: string;
415
+ sig: string;
416
+ }>, z.ZodObject<{
417
+ k: z.ZodLiteral<"data">;
418
+ ch: z.ZodString;
419
+ box: z.ZodString;
420
+ }, "strip", z.ZodTypeAny, {
421
+ k: "data";
422
+ ch: string;
423
+ box: string;
424
+ }, {
425
+ k: "data";
426
+ ch: string;
427
+ box: string;
428
+ }>, z.ZodObject<{
429
+ k: z.ZodLiteral<"close">;
430
+ ch: z.ZodString;
431
+ reason: z.ZodOptional<z.ZodString>;
432
+ }, "strip", z.ZodTypeAny, {
433
+ k: "close";
434
+ ch: string;
435
+ reason?: string | undefined;
436
+ }, {
437
+ k: "close";
438
+ ch: string;
439
+ reason?: string | undefined;
440
+ }>, z.ZodObject<{
441
+ k: z.ZodLiteral<"refuse">;
442
+ ch: z.ZodString;
443
+ code: z.ZodString;
444
+ message: z.ZodString;
445
+ }, "strip", z.ZodTypeAny, {
446
+ code: string;
447
+ message: string;
448
+ k: "refuse";
449
+ ch: string;
450
+ }, {
451
+ code: string;
452
+ message: string;
453
+ k: "refuse";
454
+ ch: string;
455
+ }>]>;
456
+ export type TunnelFrame = z.infer<typeof tunnelFrameSchema>;
457
+ /** Device side: start a channel to `machine`. */
458
+ export declare function openTunnel(device: Identity, machine: PublicIdentity, channel: string): {
459
+ hello: {
460
+ k: "hello";
461
+ ch: string;
462
+ eph: string;
463
+ sig: string;
464
+ };
465
+ /** Checks the machine's answer and returns the channel, or throws. */
466
+ accept(welcome: Extract<TunnelFrame, {
467
+ k: "welcome";
468
+ }>): SecureChannel;
469
+ };
470
+ /** Machine side: answer a device's hello. Throws when the signature is wrong. */
471
+ export declare function answerTunnel(machine: Identity, device: PublicIdentity, hello: Extract<TunnelFrame, {
472
+ k: "hello";
473
+ }>): {
474
+ welcome: {
475
+ k: "welcome";
476
+ ch: string;
477
+ eph: string;
478
+ sig: string;
479
+ };
480
+ channel: SecureChannel;
481
+ };
@@ -0,0 +1,129 @@
1
+ import { z } from "zod";
2
+ import { channelKeys, ephemeralKey, SecureChannel, sign, verifySignature, } from "./crypto.js";
3
+ // Gateway v2 frames. The gateway authenticates peers by their keys, routes
4
+ // opaque frames between a device and a machine it is allowed to reach, and
5
+ // brokers pairing. Everything inside a routed frame is end-to-end encrypted:
6
+ // the gateway never sees RPC, session content or terminal output.
7
+ export const RELAY_PATH = "/v2/connect";
8
+ export const publicIdentitySchema = z.object({ id: z.string(), signKey: z.string(), boxKey: z.string() });
9
+ export const peerRoleSchema = z.enum(["machine", "device"]);
10
+ /** A machine as a device sees it in the gateway's list. */
11
+ export const machineEntrySchema = publicIdentitySchema.extend({
12
+ name: z.string(),
13
+ platform: z.string().optional(),
14
+ online: z.boolean(),
15
+ /** How this device may reach it: it paired, or both belong to the same account. */
16
+ via: z.enum(["paired", "account"]),
17
+ });
18
+ export const deviceEntrySchema = publicIdentitySchema.extend({
19
+ name: z.string(),
20
+ online: z.boolean(),
21
+ pairedAt: z.number().optional(),
22
+ });
23
+ // ── peer → gateway ───────────────────────────────────────────────────
24
+ export const clientFrameSchema = z.discriminatedUnion("t", [
25
+ /** Answer to the challenge: a signature over it proves the key. */
26
+ z.object({
27
+ t: z.literal("auth"),
28
+ role: peerRoleSchema,
29
+ identity: publicIdentitySchema,
30
+ signature: z.string(),
31
+ name: z.string().max(120),
32
+ platform: z.string().max(40).optional(),
33
+ /** Account access token, when signed in. */
34
+ token: z.string().optional(),
35
+ }),
36
+ z.object({ t: z.literal("req"), id: z.number().int(), method: z.string(), params: z.unknown().optional() }),
37
+ /** An encrypted frame for a peer. */
38
+ z.object({ t: z.literal("to"), to: z.string(), d: z.string().max(40 * 1024 * 1024) }),
39
+ z.object({ t: z.literal("ping") }),
40
+ ]);
41
+ // ── gateway → peer ───────────────────────────────────────────────────
42
+ export const serverFrameSchema = z.discriminatedUnion("t", [
43
+ z.object({ t: z.literal("challenge"), nonce: z.string() }),
44
+ z.object({ t: z.literal("ready"), userId: z.string().optional(), email: z.string().optional() }),
45
+ z.object({
46
+ t: z.literal("res"),
47
+ id: z.number().int(),
48
+ result: z.unknown().optional(),
49
+ error: z.object({ code: z.string(), message: z.string() }).optional(),
50
+ }),
51
+ z.object({ t: z.literal("event"), name: z.string(), data: z.unknown() }),
52
+ /** An encrypted frame from a peer, with the keys the gateway verified it holds. */
53
+ z.object({ t: z.literal("from"), from: publicIdentitySchema, via: z.enum(["paired", "account"]), d: z.string() }),
54
+ /** A frame couldn't be delivered: the peer is offline or not reachable. */
55
+ z.object({ t: z.literal("undeliverable"), to: z.string(), reason: z.string() }),
56
+ z.object({ t: z.literal("pong") }),
57
+ z.object({ t: z.literal("error"), code: z.string(), message: z.string() }),
58
+ ]);
59
+ export const PAIRING_LINK_PREFIX = "linkshell://pair?";
60
+ export function encodePairingLink(link) {
61
+ const params = new URLSearchParams({ g: link.gateway, k: link.signKey, s: link.secret, c: link.code });
62
+ return PAIRING_LINK_PREFIX + params.toString();
63
+ }
64
+ export function decodePairingLink(text) {
65
+ const trimmed = text.trim();
66
+ if (!trimmed.startsWith(PAIRING_LINK_PREFIX))
67
+ return undefined;
68
+ const params = new URLSearchParams(trimmed.slice(PAIRING_LINK_PREFIX.length));
69
+ const gateway = params.get("g");
70
+ const signKey = params.get("k");
71
+ const secret = params.get("s");
72
+ const code = params.get("c");
73
+ if (!gateway || !signKey || !secret || !code || !/^(wss?|https?):\/\//.test(gateway))
74
+ return undefined;
75
+ return { gateway, signKey, secret, code };
76
+ }
77
+ // ── end-to-end channel over the relay ────────────────────────────────
78
+ /**
79
+ * Frames inside `to` / `from`. A device opens channel `ch` with `hello`, the
80
+ * machine answers `welcome`; both sign their ephemeral key with their
81
+ * long-term key, so neither can be impersonated by the gateway. After that
82
+ * every frame is `data`, sealed with the channel keys.
83
+ */
84
+ export const tunnelFrameSchema = z.discriminatedUnion("k", [
85
+ z.object({ k: z.literal("hello"), ch: z.string(), eph: z.string(), sig: z.string() }),
86
+ z.object({ k: z.literal("welcome"), ch: z.string(), eph: z.string(), sig: z.string() }),
87
+ z.object({ k: z.literal("data"), ch: z.string(), box: z.string() }),
88
+ z.object({ k: z.literal("close"), ch: z.string(), reason: z.string().optional() }),
89
+ z.object({ k: z.literal("refuse"), ch: z.string(), code: z.string(), message: z.string() }),
90
+ ]);
91
+ function helloMessage(kind, channel, from, to, eph) {
92
+ return `linkshell-tunnel-v2:${kind}:${channel}:${from}:${to}:${eph}`;
93
+ }
94
+ /** Device side: start a channel to `machine`. */
95
+ export function openTunnel(device, machine, channel) {
96
+ const eph = ephemeralKey();
97
+ const hello = {
98
+ k: "hello",
99
+ ch: channel,
100
+ eph: eph.public,
101
+ sig: sign(device, helloMessage("hello", channel, device.id, machine.id, eph.public)),
102
+ };
103
+ return {
104
+ hello,
105
+ /** Checks the machine's answer and returns the channel, or throws. */
106
+ accept(welcome) {
107
+ if (!verifySignature(machine.signKey, helloMessage("welcome", channel, machine.id, device.id, welcome.eph), welcome.sig)) {
108
+ throw new Error("the computer's key doesn't match: refusing to connect");
109
+ }
110
+ return new SecureChannel(channelKeys({ initiator: true, local: device, localEphemeral: eph.secret, remoteBoxKey: machine.boxKey, remoteEphemeral: welcome.eph }));
111
+ },
112
+ };
113
+ }
114
+ /** Machine side: answer a device's hello. Throws when the signature is wrong. */
115
+ export function answerTunnel(machine, device, hello) {
116
+ if (!verifySignature(device.signKey, helloMessage("hello", hello.ch, device.id, machine.id, hello.eph), hello.sig)) {
117
+ throw new Error("bad hello signature");
118
+ }
119
+ const eph = ephemeralKey();
120
+ const welcome = {
121
+ k: "welcome",
122
+ ch: hello.ch,
123
+ eph: eph.public,
124
+ sig: sign(machine, helloMessage("welcome", hello.ch, machine.id, device.id, eph.public)),
125
+ };
126
+ const channel = new SecureChannel(channelKeys({ initiator: false, local: machine, localEphemeral: eph.secret, remoteBoxKey: device.boxKey, remoteEphemeral: hello.eph }));
127
+ return { welcome, channel };
128
+ }
129
+ //# sourceMappingURL=relay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relay.js","sourceRoot":"","sources":["../../../../wire/src/relay.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,WAAW,EACX,YAAY,EACZ,aAAa,EACb,IAAI,EACJ,eAAe,GAGhB,MAAM,aAAa,CAAC;AAErB,2EAA2E;AAC3E,2EAA2E;AAC3E,6EAA6E;AAC7E,kEAAkE;AAElE,MAAM,CAAC,MAAM,UAAU,GAAG,aAAa,CAAC;AAExC,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAE1G,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC;AAG5D,2DAA2D;AAC3D,MAAM,CAAC,MAAM,kBAAkB,GAAG,oBAAoB,CAAC,MAAM,CAAC;IAC5D,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC/B,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE;IACnB,mFAAmF;IACnF,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;CACnC,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,iBAAiB,GAAG,oBAAoB,CAAC,MAAM,CAAC;IAC3D,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE;IACnB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAChC,CAAC,CAAC;AAGH,wEAAwE;AAExE,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE;IACzD,mEAAmE;IACnE,CAAC,CAAC,MAAM,CAAC;QACP,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;QACpB,IAAI,EAAE,cAAc;QACpB,QAAQ,EAAE,oBAAoB;QAC9B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;QACrB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC;QACzB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE;QACvC,4CAA4C;QAC5C,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;KAC7B,CAAC;IACF,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC;IAC3G,qCAAqC;IACrC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC;IACrF,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;CACnC,CAAC,CAAC;AAGH,wEAAwE;AAExE,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE;IACzD,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;IAC1D,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC;IAChG,CAAC,CAAC,MAAM,CAAC;QACP,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;QACnB,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;QACpB,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;QAC9B,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,QAAQ,EAAE;KACtE,CAAC;IACF,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC;IACxE,mFAAmF;IACnF,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,oBAAoB,EAAE,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;IACjH,2EAA2E;IAC3E,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;IAC/E,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;IAClC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;CAC3E,CAAC,CAAC;AA+CH,MAAM,CAAC,MAAM,mBAAmB,GAAG,mBAAmB,CAAC;AAEvD,MAAM,UAAU,iBAAiB,CAAC,IAAiB;IACjD,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IACvG,OAAO,mBAAmB,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,mBAAmB,CAAC;QAAE,OAAO,SAAS,CAAC;IAC/D,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,OAAO,CAAC,KAAK,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC,CAAC;IAC9E,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC/B,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,OAAO,SAAS,CAAC;IACvG,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AAC5C,CAAC;AAED,wEAAwE;AAExE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE;IACzD,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;IACrF,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;IACvF,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;IACnE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC;IAClF,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;CAC5F,CAAC,CAAC;AAGH,SAAS,YAAY,CAAC,IAAyB,EAAE,OAAe,EAAE,IAAY,EAAE,EAAU,EAAE,GAAW;IACrG,OAAO,uBAAuB,IAAI,IAAI,OAAO,IAAI,IAAI,IAAI,EAAE,IAAI,GAAG,EAAE,CAAC;AACvE,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,UAAU,CAAC,MAAgB,EAAE,OAAuB,EAAE,OAAe;IACnF,MAAM,GAAG,GAAG,YAAY,EAAE,CAAC;IAC3B,MAAM,KAAK,GAAgB;QACzB,CAAC,EAAE,OAAO;QACV,EAAE,EAAE,OAAO;QACX,GAAG,EAAE,GAAG,CAAC,MAAM;QACf,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;KACrF,CAAC;IACF,OAAO;QACL,KAAK;QACL,sEAAsE;QACtE,MAAM,CAAC,OAA+C;YACpD,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,OAAO,EAAE,YAAY,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;gBACzH,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;YAC3E,CAAC;YACD,OAAO,IAAI,aAAa,CACtB,WAAW,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,CAAC,MAAM,EAAE,eAAe,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CACxI,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,YAAY,CAAC,OAAiB,EAAE,MAAsB,EAAE,KAA2C;IACjH,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,OAAO,EAAE,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACnH,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;IACzC,CAAC;IACD,MAAM,GAAG,GAAG,YAAY,EAAE,CAAC;IAC3B,MAAM,OAAO,GAAgB;QAC3B,CAAC,EAAE,SAAS;QACZ,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,GAAG,EAAE,GAAG,CAAC,MAAM;QACf,GAAG,EAAE,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;KACzF,CAAC;IACF,MAAM,OAAO,GAAG,IAAI,aAAa,CAC/B,WAAW,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CACvI,CAAC;IACF,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAC9B,CAAC"}