@spotpatch/shared 1.12.0 → 1.14.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/dist/annotation-Cz-NNgR4.d.cts +102 -0
- package/dist/annotation-Cz-NNgR4.d.ts +102 -0
- package/dist/chunk-CLQ6MIJB.js +586 -0
- package/dist/chunk-CLQ6MIJB.js.map +1 -0
- package/dist/chunk-EWJTKNL4.js +90 -0
- package/dist/chunk-EWJTKNL4.js.map +1 -0
- package/dist/{chunk-JGOIBOFI.js → chunk-FPDSZDP2.js} +16 -2
- package/dist/chunk-FPDSZDP2.js.map +1 -0
- package/dist/{chunk-2LVIH7OA.js → chunk-IX6MSCK6.js} +6 -2
- package/dist/chunk-IX6MSCK6.js.map +1 -0
- package/dist/{chunk-JU5HIWX7.js → chunk-JTZFOTPT.js} +9 -174
- package/dist/chunk-JTZFOTPT.js.map +1 -0
- package/dist/chunk-R6QJFNT2.js +195 -0
- package/dist/chunk-R6QJFNT2.js.map +1 -0
- package/dist/contextual-ask-BpbkpFFf.d.cts +1476 -0
- package/dist/contextual-ask-BpbkpFFf.d.ts +1476 -0
- package/dist/contextual-ask-browser.cjs +201 -0
- package/dist/contextual-ask-browser.cjs.map +1 -0
- package/dist/contextual-ask-browser.d.cts +31 -0
- package/dist/contextual-ask-browser.d.ts +31 -0
- package/dist/contextual-ask-browser.js +66 -0
- package/dist/contextual-ask-browser.js.map +1 -0
- package/dist/contextual-ask-node.cjs +971 -0
- package/dist/contextual-ask-node.cjs.map +1 -0
- package/dist/contextual-ask-node.d.cts +14 -0
- package/dist/contextual-ask-node.d.ts +14 -0
- package/dist/contextual-ask-node.js +122 -0
- package/dist/contextual-ask-node.js.map +1 -0
- package/dist/{data-flow-runtime-BelOgo8s.d.ts → data-flow-runtime-DhWpQoik.d.ts} +26 -13
- package/dist/{data-flow-runtime-oq9m21IP.d.cts → data-flow-runtime-w43iwvGA.d.cts} +26 -13
- package/dist/data-flow-runtime.cjs +2 -0
- package/dist/data-flow-runtime.cjs.map +1 -1
- package/dist/data-flow-runtime.d.cts +2 -2
- package/dist/data-flow-runtime.d.ts +2 -2
- package/dist/data-flow-runtime.js +1 -1
- package/dist/{endpoints-GedF44M2.d.cts → endpoints-O3ohYyAo.d.cts} +7 -1
- package/dist/{endpoints-GedF44M2.d.ts → endpoints-O3ohYyAo.d.ts} +7 -1
- package/dist/error-code-DRz2eqcB.d.cts +63 -0
- package/dist/error-code-DRz2eqcB.d.ts +63 -0
- package/dist/external-agent-node.cjs +320 -141
- package/dist/external-agent-node.cjs.map +1 -1
- package/dist/external-agent-node.d.cts +43 -27
- package/dist/external-agent-node.d.ts +43 -27
- package/dist/external-agent-node.js +174 -20
- package/dist/external-agent-node.js.map +1 -1
- package/dist/{external-handoff-BNUyMfNb.d.ts → external-handoff-5zHu-fz2.d.ts} +41 -131
- package/dist/{external-handoff-BNUyMfNb.d.cts → external-handoff-DeiIvR-2.d.cts} +41 -131
- package/dist/external-handoff-browser.cjs +7 -1
- package/dist/external-handoff-browser.cjs.map +1 -1
- package/dist/external-handoff-browser.d.cts +4 -3
- package/dist/external-handoff-browser.d.ts +4 -3
- package/dist/external-handoff-browser.js +2 -2
- package/dist/index.cjs +1170 -426
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +138 -178
- package/dist/index.d.ts +138 -178
- package/dist/index.js +116 -20
- package/dist/index.js.map +1 -1
- package/package.json +29 -2
- package/dist/chunk-2LVIH7OA.js.map +0 -1
- package/dist/chunk-JGOIBOFI.js.map +0 -1
- package/dist/chunk-JU5HIWX7.js.map +0 -1
- package/dist/{external-agent-control-BMoSq_xI.d.cts → external-agent-control-C79Nl85y.d.cts} +49 -49
- package/dist/{external-agent-control-BMoSq_xI.d.ts → external-agent-control-C79Nl85y.d.ts} +49 -49
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { Stats } from 'node:fs';
|
|
1
2
|
import { z } from 'zod';
|
|
2
|
-
import { E as EXTERNAL_HANDOFF_LIMITS, A as ActiveAdapterSummary, D as DispatchSummary, a as ExternalHandoffSnapshot } from './external-handoff-
|
|
3
|
+
import { E as EXTERNAL_HANDOFF_LIMITS, A as ActiveAdapterSummary, D as DispatchSummary, a as ExternalHandoffSnapshot } from './external-handoff-5zHu-fz2.js';
|
|
4
|
+
import './annotation-Cz-NNgR4.js';
|
|
3
5
|
|
|
4
6
|
declare const SPOTPATCH_BRIDGE_TOKEN_HEADER: "X-SpotPatch-Bridge-Token";
|
|
5
7
|
declare const SPOTPATCH_BRIDGE_PATHS: Readonly<{
|
|
@@ -19,6 +21,7 @@ declare const externalHandoffDescriptorSchema: z.ZodObject<{
|
|
|
19
21
|
projectKey: z.ZodString;
|
|
20
22
|
sessionId: z.ZodString;
|
|
21
23
|
framework: z.ZodEnum<{
|
|
24
|
+
astro: "astro";
|
|
22
25
|
vite: "vite";
|
|
23
26
|
next: "next";
|
|
24
27
|
}>;
|
|
@@ -53,10 +56,10 @@ declare const bridgeActiveReportRequestSchema: z.ZodObject<{
|
|
|
53
56
|
leaseToken: z.ZodString;
|
|
54
57
|
cursor: z.ZodString;
|
|
55
58
|
phase: z.ZodEnum<{
|
|
56
|
-
dispatching: "dispatching";
|
|
57
|
-
completed: "completed";
|
|
58
59
|
failed: "failed";
|
|
59
60
|
dispatched: "dispatched";
|
|
61
|
+
completed: "completed";
|
|
62
|
+
dispatching: "dispatching";
|
|
60
63
|
working: "working";
|
|
61
64
|
"delivery-unknown": "delivery-unknown";
|
|
62
65
|
}>;
|
|
@@ -69,12 +72,14 @@ declare const bridgeStatusSchema: z.ZodObject<{
|
|
|
69
72
|
projectKey: z.ZodString;
|
|
70
73
|
sessionId: z.ZodString;
|
|
71
74
|
framework: z.ZodEnum<{
|
|
75
|
+
astro: "astro";
|
|
72
76
|
vite: "vite";
|
|
73
77
|
next: "next";
|
|
74
78
|
}>;
|
|
75
79
|
current: z.ZodNullable<z.ZodObject<{
|
|
76
80
|
sessionId: z.ZodString;
|
|
77
81
|
framework: z.ZodEnum<{
|
|
82
|
+
astro: "astro";
|
|
78
83
|
vite: "vite";
|
|
79
84
|
next: "next";
|
|
80
85
|
}>;
|
|
@@ -88,8 +93,8 @@ declare const bridgeStatusSchema: z.ZodObject<{
|
|
|
88
93
|
publishedAt: z.ZodISODateTime;
|
|
89
94
|
expiresAt: z.ZodISODateTime;
|
|
90
95
|
state: z.ZodEnum<{
|
|
91
|
-
available: "available";
|
|
92
96
|
expired: "expired";
|
|
97
|
+
available: "available";
|
|
93
98
|
superseded: "superseded";
|
|
94
99
|
}>;
|
|
95
100
|
pickupCount: z.ZodNumber;
|
|
@@ -104,6 +109,7 @@ declare const bridgeCurrentResultSchema: z.ZodObject<{
|
|
|
104
109
|
session: z.ZodObject<{
|
|
105
110
|
id: z.ZodString;
|
|
106
111
|
framework: z.ZodEnum<{
|
|
112
|
+
astro: "astro";
|
|
107
113
|
vite: "vite";
|
|
108
114
|
next: "next";
|
|
109
115
|
}>;
|
|
@@ -142,16 +148,17 @@ declare const bridgeCurrentResultSchema: z.ZodObject<{
|
|
|
142
148
|
line: z.ZodOptional<z.ZodNumber>;
|
|
143
149
|
column: z.ZodOptional<z.ZodNumber>;
|
|
144
150
|
origin: z.ZodEnum<{
|
|
145
|
-
none: "none";
|
|
146
151
|
"jsx-host": "jsx-host";
|
|
152
|
+
"astro-host": "astro-host";
|
|
147
153
|
"react-fiber": "react-fiber";
|
|
148
154
|
"dom-ancestor": "dom-ancestor";
|
|
155
|
+
none: "none";
|
|
149
156
|
}>;
|
|
150
157
|
confidence: z.ZodEnum<{
|
|
151
|
-
unknown: "unknown";
|
|
152
158
|
exact: "exact";
|
|
153
159
|
probable: "probable";
|
|
154
160
|
approximate: "approximate";
|
|
161
|
+
unknown: "unknown";
|
|
155
162
|
}>;
|
|
156
163
|
}, z.core.$strict>;
|
|
157
164
|
react: z.ZodObject<{
|
|
@@ -167,16 +174,17 @@ declare const bridgeCurrentResultSchema: z.ZodObject<{
|
|
|
167
174
|
line: z.ZodOptional<z.ZodNumber>;
|
|
168
175
|
column: z.ZodOptional<z.ZodNumber>;
|
|
169
176
|
origin: z.ZodEnum<{
|
|
170
|
-
none: "none";
|
|
171
177
|
"jsx-host": "jsx-host";
|
|
178
|
+
"astro-host": "astro-host";
|
|
172
179
|
"react-fiber": "react-fiber";
|
|
173
180
|
"dom-ancestor": "dom-ancestor";
|
|
181
|
+
none: "none";
|
|
174
182
|
}>;
|
|
175
183
|
confidence: z.ZodEnum<{
|
|
176
|
-
unknown: "unknown";
|
|
177
184
|
exact: "exact";
|
|
178
185
|
probable: "probable";
|
|
179
186
|
approximate: "approximate";
|
|
187
|
+
unknown: "unknown";
|
|
180
188
|
}>;
|
|
181
189
|
}, z.core.$strict>>;
|
|
182
190
|
}, z.core.$strict>;
|
|
@@ -210,6 +218,7 @@ declare const bridgeCurrentResultSchema: z.ZodObject<{
|
|
|
210
218
|
language: z.ZodEnum<{
|
|
211
219
|
tsx: "tsx";
|
|
212
220
|
jsx: "jsx";
|
|
221
|
+
astro: "astro";
|
|
213
222
|
}>;
|
|
214
223
|
startLine: z.ZodNumber;
|
|
215
224
|
endLine: z.ZodNumber;
|
|
@@ -233,6 +242,7 @@ declare const bridgeWaitResultSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
233
242
|
session: z.ZodObject<{
|
|
234
243
|
id: z.ZodString;
|
|
235
244
|
framework: z.ZodEnum<{
|
|
245
|
+
astro: "astro";
|
|
236
246
|
vite: "vite";
|
|
237
247
|
next: "next";
|
|
238
248
|
}>;
|
|
@@ -271,16 +281,17 @@ declare const bridgeWaitResultSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
271
281
|
line: z.ZodOptional<z.ZodNumber>;
|
|
272
282
|
column: z.ZodOptional<z.ZodNumber>;
|
|
273
283
|
origin: z.ZodEnum<{
|
|
274
|
-
none: "none";
|
|
275
284
|
"jsx-host": "jsx-host";
|
|
285
|
+
"astro-host": "astro-host";
|
|
276
286
|
"react-fiber": "react-fiber";
|
|
277
287
|
"dom-ancestor": "dom-ancestor";
|
|
288
|
+
none: "none";
|
|
278
289
|
}>;
|
|
279
290
|
confidence: z.ZodEnum<{
|
|
280
|
-
unknown: "unknown";
|
|
281
291
|
exact: "exact";
|
|
282
292
|
probable: "probable";
|
|
283
293
|
approximate: "approximate";
|
|
294
|
+
unknown: "unknown";
|
|
284
295
|
}>;
|
|
285
296
|
}, z.core.$strict>;
|
|
286
297
|
react: z.ZodObject<{
|
|
@@ -296,16 +307,17 @@ declare const bridgeWaitResultSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
296
307
|
line: z.ZodOptional<z.ZodNumber>;
|
|
297
308
|
column: z.ZodOptional<z.ZodNumber>;
|
|
298
309
|
origin: z.ZodEnum<{
|
|
299
|
-
none: "none";
|
|
300
310
|
"jsx-host": "jsx-host";
|
|
311
|
+
"astro-host": "astro-host";
|
|
301
312
|
"react-fiber": "react-fiber";
|
|
302
313
|
"dom-ancestor": "dom-ancestor";
|
|
314
|
+
none: "none";
|
|
303
315
|
}>;
|
|
304
316
|
confidence: z.ZodEnum<{
|
|
305
|
-
unknown: "unknown";
|
|
306
317
|
exact: "exact";
|
|
307
318
|
probable: "probable";
|
|
308
319
|
approximate: "approximate";
|
|
320
|
+
unknown: "unknown";
|
|
309
321
|
}>;
|
|
310
322
|
}, z.core.$strict>>;
|
|
311
323
|
}, z.core.$strict>;
|
|
@@ -339,6 +351,7 @@ declare const bridgeWaitResultSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
339
351
|
language: z.ZodEnum<{
|
|
340
352
|
tsx: "tsx";
|
|
341
353
|
jsx: "jsx";
|
|
354
|
+
astro: "astro";
|
|
342
355
|
}>;
|
|
343
356
|
startLine: z.ZodNumber;
|
|
344
357
|
endLine: z.ZodNumber;
|
|
@@ -360,6 +373,7 @@ declare const bridgeAckResultSchema: z.ZodObject<{
|
|
|
360
373
|
summary: z.ZodObject<{
|
|
361
374
|
sessionId: z.ZodString;
|
|
362
375
|
framework: z.ZodEnum<{
|
|
376
|
+
astro: "astro";
|
|
363
377
|
vite: "vite";
|
|
364
378
|
next: "next";
|
|
365
379
|
}>;
|
|
@@ -373,8 +387,8 @@ declare const bridgeAckResultSchema: z.ZodObject<{
|
|
|
373
387
|
publishedAt: z.ZodISODateTime;
|
|
374
388
|
expiresAt: z.ZodISODateTime;
|
|
375
389
|
state: z.ZodEnum<{
|
|
376
|
-
available: "available";
|
|
377
390
|
expired: "expired";
|
|
391
|
+
available: "available";
|
|
378
392
|
superseded: "superseded";
|
|
379
393
|
}>;
|
|
380
394
|
pickupCount: z.ZodNumber;
|
|
@@ -392,8 +406,8 @@ declare const bridgeActiveClaimResultSchema: z.ZodObject<{
|
|
|
392
406
|
}>;
|
|
393
407
|
state: z.ZodEnum<{
|
|
394
408
|
ready: "ready";
|
|
395
|
-
busy: "busy";
|
|
396
409
|
blocked: "blocked";
|
|
410
|
+
busy: "busy";
|
|
397
411
|
}>;
|
|
398
412
|
canDispatch: z.ZodBoolean;
|
|
399
413
|
connectedAt: z.ZodISODateTime;
|
|
@@ -408,8 +422,8 @@ declare const bridgeActiveStateResultSchema: z.ZodObject<{
|
|
|
408
422
|
}>;
|
|
409
423
|
state: z.ZodEnum<{
|
|
410
424
|
ready: "ready";
|
|
411
|
-
busy: "busy";
|
|
412
425
|
blocked: "blocked";
|
|
426
|
+
busy: "busy";
|
|
413
427
|
}>;
|
|
414
428
|
canDispatch: z.ZodBoolean;
|
|
415
429
|
connectedAt: z.ZodISODateTime;
|
|
@@ -423,10 +437,10 @@ declare const bridgeActiveStateResultSchema: z.ZodObject<{
|
|
|
423
437
|
revision: z.ZodNumber;
|
|
424
438
|
phase: z.ZodEnum<{
|
|
425
439
|
queued: "queued";
|
|
426
|
-
dispatching: "dispatching";
|
|
427
|
-
completed: "completed";
|
|
428
440
|
failed: "failed";
|
|
429
441
|
dispatched: "dispatched";
|
|
442
|
+
completed: "completed";
|
|
443
|
+
dispatching: "dispatching";
|
|
430
444
|
working: "working";
|
|
431
445
|
"delivery-unknown": "delivery-unknown";
|
|
432
446
|
}>;
|
|
@@ -441,8 +455,8 @@ declare const bridgeActiveHeartbeatResultSchema: z.ZodObject<{
|
|
|
441
455
|
}>;
|
|
442
456
|
state: z.ZodEnum<{
|
|
443
457
|
ready: "ready";
|
|
444
|
-
busy: "busy";
|
|
445
458
|
blocked: "blocked";
|
|
459
|
+
busy: "busy";
|
|
446
460
|
}>;
|
|
447
461
|
canDispatch: z.ZodBoolean;
|
|
448
462
|
connectedAt: z.ZodISODateTime;
|
|
@@ -456,10 +470,10 @@ declare const bridgeActiveHeartbeatResultSchema: z.ZodObject<{
|
|
|
456
470
|
revision: z.ZodNumber;
|
|
457
471
|
phase: z.ZodEnum<{
|
|
458
472
|
queued: "queued";
|
|
459
|
-
dispatching: "dispatching";
|
|
460
|
-
completed: "completed";
|
|
461
473
|
failed: "failed";
|
|
462
474
|
dispatched: "dispatched";
|
|
475
|
+
completed: "completed";
|
|
476
|
+
dispatching: "dispatching";
|
|
463
477
|
working: "working";
|
|
464
478
|
"delivery-unknown": "delivery-unknown";
|
|
465
479
|
}>;
|
|
@@ -474,8 +488,8 @@ declare const bridgeActiveReportResultSchema: z.ZodObject<{
|
|
|
474
488
|
}>;
|
|
475
489
|
state: z.ZodEnum<{
|
|
476
490
|
ready: "ready";
|
|
477
|
-
busy: "busy";
|
|
478
491
|
blocked: "blocked";
|
|
492
|
+
busy: "busy";
|
|
479
493
|
}>;
|
|
480
494
|
canDispatch: z.ZodBoolean;
|
|
481
495
|
connectedAt: z.ZodISODateTime;
|
|
@@ -489,10 +503,10 @@ declare const bridgeActiveReportResultSchema: z.ZodObject<{
|
|
|
489
503
|
revision: z.ZodNumber;
|
|
490
504
|
phase: z.ZodEnum<{
|
|
491
505
|
queued: "queued";
|
|
492
|
-
dispatching: "dispatching";
|
|
493
|
-
completed: "completed";
|
|
494
506
|
failed: "failed";
|
|
495
507
|
dispatched: "dispatched";
|
|
508
|
+
completed: "completed";
|
|
509
|
+
dispatching: "dispatching";
|
|
496
510
|
working: "working";
|
|
497
511
|
"delivery-unknown": "delivery-unknown";
|
|
498
512
|
}>;
|
|
@@ -507,8 +521,8 @@ declare const bridgeActiveReleaseResultSchema: z.ZodObject<{
|
|
|
507
521
|
}>;
|
|
508
522
|
state: z.ZodEnum<{
|
|
509
523
|
ready: "ready";
|
|
510
|
-
busy: "busy";
|
|
511
524
|
blocked: "blocked";
|
|
525
|
+
busy: "busy";
|
|
512
526
|
}>;
|
|
513
527
|
canDispatch: z.ZodBoolean;
|
|
514
528
|
connectedAt: z.ZodISODateTime;
|
|
@@ -522,10 +536,10 @@ declare const bridgeActiveReleaseResultSchema: z.ZodObject<{
|
|
|
522
536
|
revision: z.ZodNumber;
|
|
523
537
|
phase: z.ZodEnum<{
|
|
524
538
|
queued: "queued";
|
|
525
|
-
dispatching: "dispatching";
|
|
526
|
-
completed: "completed";
|
|
527
539
|
failed: "failed";
|
|
528
540
|
dispatched: "dispatched";
|
|
541
|
+
completed: "completed";
|
|
542
|
+
dispatching: "dispatching";
|
|
529
543
|
working: "working";
|
|
530
544
|
"delivery-unknown": "delivery-unknown";
|
|
531
545
|
}>;
|
|
@@ -550,7 +564,9 @@ interface BridgeActiveStateResult {
|
|
|
550
564
|
readonly activeAdapter: ActiveAdapterSummary | null;
|
|
551
565
|
readonly dispatch: DispatchSummary | null;
|
|
552
566
|
}
|
|
567
|
+
declare function assertPrivateExternalHandoffPath(candidate: string, kind: "directory" | "file"): Promise<Stats>;
|
|
568
|
+
declare function initializePrivateExternalHandoffFile(candidate: string): Promise<void>;
|
|
553
569
|
declare function resolveExternalHandoffRuntimeDirectory(create: boolean): Promise<string>;
|
|
554
570
|
declare function computeExternalHandoffProjectKey(root: string): Promise<string>;
|
|
555
571
|
|
|
556
|
-
export { type BridgeActiveClaimResult, type BridgeActiveStateResult, type BridgeStatus, type BridgeWaitResult, EXTERNAL_HANDOFF_PROJECT_KEY_SALT, type ExternalHandoffDescriptor, SPOTPATCH_BRIDGE_PATHS, SPOTPATCH_BRIDGE_TOKEN_HEADER, bridgeAckRequestSchema, bridgeAckResultSchema, bridgeActiveClaimRequestSchema, bridgeActiveClaimResultSchema, bridgeActiveHeartbeatRequestSchema, bridgeActiveHeartbeatResultSchema, bridgeActiveReleaseRequestSchema, bridgeActiveReleaseResultSchema, bridgeActiveReportRequestSchema, bridgeActiveReportResultSchema, bridgeActiveStateResultSchema, bridgeCurrentRequestSchema, bridgeCurrentResultSchema, bridgeStatusRequestSchema, bridgeStatusSchema, bridgeWaitRequestSchema, bridgeWaitResultSchema, computeExternalHandoffProjectKey, externalHandoffDescriptorSchema, resolveExternalHandoffRuntimeDirectory };
|
|
572
|
+
export { type BridgeActiveClaimResult, type BridgeActiveStateResult, type BridgeStatus, type BridgeWaitResult, EXTERNAL_HANDOFF_PROJECT_KEY_SALT, type ExternalHandoffDescriptor, SPOTPATCH_BRIDGE_PATHS, SPOTPATCH_BRIDGE_TOKEN_HEADER, assertPrivateExternalHandoffPath, bridgeAckRequestSchema, bridgeAckResultSchema, bridgeActiveClaimRequestSchema, bridgeActiveClaimResultSchema, bridgeActiveHeartbeatRequestSchema, bridgeActiveHeartbeatResultSchema, bridgeActiveReleaseRequestSchema, bridgeActiveReleaseResultSchema, bridgeActiveReportRequestSchema, bridgeActiveReportResultSchema, bridgeActiveStateResultSchema, bridgeCurrentRequestSchema, bridgeCurrentResultSchema, bridgeStatusRequestSchema, bridgeStatusSchema, bridgeWaitRequestSchema, bridgeWaitResultSchema, computeExternalHandoffProjectKey, externalHandoffDescriptorSchema, initializePrivateExternalHandoffFile, resolveExternalHandoffRuntimeDirectory };
|
|
@@ -1,24 +1,28 @@
|
|
|
1
1
|
import {
|
|
2
|
-
ERROR_CODES,
|
|
3
2
|
SpotPatchError,
|
|
4
3
|
activeAdapterSummarySchema,
|
|
5
4
|
dispatchSummarySchema,
|
|
6
5
|
externalHandoffReportableDispatchPhaseSchema,
|
|
7
6
|
externalHandoffSnapshotSchema,
|
|
8
7
|
externalHandoffSummarySchema
|
|
9
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-JTZFOTPT.js";
|
|
9
|
+
import {
|
|
10
|
+
ERROR_CODES
|
|
11
|
+
} from "./chunk-R6QJFNT2.js";
|
|
10
12
|
import {
|
|
11
13
|
EXTERNAL_HANDOFF_ACTIVE_ADAPTER_KINDS,
|
|
12
14
|
EXTERNAL_HANDOFF_BROKER_PROTOCOL_VERSION,
|
|
13
15
|
EXTERNAL_HANDOFF_FRAMEWORKS,
|
|
14
16
|
EXTERNAL_HANDOFF_LIMITS
|
|
15
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-IX6MSCK6.js";
|
|
16
18
|
|
|
17
19
|
// src/external-agent-node.ts
|
|
18
20
|
import { createHash } from "crypto";
|
|
21
|
+
import { execFile } from "child_process";
|
|
19
22
|
import { lstat, mkdir, realpath } from "fs/promises";
|
|
20
23
|
import os from "os";
|
|
21
24
|
import path from "path";
|
|
25
|
+
import { promisify } from "util";
|
|
22
26
|
import { z } from "zod";
|
|
23
27
|
var SPOTPATCH_BRIDGE_TOKEN_HEADER = "X-SpotPatch-Bridge-Token";
|
|
24
28
|
var SPOTPATCH_BRIDGE_PATHS = Object.freeze({
|
|
@@ -32,6 +36,75 @@ var SPOTPATCH_BRIDGE_PATHS = Object.freeze({
|
|
|
32
36
|
activeRelease: "/bridge/v1/active/release"
|
|
33
37
|
});
|
|
34
38
|
var EXTERNAL_HANDOFF_PROJECT_KEY_SALT = "spotpatch-external-agent-project-v1";
|
|
39
|
+
var execFileAsync = promisify(execFile);
|
|
40
|
+
var WINDOWS_ACL_SCRIPT = String.raw`
|
|
41
|
+
$ErrorActionPreference = 'Stop'
|
|
42
|
+
$target = $env:SPOTPATCH_ACL_TARGET
|
|
43
|
+
$kind = $env:SPOTPATCH_ACL_KIND
|
|
44
|
+
$operation = $env:SPOTPATCH_ACL_OPERATION
|
|
45
|
+
$identity = [System.Security.Principal.WindowsIdentity]::GetCurrent().User
|
|
46
|
+
$allowed = @($identity.Value, 'S-1-5-18', 'S-1-5-32-544')
|
|
47
|
+
if ($kind -eq 'directory') {
|
|
48
|
+
$item = [System.IO.DirectoryInfo]::new($target)
|
|
49
|
+
if ($operation -eq 'initialize') {
|
|
50
|
+
$security = [System.Security.AccessControl.DirectorySecurity]::new()
|
|
51
|
+
$security.SetOwner($identity)
|
|
52
|
+
foreach ($sidValue in $allowed) {
|
|
53
|
+
$sid = [System.Security.Principal.SecurityIdentifier]::new($sidValue)
|
|
54
|
+
$rule = [System.Security.AccessControl.FileSystemAccessRule]::new(
|
|
55
|
+
$sid,
|
|
56
|
+
[System.Security.AccessControl.FileSystemRights]::FullControl,
|
|
57
|
+
[System.Security.AccessControl.InheritanceFlags]'ContainerInherit, ObjectInherit',
|
|
58
|
+
[System.Security.AccessControl.PropagationFlags]::None,
|
|
59
|
+
[System.Security.AccessControl.AccessControlType]::Allow
|
|
60
|
+
)
|
|
61
|
+
[void]$security.AddAccessRule($rule)
|
|
62
|
+
}
|
|
63
|
+
$security.SetAccessRuleProtection($true, $false)
|
|
64
|
+
$item.SetAccessControl($security)
|
|
65
|
+
}
|
|
66
|
+
$acl = $item.GetAccessControl(
|
|
67
|
+
[System.Security.AccessControl.AccessControlSections]'Access, Owner'
|
|
68
|
+
)
|
|
69
|
+
} elseif ($kind -eq 'file') {
|
|
70
|
+
$item = [System.IO.FileInfo]::new($target)
|
|
71
|
+
if ($operation -eq 'initialize') {
|
|
72
|
+
$security = [System.Security.AccessControl.FileSecurity]::new()
|
|
73
|
+
$security.SetOwner($identity)
|
|
74
|
+
foreach ($sidValue in $allowed) {
|
|
75
|
+
$sid = [System.Security.Principal.SecurityIdentifier]::new($sidValue)
|
|
76
|
+
$rule = [System.Security.AccessControl.FileSystemAccessRule]::new(
|
|
77
|
+
$sid,
|
|
78
|
+
[System.Security.AccessControl.FileSystemRights]::FullControl,
|
|
79
|
+
[System.Security.AccessControl.AccessControlType]::Allow
|
|
80
|
+
)
|
|
81
|
+
[void]$security.AddAccessRule($rule)
|
|
82
|
+
}
|
|
83
|
+
$security.SetAccessRuleProtection($true, $false)
|
|
84
|
+
$item.SetAccessControl($security)
|
|
85
|
+
}
|
|
86
|
+
$acl = $item.GetAccessControl(
|
|
87
|
+
[System.Security.AccessControl.AccessControlSections]'Access, Owner'
|
|
88
|
+
)
|
|
89
|
+
} else {
|
|
90
|
+
exit 10
|
|
91
|
+
}
|
|
92
|
+
if ($acl.GetOwner([System.Security.Principal.SecurityIdentifier]).Value -ne $identity.Value) {
|
|
93
|
+
exit 11
|
|
94
|
+
}
|
|
95
|
+
foreach ($rule in $acl.GetAccessRules(
|
|
96
|
+
$true,
|
|
97
|
+
$true,
|
|
98
|
+
[System.Security.Principal.SecurityIdentifier]
|
|
99
|
+
)) {
|
|
100
|
+
if (
|
|
101
|
+
$rule.AccessControlType -eq [System.Security.AccessControl.AccessControlType]::Allow -and
|
|
102
|
+
$allowed -notcontains $rule.IdentityReference.Value
|
|
103
|
+
) {
|
|
104
|
+
exit 12
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
`;
|
|
35
108
|
var opaqueIdSchema = z.string().min(22).max(128).regex(/^[A-Za-z0-9_-]+$/u);
|
|
36
109
|
var projectKeySchema = z.string().length(64).regex(/^[a-f0-9]+$/u);
|
|
37
110
|
var loopbackEndpointSchema = z.url().refine((value) => {
|
|
@@ -111,46 +184,111 @@ var bridgeActiveStateResultSchema = z.strictObject({
|
|
|
111
184
|
var bridgeActiveHeartbeatResultSchema = bridgeActiveStateResultSchema;
|
|
112
185
|
var bridgeActiveReportResultSchema = bridgeActiveStateResultSchema;
|
|
113
186
|
var bridgeActiveReleaseResultSchema = bridgeActiveStateResultSchema;
|
|
114
|
-
function
|
|
115
|
-
const
|
|
116
|
-
if (
|
|
187
|
+
function windowsPowerShellExecutable() {
|
|
188
|
+
const systemRoot = process.env.SystemRoot ?? process.env.SYSTEMROOT;
|
|
189
|
+
if (systemRoot === void 0 || !path.win32.isAbsolute(systemRoot)) {
|
|
117
190
|
throw new SpotPatchError(ERROR_CODES.BRIDGE_UNAUTHORIZED);
|
|
118
191
|
}
|
|
119
|
-
return
|
|
192
|
+
return path.win32.join(
|
|
193
|
+
systemRoot,
|
|
194
|
+
"System32",
|
|
195
|
+
"WindowsPowerShell",
|
|
196
|
+
"v1.0",
|
|
197
|
+
"powershell.exe"
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
async function verifyWindowsAcl(candidate, kind, initialize) {
|
|
201
|
+
try {
|
|
202
|
+
await execFileAsync(
|
|
203
|
+
windowsPowerShellExecutable(),
|
|
204
|
+
["-NoLogo", "-NoProfile", "-NonInteractive", "-Command", WINDOWS_ACL_SCRIPT],
|
|
205
|
+
{
|
|
206
|
+
encoding: "utf8",
|
|
207
|
+
env: {
|
|
208
|
+
...process.env,
|
|
209
|
+
SPOTPATCH_ACL_KIND: kind,
|
|
210
|
+
SPOTPATCH_ACL_OPERATION: initialize ? "initialize" : "verify",
|
|
211
|
+
SPOTPATCH_ACL_TARGET: candidate
|
|
212
|
+
},
|
|
213
|
+
timeout: 1e4,
|
|
214
|
+
windowsHide: true
|
|
215
|
+
}
|
|
216
|
+
);
|
|
217
|
+
} catch (error) {
|
|
218
|
+
throw new SpotPatchError(ERROR_CODES.BRIDGE_UNAUTHORIZED, void 0, {
|
|
219
|
+
cause: error
|
|
220
|
+
});
|
|
221
|
+
}
|
|
120
222
|
}
|
|
121
|
-
async function
|
|
122
|
-
const status = await lstat(
|
|
123
|
-
|
|
223
|
+
async function assertPrivateExternalHandoffPath(candidate, kind) {
|
|
224
|
+
const status = await lstat(candidate);
|
|
225
|
+
const correctKind = kind === "directory" ? status.isDirectory() : status.isFile();
|
|
226
|
+
if (!correctKind || status.isSymbolicLink()) {
|
|
227
|
+
throw new SpotPatchError(ERROR_CODES.BRIDGE_UNAUTHORIZED);
|
|
228
|
+
}
|
|
229
|
+
if (process.platform === "win32") {
|
|
230
|
+
await verifyWindowsAcl(candidate, kind, false);
|
|
231
|
+
return status;
|
|
232
|
+
}
|
|
233
|
+
const uid = process.getuid?.();
|
|
234
|
+
if (uid === void 0 || status.uid !== uid || (status.mode & 63) !== 0) {
|
|
124
235
|
throw new SpotPatchError(ERROR_CODES.BRIDGE_UNAUTHORIZED);
|
|
125
236
|
}
|
|
237
|
+
return status;
|
|
238
|
+
}
|
|
239
|
+
async function initializePrivateExternalHandoffFile(candidate) {
|
|
240
|
+
if (process.platform === "win32") {
|
|
241
|
+
await verifyWindowsAcl(candidate, "file", true);
|
|
242
|
+
}
|
|
126
243
|
}
|
|
127
|
-
async function
|
|
244
|
+
async function initializeWindowsDirectory(directory) {
|
|
245
|
+
if (process.platform === "win32") {
|
|
246
|
+
await verifyWindowsAcl(directory, "directory", true);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
async function ensurePrivateSubdirectory(base, create) {
|
|
128
250
|
const directory = path.join(base, "spotpatch");
|
|
251
|
+
let created = false;
|
|
129
252
|
if (create) {
|
|
130
253
|
try {
|
|
131
254
|
await mkdir(directory, { mode: 448 });
|
|
255
|
+
created = true;
|
|
132
256
|
} catch (error) {
|
|
133
257
|
if (error.code !== "EEXIST") {
|
|
134
258
|
throw error;
|
|
135
259
|
}
|
|
136
260
|
}
|
|
137
261
|
}
|
|
138
|
-
await
|
|
139
|
-
|
|
262
|
+
if (created) await initializeWindowsDirectory(directory);
|
|
263
|
+
await assertPrivateExternalHandoffPath(directory, "directory");
|
|
264
|
+
return realpath(directory);
|
|
140
265
|
}
|
|
141
|
-
async function
|
|
142
|
-
|
|
266
|
+
async function resolveWindowsRuntimeDirectory(create) {
|
|
267
|
+
const configuredBase = process.env.LOCALAPPDATA;
|
|
268
|
+
if (configuredBase !== void 0 && !path.isAbsolute(configuredBase)) {
|
|
143
269
|
throw new SpotPatchError(ERROR_CODES.BRIDGE_UNAUTHORIZED);
|
|
144
270
|
}
|
|
145
|
-
const
|
|
271
|
+
const base = configuredBase ?? path.join(os.homedir(), "AppData", "Local");
|
|
272
|
+
const directory = path.join(base, "SpotPatch", "external-agent-runtime-v1");
|
|
273
|
+
let created = false;
|
|
274
|
+
if (create) {
|
|
275
|
+
created = await mkdir(directory, { mode: 448, recursive: true }) !== void 0;
|
|
276
|
+
}
|
|
277
|
+
if (created) await initializeWindowsDirectory(directory);
|
|
278
|
+
await assertPrivateExternalHandoffPath(directory, "directory");
|
|
279
|
+
return realpath(directory);
|
|
280
|
+
}
|
|
281
|
+
async function resolveExternalHandoffRuntimeDirectory(create) {
|
|
146
282
|
const xdgRuntimeDirectory = process.env.XDG_RUNTIME_DIR;
|
|
147
283
|
if (xdgRuntimeDirectory !== void 0 && !path.isAbsolute(xdgRuntimeDirectory)) {
|
|
148
284
|
throw new SpotPatchError(ERROR_CODES.BRIDGE_UNAUTHORIZED);
|
|
149
285
|
}
|
|
150
286
|
if (xdgRuntimeDirectory !== void 0) {
|
|
151
287
|
try {
|
|
152
|
-
|
|
153
|
-
|
|
288
|
+
if (process.platform !== "win32") {
|
|
289
|
+
await assertPrivateExternalHandoffPath(xdgRuntimeDirectory, "directory");
|
|
290
|
+
}
|
|
291
|
+
return await ensurePrivateSubdirectory(xdgRuntimeDirectory, create);
|
|
154
292
|
} catch (error) {
|
|
155
293
|
if (!create && error.code === "ENOENT") {
|
|
156
294
|
throw new SpotPatchError(ERROR_CODES.SESSION_NOT_FOUND);
|
|
@@ -158,6 +296,20 @@ async function resolveExternalHandoffRuntimeDirectory(create) {
|
|
|
158
296
|
throw error;
|
|
159
297
|
}
|
|
160
298
|
}
|
|
299
|
+
if (process.platform === "win32") {
|
|
300
|
+
try {
|
|
301
|
+
return await resolveWindowsRuntimeDirectory(create);
|
|
302
|
+
} catch (error) {
|
|
303
|
+
if (!create && error.code === "ENOENT") {
|
|
304
|
+
throw new SpotPatchError(ERROR_CODES.SESSION_NOT_FOUND);
|
|
305
|
+
}
|
|
306
|
+
throw error;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
const uid = process.getuid?.();
|
|
310
|
+
if (uid === void 0) {
|
|
311
|
+
throw new SpotPatchError(ERROR_CODES.BRIDGE_UNAUTHORIZED);
|
|
312
|
+
}
|
|
161
313
|
const fallback = path.join(os.tmpdir(), `spotpatch-${String(uid)}`);
|
|
162
314
|
if (create) {
|
|
163
315
|
try {
|
|
@@ -169,14 +321,14 @@ async function resolveExternalHandoffRuntimeDirectory(create) {
|
|
|
169
321
|
}
|
|
170
322
|
}
|
|
171
323
|
try {
|
|
172
|
-
await
|
|
324
|
+
await assertPrivateExternalHandoffPath(fallback, "directory");
|
|
173
325
|
} catch (error) {
|
|
174
326
|
if (!create && error.code === "ENOENT") {
|
|
175
327
|
throw new SpotPatchError(ERROR_CODES.SESSION_NOT_FOUND);
|
|
176
328
|
}
|
|
177
329
|
throw error;
|
|
178
330
|
}
|
|
179
|
-
return fallback;
|
|
331
|
+
return realpath(fallback);
|
|
180
332
|
}
|
|
181
333
|
async function computeExternalHandoffProjectKey(root) {
|
|
182
334
|
const canonicalRoot = await realpath(root);
|
|
@@ -186,6 +338,7 @@ export {
|
|
|
186
338
|
EXTERNAL_HANDOFF_PROJECT_KEY_SALT,
|
|
187
339
|
SPOTPATCH_BRIDGE_PATHS,
|
|
188
340
|
SPOTPATCH_BRIDGE_TOKEN_HEADER,
|
|
341
|
+
assertPrivateExternalHandoffPath,
|
|
189
342
|
bridgeAckRequestSchema,
|
|
190
343
|
bridgeAckResultSchema,
|
|
191
344
|
bridgeActiveClaimRequestSchema,
|
|
@@ -205,6 +358,7 @@ export {
|
|
|
205
358
|
bridgeWaitResultSchema,
|
|
206
359
|
computeExternalHandoffProjectKey,
|
|
207
360
|
externalHandoffDescriptorSchema,
|
|
361
|
+
initializePrivateExternalHandoffFile,
|
|
208
362
|
resolveExternalHandoffRuntimeDirectory
|
|
209
363
|
};
|
|
210
364
|
//# sourceMappingURL=external-agent-node.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/external-agent-node.ts"],"sourcesContent":["/// <reference types=\"node\" />\n\nimport { createHash } from \"node:crypto\";\nimport { lstat, mkdir, realpath } from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\n\nimport { z } from \"zod\";\n\nimport {\n EXTERNAL_HANDOFF_ACTIVE_ADAPTER_KINDS,\n EXTERNAL_HANDOFF_BROKER_PROTOCOL_VERSION,\n EXTERNAL_HANDOFF_FRAMEWORKS,\n EXTERNAL_HANDOFF_LIMITS,\n activeAdapterSummarySchema,\n dispatchSummarySchema,\n externalHandoffReportableDispatchPhaseSchema,\n externalHandoffSnapshotSchema,\n externalHandoffSummarySchema,\n type ActiveAdapterSummary,\n type DispatchSummary,\n type ExternalHandoffSnapshot,\n} from \"./protocol/external-handoff.js\";\nimport { ERROR_CODES } from \"./errors/error-code.js\";\nimport { SpotPatchError } from \"./errors/spotpatch-error.js\";\n\nexport const SPOTPATCH_BRIDGE_TOKEN_HEADER = \"X-SpotPatch-Bridge-Token\" as const;\nexport const SPOTPATCH_BRIDGE_PATHS = Object.freeze({\n status: \"/bridge/v1/status\",\n current: \"/bridge/v1/handoff/current\",\n wait: \"/bridge/v1/handoff/wait\",\n ack: \"/bridge/v1/handoff/ack\",\n activeClaim: \"/bridge/v1/active/claim\",\n activeHeartbeat: \"/bridge/v1/active/heartbeat\",\n activeReport: \"/bridge/v1/active/report\",\n activeRelease: \"/bridge/v1/active/release\",\n});\nexport const EXTERNAL_HANDOFF_PROJECT_KEY_SALT =\n \"spotpatch-external-agent-project-v1\" as const;\n\nconst opaqueIdSchema = z\n .string()\n .min(22)\n .max(128)\n .regex(/^[A-Za-z0-9_-]+$/u);\nconst projectKeySchema = z\n .string()\n .length(64)\n .regex(/^[a-f0-9]+$/u);\nconst loopbackEndpointSchema = z.url().refine((value) => {\n const match = /^http:\\/\\/127\\.0\\.0\\.1:([1-9][0-9]{0,4})$/u.exec(value);\n\n if (match?.[1] === undefined) {\n return false;\n }\n\n const port = Number(match[1]);\n return Number.isSafeInteger(port) && port <= 65_535;\n});\n\nexport const externalHandoffDescriptorSchema = z.strictObject({\n schemaVersion: z.literal(1),\n brokerProtocolVersion: z.literal(EXTERNAL_HANDOFF_BROKER_PROTOCOL_VERSION),\n projectKey: projectKeySchema,\n sessionId: opaqueIdSchema,\n framework: z.enum(EXTERNAL_HANDOFF_FRAMEWORKS),\n endpoint: loopbackEndpointSchema,\n bridgeToken: z\n .string()\n .min(43)\n .max(128)\n .regex(/^[A-Za-z0-9_-]+$/u),\n pid: z.number().int().positive(),\n createdAt: z.iso.datetime(),\n});\n\nexport const bridgeStatusRequestSchema = z.strictObject({});\nexport const bridgeCurrentRequestSchema = z.strictObject({\n cursor: opaqueIdSchema.optional(),\n});\nexport const bridgeWaitRequestSchema = z.strictObject({\n afterCursor: opaqueIdSchema.optional(),\n timeoutMs: z\n .number()\n .int()\n .positive()\n .max(EXTERNAL_HANDOFF_LIMITS.maximumWaitMs)\n .default(EXTERNAL_HANDOFF_LIMITS.defaultWaitMs),\n});\nexport const bridgeAckRequestSchema = z.strictObject({\n cursor: opaqueIdSchema,\n connectorInstanceId: opaqueIdSchema,\n});\nexport const bridgeActiveClaimRequestSchema = z.strictObject({\n adapterKind: z.enum(EXTERNAL_HANDOFF_ACTIVE_ADAPTER_KINDS),\n connectorInstanceId: opaqueIdSchema,\n});\nexport const bridgeActiveHeartbeatRequestSchema = z.strictObject({\n leaseToken: opaqueIdSchema,\n});\nexport const bridgeActiveReportRequestSchema = z.strictObject({\n leaseToken: opaqueIdSchema,\n cursor: opaqueIdSchema,\n phase: externalHandoffReportableDispatchPhaseSchema,\n});\nexport const bridgeActiveReleaseRequestSchema = z.strictObject({\n leaseToken: opaqueIdSchema,\n});\nexport const bridgeStatusSchema = z.strictObject({\n brokerProtocolVersion: z.literal(EXTERNAL_HANDOFF_BROKER_PROTOCOL_VERSION),\n projectKey: projectKeySchema,\n sessionId: opaqueIdSchema,\n framework: z.enum(EXTERNAL_HANDOFF_FRAMEWORKS),\n current: externalHandoffSummarySchema.nullable(),\n});\nexport const bridgeCurrentResultSchema = z.strictObject({\n outcome: z.literal(\"handoff\"),\n snapshot: externalHandoffSnapshotSchema,\n});\nexport const bridgeWaitResultSchema = z.discriminatedUnion(\"outcome\", [\n bridgeCurrentResultSchema,\n z.strictObject({ outcome: z.literal(\"timeout\") }),\n]);\nexport const bridgeAckResultSchema = z.strictObject({\n summary: externalHandoffSummarySchema,\n});\nexport const bridgeActiveClaimResultSchema = z.strictObject({\n leaseToken: opaqueIdSchema,\n heartbeatIntervalMs: z.literal(EXTERNAL_HANDOFF_LIMITS.activeHeartbeatIntervalMs),\n baselineCursor: opaqueIdSchema.nullable(),\n activeAdapter: activeAdapterSummarySchema,\n});\nexport const bridgeActiveStateResultSchema = z.strictObject({\n activeAdapter: activeAdapterSummarySchema.nullable(),\n dispatch: dispatchSummarySchema.nullable(),\n});\nexport const bridgeActiveHeartbeatResultSchema = bridgeActiveStateResultSchema;\nexport const bridgeActiveReportResultSchema = bridgeActiveStateResultSchema;\nexport const bridgeActiveReleaseResultSchema = bridgeActiveStateResultSchema;\n\nexport type ExternalHandoffDescriptor = z.infer<typeof externalHandoffDescriptorSchema>;\nexport type BridgeStatus = z.infer<typeof bridgeStatusSchema>;\nexport type BridgeWaitResult =\n | Readonly<{ outcome: \"handoff\"; snapshot: ExternalHandoffSnapshot }>\n | Readonly<{ outcome: \"timeout\" }>;\nexport interface BridgeActiveClaimResult {\n readonly leaseToken: string;\n readonly heartbeatIntervalMs: typeof EXTERNAL_HANDOFF_LIMITS.activeHeartbeatIntervalMs;\n readonly baselineCursor: string | null;\n readonly activeAdapter: ActiveAdapterSummary;\n}\nexport interface BridgeActiveStateResult {\n readonly activeAdapter: ActiveAdapterSummary | null;\n readonly dispatch: DispatchSummary | null;\n}\n\nfunction currentUid(): number {\n const uid = process.getuid?.();\n\n if (uid === undefined) {\n throw new SpotPatchError(ERROR_CODES.BRIDGE_UNAUTHORIZED);\n }\n\n return uid;\n}\n\nasync function assertPrivateDirectory(directory: string, uid: number): Promise<void> {\n const status = await lstat(directory);\n\n if (\n !status.isDirectory() ||\n status.isSymbolicLink() ||\n status.uid !== uid ||\n (status.mode & 0o077) !== 0\n ) {\n throw new SpotPatchError(ERROR_CODES.BRIDGE_UNAUTHORIZED);\n }\n}\n\nasync function ensurePrivateSubdirectory(\n base: string,\n uid: number,\n create: boolean,\n): Promise<string> {\n const directory = path.join(base, \"spotpatch\");\n\n if (create) {\n try {\n await mkdir(directory, { mode: 0o700 });\n } catch (error: unknown) {\n if ((error as NodeJS.ErrnoException).code !== \"EEXIST\") {\n throw error;\n }\n }\n }\n\n await assertPrivateDirectory(directory, uid);\n return directory;\n}\n\nexport async function resolveExternalHandoffRuntimeDirectory(\n create: boolean,\n): Promise<string> {\n if (process.platform === \"win32\") {\n throw new SpotPatchError(ERROR_CODES.BRIDGE_UNAUTHORIZED);\n }\n\n const uid = currentUid();\n const xdgRuntimeDirectory = process.env.XDG_RUNTIME_DIR;\n\n if (xdgRuntimeDirectory !== undefined && !path.isAbsolute(xdgRuntimeDirectory)) {\n throw new SpotPatchError(ERROR_CODES.BRIDGE_UNAUTHORIZED);\n }\n\n if (xdgRuntimeDirectory !== undefined) {\n try {\n await assertPrivateDirectory(xdgRuntimeDirectory, uid);\n return await ensurePrivateSubdirectory(xdgRuntimeDirectory, uid, create);\n } catch (error: unknown) {\n if (!create && (error as NodeJS.ErrnoException).code === \"ENOENT\") {\n throw new SpotPatchError(ERROR_CODES.SESSION_NOT_FOUND);\n }\n\n throw error;\n }\n }\n\n const fallback = path.join(os.tmpdir(), `spotpatch-${String(uid)}`);\n\n if (create) {\n try {\n await mkdir(fallback, { mode: 0o700 });\n } catch (error: unknown) {\n if ((error as NodeJS.ErrnoException).code !== \"EEXIST\") {\n throw error;\n }\n }\n }\n\n try {\n await assertPrivateDirectory(fallback, uid);\n } catch (error: unknown) {\n if (!create && (error as NodeJS.ErrnoException).code === \"ENOENT\") {\n throw new SpotPatchError(ERROR_CODES.SESSION_NOT_FOUND);\n }\n\n throw error;\n }\n\n return fallback;\n}\n\nexport async function computeExternalHandoffProjectKey(root: string): Promise<string> {\n const canonicalRoot = await realpath(root);\n return createHash(\"sha256\")\n .update(`${EXTERNAL_HANDOFF_PROJECT_KEY_SALT}\\0${canonicalRoot}`)\n .digest(\"hex\");\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/external-agent-node.ts"],"sourcesContent":["/// <reference types=\"node\" />\n\nimport { createHash } from \"node:crypto\";\nimport { execFile } from \"node:child_process\";\nimport type { Stats } from \"node:fs\";\nimport { lstat, mkdir, realpath } from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { promisify } from \"node:util\";\n\nimport { z } from \"zod\";\n\nimport {\n EXTERNAL_HANDOFF_ACTIVE_ADAPTER_KINDS,\n EXTERNAL_HANDOFF_BROKER_PROTOCOL_VERSION,\n EXTERNAL_HANDOFF_FRAMEWORKS,\n EXTERNAL_HANDOFF_LIMITS,\n activeAdapterSummarySchema,\n dispatchSummarySchema,\n externalHandoffReportableDispatchPhaseSchema,\n externalHandoffSnapshotSchema,\n externalHandoffSummarySchema,\n type ActiveAdapterSummary,\n type DispatchSummary,\n type ExternalHandoffSnapshot,\n} from \"./protocol/external-handoff.js\";\nimport { ERROR_CODES } from \"./errors/error-code.js\";\nimport { SpotPatchError } from \"./errors/spotpatch-error.js\";\n\nexport const SPOTPATCH_BRIDGE_TOKEN_HEADER = \"X-SpotPatch-Bridge-Token\" as const;\nexport const SPOTPATCH_BRIDGE_PATHS = Object.freeze({\n status: \"/bridge/v1/status\",\n current: \"/bridge/v1/handoff/current\",\n wait: \"/bridge/v1/handoff/wait\",\n ack: \"/bridge/v1/handoff/ack\",\n activeClaim: \"/bridge/v1/active/claim\",\n activeHeartbeat: \"/bridge/v1/active/heartbeat\",\n activeReport: \"/bridge/v1/active/report\",\n activeRelease: \"/bridge/v1/active/release\",\n});\nexport const EXTERNAL_HANDOFF_PROJECT_KEY_SALT =\n \"spotpatch-external-agent-project-v1\" as const;\n\nconst execFileAsync = promisify(execFile);\nconst WINDOWS_ACL_SCRIPT = String.raw`\n$ErrorActionPreference = 'Stop'\n$target = $env:SPOTPATCH_ACL_TARGET\n$kind = $env:SPOTPATCH_ACL_KIND\n$operation = $env:SPOTPATCH_ACL_OPERATION\n$identity = [System.Security.Principal.WindowsIdentity]::GetCurrent().User\n$allowed = @($identity.Value, 'S-1-5-18', 'S-1-5-32-544')\nif ($kind -eq 'directory') {\n $item = [System.IO.DirectoryInfo]::new($target)\n if ($operation -eq 'initialize') {\n $security = [System.Security.AccessControl.DirectorySecurity]::new()\n $security.SetOwner($identity)\n foreach ($sidValue in $allowed) {\n $sid = [System.Security.Principal.SecurityIdentifier]::new($sidValue)\n $rule = [System.Security.AccessControl.FileSystemAccessRule]::new(\n $sid,\n [System.Security.AccessControl.FileSystemRights]::FullControl,\n [System.Security.AccessControl.InheritanceFlags]'ContainerInherit, ObjectInherit',\n [System.Security.AccessControl.PropagationFlags]::None,\n [System.Security.AccessControl.AccessControlType]::Allow\n )\n [void]$security.AddAccessRule($rule)\n }\n $security.SetAccessRuleProtection($true, $false)\n $item.SetAccessControl($security)\n }\n $acl = $item.GetAccessControl(\n [System.Security.AccessControl.AccessControlSections]'Access, Owner'\n )\n} elseif ($kind -eq 'file') {\n $item = [System.IO.FileInfo]::new($target)\n if ($operation -eq 'initialize') {\n $security = [System.Security.AccessControl.FileSecurity]::new()\n $security.SetOwner($identity)\n foreach ($sidValue in $allowed) {\n $sid = [System.Security.Principal.SecurityIdentifier]::new($sidValue)\n $rule = [System.Security.AccessControl.FileSystemAccessRule]::new(\n $sid,\n [System.Security.AccessControl.FileSystemRights]::FullControl,\n [System.Security.AccessControl.AccessControlType]::Allow\n )\n [void]$security.AddAccessRule($rule)\n }\n $security.SetAccessRuleProtection($true, $false)\n $item.SetAccessControl($security)\n }\n $acl = $item.GetAccessControl(\n [System.Security.AccessControl.AccessControlSections]'Access, Owner'\n )\n} else {\n exit 10\n}\nif ($acl.GetOwner([System.Security.Principal.SecurityIdentifier]).Value -ne $identity.Value) {\n exit 11\n}\nforeach ($rule in $acl.GetAccessRules(\n $true,\n $true,\n [System.Security.Principal.SecurityIdentifier]\n)) {\n if (\n $rule.AccessControlType -eq [System.Security.AccessControl.AccessControlType]::Allow -and\n $allowed -notcontains $rule.IdentityReference.Value\n ) {\n exit 12\n }\n}\n`;\n\nconst opaqueIdSchema = z\n .string()\n .min(22)\n .max(128)\n .regex(/^[A-Za-z0-9_-]+$/u);\nconst projectKeySchema = z\n .string()\n .length(64)\n .regex(/^[a-f0-9]+$/u);\nconst loopbackEndpointSchema = z.url().refine((value) => {\n const match = /^http:\\/\\/127\\.0\\.0\\.1:([1-9][0-9]{0,4})$/u.exec(value);\n\n if (match?.[1] === undefined) {\n return false;\n }\n\n const port = Number(match[1]);\n return Number.isSafeInteger(port) && port <= 65_535;\n});\n\nexport const externalHandoffDescriptorSchema = z.strictObject({\n schemaVersion: z.literal(1),\n brokerProtocolVersion: z.literal(EXTERNAL_HANDOFF_BROKER_PROTOCOL_VERSION),\n projectKey: projectKeySchema,\n sessionId: opaqueIdSchema,\n framework: z.enum(EXTERNAL_HANDOFF_FRAMEWORKS),\n endpoint: loopbackEndpointSchema,\n bridgeToken: z\n .string()\n .min(43)\n .max(128)\n .regex(/^[A-Za-z0-9_-]+$/u),\n pid: z.number().int().positive(),\n createdAt: z.iso.datetime(),\n});\n\nexport const bridgeStatusRequestSchema = z.strictObject({});\nexport const bridgeCurrentRequestSchema = z.strictObject({\n cursor: opaqueIdSchema.optional(),\n});\nexport const bridgeWaitRequestSchema = z.strictObject({\n afterCursor: opaqueIdSchema.optional(),\n timeoutMs: z\n .number()\n .int()\n .positive()\n .max(EXTERNAL_HANDOFF_LIMITS.maximumWaitMs)\n .default(EXTERNAL_HANDOFF_LIMITS.defaultWaitMs),\n});\nexport const bridgeAckRequestSchema = z.strictObject({\n cursor: opaqueIdSchema,\n connectorInstanceId: opaqueIdSchema,\n});\nexport const bridgeActiveClaimRequestSchema = z.strictObject({\n adapterKind: z.enum(EXTERNAL_HANDOFF_ACTIVE_ADAPTER_KINDS),\n connectorInstanceId: opaqueIdSchema,\n});\nexport const bridgeActiveHeartbeatRequestSchema = z.strictObject({\n leaseToken: opaqueIdSchema,\n});\nexport const bridgeActiveReportRequestSchema = z.strictObject({\n leaseToken: opaqueIdSchema,\n cursor: opaqueIdSchema,\n phase: externalHandoffReportableDispatchPhaseSchema,\n});\nexport const bridgeActiveReleaseRequestSchema = z.strictObject({\n leaseToken: opaqueIdSchema,\n});\nexport const bridgeStatusSchema = z.strictObject({\n brokerProtocolVersion: z.literal(EXTERNAL_HANDOFF_BROKER_PROTOCOL_VERSION),\n projectKey: projectKeySchema,\n sessionId: opaqueIdSchema,\n framework: z.enum(EXTERNAL_HANDOFF_FRAMEWORKS),\n current: externalHandoffSummarySchema.nullable(),\n});\nexport const bridgeCurrentResultSchema = z.strictObject({\n outcome: z.literal(\"handoff\"),\n snapshot: externalHandoffSnapshotSchema,\n});\nexport const bridgeWaitResultSchema = z.discriminatedUnion(\"outcome\", [\n bridgeCurrentResultSchema,\n z.strictObject({ outcome: z.literal(\"timeout\") }),\n]);\nexport const bridgeAckResultSchema = z.strictObject({\n summary: externalHandoffSummarySchema,\n});\nexport const bridgeActiveClaimResultSchema = z.strictObject({\n leaseToken: opaqueIdSchema,\n heartbeatIntervalMs: z.literal(EXTERNAL_HANDOFF_LIMITS.activeHeartbeatIntervalMs),\n baselineCursor: opaqueIdSchema.nullable(),\n activeAdapter: activeAdapterSummarySchema,\n});\nexport const bridgeActiveStateResultSchema = z.strictObject({\n activeAdapter: activeAdapterSummarySchema.nullable(),\n dispatch: dispatchSummarySchema.nullable(),\n});\nexport const bridgeActiveHeartbeatResultSchema = bridgeActiveStateResultSchema;\nexport const bridgeActiveReportResultSchema = bridgeActiveStateResultSchema;\nexport const bridgeActiveReleaseResultSchema = bridgeActiveStateResultSchema;\n\nexport type ExternalHandoffDescriptor = z.infer<typeof externalHandoffDescriptorSchema>;\nexport type BridgeStatus = z.infer<typeof bridgeStatusSchema>;\nexport type BridgeWaitResult =\n | Readonly<{ outcome: \"handoff\"; snapshot: ExternalHandoffSnapshot }>\n | Readonly<{ outcome: \"timeout\" }>;\nexport interface BridgeActiveClaimResult {\n readonly leaseToken: string;\n readonly heartbeatIntervalMs: typeof EXTERNAL_HANDOFF_LIMITS.activeHeartbeatIntervalMs;\n readonly baselineCursor: string | null;\n readonly activeAdapter: ActiveAdapterSummary;\n}\nexport interface BridgeActiveStateResult {\n readonly activeAdapter: ActiveAdapterSummary | null;\n readonly dispatch: DispatchSummary | null;\n}\n\nfunction windowsPowerShellExecutable(): string {\n const systemRoot = process.env.SystemRoot ?? process.env.SYSTEMROOT;\n if (systemRoot === undefined || !path.win32.isAbsolute(systemRoot)) {\n throw new SpotPatchError(ERROR_CODES.BRIDGE_UNAUTHORIZED);\n }\n return path.win32.join(\n systemRoot,\n \"System32\",\n \"WindowsPowerShell\",\n \"v1.0\",\n \"powershell.exe\",\n );\n}\n\nasync function verifyWindowsAcl(\n candidate: string,\n kind: \"directory\" | \"file\",\n initialize: boolean,\n): Promise<void> {\n try {\n await execFileAsync(\n windowsPowerShellExecutable(),\n [\"-NoLogo\", \"-NoProfile\", \"-NonInteractive\", \"-Command\", WINDOWS_ACL_SCRIPT],\n {\n encoding: \"utf8\",\n env: {\n ...process.env,\n SPOTPATCH_ACL_KIND: kind,\n SPOTPATCH_ACL_OPERATION: initialize ? \"initialize\" : \"verify\",\n SPOTPATCH_ACL_TARGET: candidate,\n },\n timeout: 10_000,\n windowsHide: true,\n },\n );\n } catch (error: unknown) {\n throw new SpotPatchError(ERROR_CODES.BRIDGE_UNAUTHORIZED, undefined, {\n cause: error,\n });\n }\n}\n\nexport async function assertPrivateExternalHandoffPath(\n candidate: string,\n kind: \"directory\" | \"file\",\n): Promise<Stats> {\n const status = await lstat(candidate);\n const correctKind = kind === \"directory\" ? status.isDirectory() : status.isFile();\n\n if (!correctKind || status.isSymbolicLink()) {\n throw new SpotPatchError(ERROR_CODES.BRIDGE_UNAUTHORIZED);\n }\n\n if (process.platform === \"win32\") {\n await verifyWindowsAcl(candidate, kind, false);\n return status;\n }\n\n const uid = process.getuid?.();\n if (uid === undefined || status.uid !== uid || (status.mode & 0o077) !== 0) {\n throw new SpotPatchError(ERROR_CODES.BRIDGE_UNAUTHORIZED);\n }\n\n return status;\n}\n\nexport async function initializePrivateExternalHandoffFile(\n candidate: string,\n): Promise<void> {\n if (process.platform === \"win32\") {\n await verifyWindowsAcl(candidate, \"file\", true);\n }\n}\n\nasync function initializeWindowsDirectory(directory: string): Promise<void> {\n if (process.platform === \"win32\") {\n await verifyWindowsAcl(directory, \"directory\", true);\n }\n}\n\nasync function ensurePrivateSubdirectory(\n base: string,\n create: boolean,\n): Promise<string> {\n const directory = path.join(base, \"spotpatch\");\n let created = false;\n\n if (create) {\n try {\n await mkdir(directory, { mode: 0o700 });\n created = true;\n } catch (error: unknown) {\n if ((error as NodeJS.ErrnoException).code !== \"EEXIST\") {\n throw error;\n }\n }\n }\n\n if (created) await initializeWindowsDirectory(directory);\n await assertPrivateExternalHandoffPath(directory, \"directory\");\n return realpath(directory);\n}\n\nasync function resolveWindowsRuntimeDirectory(create: boolean): Promise<string> {\n const configuredBase = process.env.LOCALAPPDATA;\n\n if (configuredBase !== undefined && !path.isAbsolute(configuredBase)) {\n throw new SpotPatchError(ERROR_CODES.BRIDGE_UNAUTHORIZED);\n }\n\n const base = configuredBase ?? path.join(os.homedir(), \"AppData\", \"Local\");\n const directory = path.join(base, \"SpotPatch\", \"external-agent-runtime-v1\");\n let created = false;\n\n if (create) {\n created = (await mkdir(directory, { mode: 0o700, recursive: true })) !== undefined;\n }\n\n if (created) await initializeWindowsDirectory(directory);\n await assertPrivateExternalHandoffPath(directory, \"directory\");\n return realpath(directory);\n}\n\nexport async function resolveExternalHandoffRuntimeDirectory(\n create: boolean,\n): Promise<string> {\n const xdgRuntimeDirectory = process.env.XDG_RUNTIME_DIR;\n\n if (xdgRuntimeDirectory !== undefined && !path.isAbsolute(xdgRuntimeDirectory)) {\n throw new SpotPatchError(ERROR_CODES.BRIDGE_UNAUTHORIZED);\n }\n\n if (xdgRuntimeDirectory !== undefined) {\n try {\n if (process.platform !== \"win32\") {\n await assertPrivateExternalHandoffPath(xdgRuntimeDirectory, \"directory\");\n }\n return await ensurePrivateSubdirectory(xdgRuntimeDirectory, create);\n } catch (error: unknown) {\n if (!create && (error as NodeJS.ErrnoException).code === \"ENOENT\") {\n throw new SpotPatchError(ERROR_CODES.SESSION_NOT_FOUND);\n }\n\n throw error;\n }\n }\n\n if (process.platform === \"win32\") {\n try {\n return await resolveWindowsRuntimeDirectory(create);\n } catch (error: unknown) {\n if (!create && (error as NodeJS.ErrnoException).code === \"ENOENT\") {\n throw new SpotPatchError(ERROR_CODES.SESSION_NOT_FOUND);\n }\n\n throw error;\n }\n }\n\n const uid = process.getuid?.();\n if (uid === undefined) {\n throw new SpotPatchError(ERROR_CODES.BRIDGE_UNAUTHORIZED);\n }\n\n const fallback = path.join(os.tmpdir(), `spotpatch-${String(uid)}`);\n\n if (create) {\n try {\n await mkdir(fallback, { mode: 0o700 });\n } catch (error: unknown) {\n if ((error as NodeJS.ErrnoException).code !== \"EEXIST\") {\n throw error;\n }\n }\n }\n\n try {\n await assertPrivateExternalHandoffPath(fallback, \"directory\");\n } catch (error: unknown) {\n if (!create && (error as NodeJS.ErrnoException).code === \"ENOENT\") {\n throw new SpotPatchError(ERROR_CODES.SESSION_NOT_FOUND);\n }\n\n throw error;\n }\n\n return realpath(fallback);\n}\n\nexport async function computeExternalHandoffProjectKey(root: string): Promise<string> {\n const canonicalRoot = await realpath(root);\n return createHash(\"sha256\")\n .update(`${EXTERNAL_HANDOFF_PROJECT_KEY_SALT}\\0${canonicalRoot}`)\n .digest(\"hex\");\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAEA,SAAS,kBAAkB;AAC3B,SAAS,gBAAgB;AAEzB,SAAS,OAAO,OAAO,gBAAgB;AACvC,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,SAAS,iBAAiB;AAE1B,SAAS,SAAS;AAmBX,IAAM,gCAAgC;AACtC,IAAM,yBAAyB,OAAO,OAAO;AAAA,EAClD,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,MAAM;AAAA,EACN,KAAK;AAAA,EACL,aAAa;AAAA,EACb,iBAAiB;AAAA,EACjB,cAAc;AAAA,EACd,eAAe;AACjB,CAAC;AACM,IAAM,oCACX;AAEF,IAAM,gBAAgB,UAAU,QAAQ;AACxC,IAAM,qBAAqB,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAqElC,IAAM,iBAAiB,EACpB,OAAO,EACP,IAAI,EAAE,EACN,IAAI,GAAG,EACP,MAAM,mBAAmB;AAC5B,IAAM,mBAAmB,EACtB,OAAO,EACP,OAAO,EAAE,EACT,MAAM,cAAc;AACvB,IAAM,yBAAyB,EAAE,IAAI,EAAE,OAAO,CAAC,UAAU;AACvD,QAAM,QAAQ,6CAA6C,KAAK,KAAK;AAErE,MAAI,QAAQ,CAAC,MAAM,QAAW;AAC5B,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,OAAO,MAAM,CAAC,CAAC;AAC5B,SAAO,OAAO,cAAc,IAAI,KAAK,QAAQ;AAC/C,CAAC;AAEM,IAAM,kCAAkC,EAAE,aAAa;AAAA,EAC5D,eAAe,EAAE,QAAQ,CAAC;AAAA,EAC1B,uBAAuB,EAAE,QAAQ,wCAAwC;AAAA,EACzE,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,WAAW,EAAE,KAAK,2BAA2B;AAAA,EAC7C,UAAU;AAAA,EACV,aAAa,EACV,OAAO,EACP,IAAI,EAAE,EACN,IAAI,GAAG,EACP,MAAM,mBAAmB;AAAA,EAC5B,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,EAC/B,WAAW,EAAE,IAAI,SAAS;AAC5B,CAAC;AAEM,IAAM,4BAA4B,EAAE,aAAa,CAAC,CAAC;AACnD,IAAM,6BAA6B,EAAE,aAAa;AAAA,EACvD,QAAQ,eAAe,SAAS;AAClC,CAAC;AACM,IAAM,0BAA0B,EAAE,aAAa;AAAA,EACpD,aAAa,eAAe,SAAS;AAAA,EACrC,WAAW,EACR,OAAO,EACP,IAAI,EACJ,SAAS,EACT,IAAI,wBAAwB,aAAa,EACzC,QAAQ,wBAAwB,aAAa;AAClD,CAAC;AACM,IAAM,yBAAyB,EAAE,aAAa;AAAA,EACnD,QAAQ;AAAA,EACR,qBAAqB;AACvB,CAAC;AACM,IAAM,iCAAiC,EAAE,aAAa;AAAA,EAC3D,aAAa,EAAE,KAAK,qCAAqC;AAAA,EACzD,qBAAqB;AACvB,CAAC;AACM,IAAM,qCAAqC,EAAE,aAAa;AAAA,EAC/D,YAAY;AACd,CAAC;AACM,IAAM,kCAAkC,EAAE,aAAa;AAAA,EAC5D,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,OAAO;AACT,CAAC;AACM,IAAM,mCAAmC,EAAE,aAAa;AAAA,EAC7D,YAAY;AACd,CAAC;AACM,IAAM,qBAAqB,EAAE,aAAa;AAAA,EAC/C,uBAAuB,EAAE,QAAQ,wCAAwC;AAAA,EACzE,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,WAAW,EAAE,KAAK,2BAA2B;AAAA,EAC7C,SAAS,6BAA6B,SAAS;AACjD,CAAC;AACM,IAAM,4BAA4B,EAAE,aAAa;AAAA,EACtD,SAAS,EAAE,QAAQ,SAAS;AAAA,EAC5B,UAAU;AACZ,CAAC;AACM,IAAM,yBAAyB,EAAE,mBAAmB,WAAW;AAAA,EACpE;AAAA,EACA,EAAE,aAAa,EAAE,SAAS,EAAE,QAAQ,SAAS,EAAE,CAAC;AAClD,CAAC;AACM,IAAM,wBAAwB,EAAE,aAAa;AAAA,EAClD,SAAS;AACX,CAAC;AACM,IAAM,gCAAgC,EAAE,aAAa;AAAA,EAC1D,YAAY;AAAA,EACZ,qBAAqB,EAAE,QAAQ,wBAAwB,yBAAyB;AAAA,EAChF,gBAAgB,eAAe,SAAS;AAAA,EACxC,eAAe;AACjB,CAAC;AACM,IAAM,gCAAgC,EAAE,aAAa;AAAA,EAC1D,eAAe,2BAA2B,SAAS;AAAA,EACnD,UAAU,sBAAsB,SAAS;AAC3C,CAAC;AACM,IAAM,oCAAoC;AAC1C,IAAM,iCAAiC;AACvC,IAAM,kCAAkC;AAkB/C,SAAS,8BAAsC;AAC7C,QAAM,aAAa,QAAQ,IAAI,cAAc,QAAQ,IAAI;AACzD,MAAI,eAAe,UAAa,CAAC,KAAK,MAAM,WAAW,UAAU,GAAG;AAClE,UAAM,IAAI,eAAe,YAAY,mBAAmB;AAAA,EAC1D;AACA,SAAO,KAAK,MAAM;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,eAAe,iBACb,WACA,MACA,YACe;AACf,MAAI;AACF,UAAM;AAAA,MACJ,4BAA4B;AAAA,MAC5B,CAAC,WAAW,cAAc,mBAAmB,YAAY,kBAAkB;AAAA,MAC3E;AAAA,QACE,UAAU;AAAA,QACV,KAAK;AAAA,UACH,GAAG,QAAQ;AAAA,UACX,oBAAoB;AAAA,UACpB,yBAAyB,aAAa,eAAe;AAAA,UACrD,sBAAsB;AAAA,QACxB;AAAA,QACA,SAAS;AAAA,QACT,aAAa;AAAA,MACf;AAAA,IACF;AAAA,EACF,SAAS,OAAgB;AACvB,UAAM,IAAI,eAAe,YAAY,qBAAqB,QAAW;AAAA,MACnE,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AACF;AAEA,eAAsB,iCACpB,WACA,MACgB;AAChB,QAAM,SAAS,MAAM,MAAM,SAAS;AACpC,QAAM,cAAc,SAAS,cAAc,OAAO,YAAY,IAAI,OAAO,OAAO;AAEhF,MAAI,CAAC,eAAe,OAAO,eAAe,GAAG;AAC3C,UAAM,IAAI,eAAe,YAAY,mBAAmB;AAAA,EAC1D;AAEA,MAAI,QAAQ,aAAa,SAAS;AAChC,UAAM,iBAAiB,WAAW,MAAM,KAAK;AAC7C,WAAO;AAAA,EACT;AAEA,QAAM,MAAM,QAAQ,SAAS;AAC7B,MAAI,QAAQ,UAAa,OAAO,QAAQ,QAAQ,OAAO,OAAO,QAAW,GAAG;AAC1E,UAAM,IAAI,eAAe,YAAY,mBAAmB;AAAA,EAC1D;AAEA,SAAO;AACT;AAEA,eAAsB,qCACpB,WACe;AACf,MAAI,QAAQ,aAAa,SAAS;AAChC,UAAM,iBAAiB,WAAW,QAAQ,IAAI;AAAA,EAChD;AACF;AAEA,eAAe,2BAA2B,WAAkC;AAC1E,MAAI,QAAQ,aAAa,SAAS;AAChC,UAAM,iBAAiB,WAAW,aAAa,IAAI;AAAA,EACrD;AACF;AAEA,eAAe,0BACb,MACA,QACiB;AACjB,QAAM,YAAY,KAAK,KAAK,MAAM,WAAW;AAC7C,MAAI,UAAU;AAEd,MAAI,QAAQ;AACV,QAAI;AACF,YAAM,MAAM,WAAW,EAAE,MAAM,IAAM,CAAC;AACtC,gBAAU;AAAA,IACZ,SAAS,OAAgB;AACvB,UAAK,MAAgC,SAAS,UAAU;AACtD,cAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,MAAI,QAAS,OAAM,2BAA2B,SAAS;AACvD,QAAM,iCAAiC,WAAW,WAAW;AAC7D,SAAO,SAAS,SAAS;AAC3B;AAEA,eAAe,+BAA+B,QAAkC;AAC9E,QAAM,iBAAiB,QAAQ,IAAI;AAEnC,MAAI,mBAAmB,UAAa,CAAC,KAAK,WAAW,cAAc,GAAG;AACpE,UAAM,IAAI,eAAe,YAAY,mBAAmB;AAAA,EAC1D;AAEA,QAAM,OAAO,kBAAkB,KAAK,KAAK,GAAG,QAAQ,GAAG,WAAW,OAAO;AACzE,QAAM,YAAY,KAAK,KAAK,MAAM,aAAa,2BAA2B;AAC1E,MAAI,UAAU;AAEd,MAAI,QAAQ;AACV,cAAW,MAAM,MAAM,WAAW,EAAE,MAAM,KAAO,WAAW,KAAK,CAAC,MAAO;AAAA,EAC3E;AAEA,MAAI,QAAS,OAAM,2BAA2B,SAAS;AACvD,QAAM,iCAAiC,WAAW,WAAW;AAC7D,SAAO,SAAS,SAAS;AAC3B;AAEA,eAAsB,uCACpB,QACiB;AACjB,QAAM,sBAAsB,QAAQ,IAAI;AAExC,MAAI,wBAAwB,UAAa,CAAC,KAAK,WAAW,mBAAmB,GAAG;AAC9E,UAAM,IAAI,eAAe,YAAY,mBAAmB;AAAA,EAC1D;AAEA,MAAI,wBAAwB,QAAW;AACrC,QAAI;AACF,UAAI,QAAQ,aAAa,SAAS;AAChC,cAAM,iCAAiC,qBAAqB,WAAW;AAAA,MACzE;AACA,aAAO,MAAM,0BAA0B,qBAAqB,MAAM;AAAA,IACpE,SAAS,OAAgB;AACvB,UAAI,CAAC,UAAW,MAAgC,SAAS,UAAU;AACjE,cAAM,IAAI,eAAe,YAAY,iBAAiB;AAAA,MACxD;AAEA,YAAM;AAAA,IACR;AAAA,EACF;AAEA,MAAI,QAAQ,aAAa,SAAS;AAChC,QAAI;AACF,aAAO,MAAM,+BAA+B,MAAM;AAAA,IACpD,SAAS,OAAgB;AACvB,UAAI,CAAC,UAAW,MAAgC,SAAS,UAAU;AACjE,cAAM,IAAI,eAAe,YAAY,iBAAiB;AAAA,MACxD;AAEA,YAAM;AAAA,IACR;AAAA,EACF;AAEA,QAAM,MAAM,QAAQ,SAAS;AAC7B,MAAI,QAAQ,QAAW;AACrB,UAAM,IAAI,eAAe,YAAY,mBAAmB;AAAA,EAC1D;AAEA,QAAM,WAAW,KAAK,KAAK,GAAG,OAAO,GAAG,aAAa,OAAO,GAAG,CAAC,EAAE;AAElE,MAAI,QAAQ;AACV,QAAI;AACF,YAAM,MAAM,UAAU,EAAE,MAAM,IAAM,CAAC;AAAA,IACvC,SAAS,OAAgB;AACvB,UAAK,MAAgC,SAAS,UAAU;AACtD,cAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,MAAI;AACF,UAAM,iCAAiC,UAAU,WAAW;AAAA,EAC9D,SAAS,OAAgB;AACvB,QAAI,CAAC,UAAW,MAAgC,SAAS,UAAU;AACjE,YAAM,IAAI,eAAe,YAAY,iBAAiB;AAAA,IACxD;AAEA,UAAM;AAAA,EACR;AAEA,SAAO,SAAS,QAAQ;AAC1B;AAEA,eAAsB,iCAAiC,MAA+B;AACpF,QAAM,gBAAgB,MAAM,SAAS,IAAI;AACzC,SAAO,WAAW,QAAQ,EACvB,OAAO,GAAG,iCAAiC,KAAK,aAAa,EAAE,EAC/D,OAAO,KAAK;AACjB;","names":[]}
|