@spotpatch/shared 1.13.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-C0Me9mN2.d.cts → annotation-Cz-NNgR4.d.cts} +2 -2
- package/dist/{annotation-C0Me9mN2.d.ts → annotation-Cz-NNgR4.d.ts} +2 -2
- package/dist/{chunk-IUTOVI5G.js → chunk-CLQ6MIJB.js} +5 -3
- package/dist/chunk-CLQ6MIJB.js.map +1 -0
- package/dist/{chunk-DYTWEIES.js → chunk-EWJTKNL4.js} +2 -1
- package/dist/chunk-EWJTKNL4.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-YQ5GL523.js → chunk-JTZFOTPT.js} +3 -3
- package/dist/{chunk-C2PJ4UUU.js → chunk-R6QJFNT2.js} +3 -3
- package/dist/chunk-R6QJFNT2.js.map +1 -0
- package/dist/{contextual-ask-B0mCFn92.d.cts → contextual-ask-BpbkpFFf.d.cts} +25 -0
- package/dist/{contextual-ask-B0mCFn92.d.ts → contextual-ask-BpbkpFFf.d.ts} +25 -0
- package/dist/contextual-ask-browser.cjs +1 -0
- package/dist/contextual-ask-browser.cjs.map +1 -1
- package/dist/contextual-ask-browser.d.cts +1 -1
- package/dist/contextual-ask-browser.d.ts +1 -1
- package/dist/contextual-ask-browser.js +1 -1
- package/dist/contextual-ask-node.cjs +5 -2
- package/dist/contextual-ask-node.cjs.map +1 -1
- package/dist/contextual-ask-node.d.cts +3 -3
- package/dist/contextual-ask-node.d.ts +3 -3
- package/dist/contextual-ask-node.js +3 -3
- package/dist/{data-flow-runtime-vKeEaJgT.d.ts → data-flow-runtime-DhWpQoik.d.ts} +13 -0
- package/dist/{data-flow-runtime-D8HPSb2i.d.cts → data-flow-runtime-w43iwvGA.d.cts} +13 -0
- package/dist/data-flow-runtime.d.cts +1 -1
- package/dist/data-flow-runtime.d.ts +1 -1
- package/dist/external-agent-node.cjs +178 -20
- package/dist/external-agent-node.cjs.map +1 -1
- package/dist/external-agent-node.d.cts +18 -3
- package/dist/external-agent-node.d.ts +18 -3
- package/dist/external-agent-node.js +172 -20
- package/dist/external-agent-node.js.map +1 -1
- package/dist/{external-handoff-DighrWn8.d.ts → external-handoff-5zHu-fz2.d.ts} +12 -2
- package/dist/{external-handoff-DwtFFR6F.d.cts → external-handoff-DeiIvR-2.d.cts} +12 -2
- package/dist/external-handoff-browser.cjs +5 -1
- package/dist/external-handoff-browser.cjs.map +1 -1
- package/dist/external-handoff-browser.d.cts +3 -3
- package/dist/external-handoff-browser.d.ts +3 -3
- package/dist/external-handoff-browser.js +1 -1
- package/dist/index.cjs +28 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -7
- package/dist/index.d.ts +19 -7
- package/dist/index.js +23 -8
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-2LVIH7OA.js.map +0 -1
- package/dist/chunk-C2PJ4UUU.js.map +0 -1
- package/dist/chunk-DYTWEIES.js.map +0 -1
- package/dist/chunk-IUTOVI5G.js.map +0 -1
- package/dist/{chunk-YQ5GL523.js.map → chunk-JTZFOTPT.js.map} +0 -0
- package/dist/{external-agent-control-CRBbjDDk.d.cts → external-agent-control-C79Nl85y.d.cts} +3 -3
- package/dist/{external-agent-control-CRBbjDDk.d.ts → external-agent-control-C79Nl85y.d.ts} +3 -3
|
@@ -1,6 +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 './annotation-
|
|
3
|
+
import { E as EXTERNAL_HANDOFF_LIMITS, A as ActiveAdapterSummary, D as DispatchSummary, a as ExternalHandoffSnapshot } from './external-handoff-DeiIvR-2.cjs';
|
|
4
|
+
import './annotation-Cz-NNgR4.cjs';
|
|
4
5
|
|
|
5
6
|
declare const SPOTPATCH_BRIDGE_TOKEN_HEADER: "X-SpotPatch-Bridge-Token";
|
|
6
7
|
declare const SPOTPATCH_BRIDGE_PATHS: Readonly<{
|
|
@@ -20,6 +21,7 @@ declare const externalHandoffDescriptorSchema: z.ZodObject<{
|
|
|
20
21
|
projectKey: z.ZodString;
|
|
21
22
|
sessionId: z.ZodString;
|
|
22
23
|
framework: z.ZodEnum<{
|
|
24
|
+
astro: "astro";
|
|
23
25
|
vite: "vite";
|
|
24
26
|
next: "next";
|
|
25
27
|
}>;
|
|
@@ -70,12 +72,14 @@ declare const bridgeStatusSchema: z.ZodObject<{
|
|
|
70
72
|
projectKey: z.ZodString;
|
|
71
73
|
sessionId: z.ZodString;
|
|
72
74
|
framework: z.ZodEnum<{
|
|
75
|
+
astro: "astro";
|
|
73
76
|
vite: "vite";
|
|
74
77
|
next: "next";
|
|
75
78
|
}>;
|
|
76
79
|
current: z.ZodNullable<z.ZodObject<{
|
|
77
80
|
sessionId: z.ZodString;
|
|
78
81
|
framework: z.ZodEnum<{
|
|
82
|
+
astro: "astro";
|
|
79
83
|
vite: "vite";
|
|
80
84
|
next: "next";
|
|
81
85
|
}>;
|
|
@@ -105,6 +109,7 @@ declare const bridgeCurrentResultSchema: z.ZodObject<{
|
|
|
105
109
|
session: z.ZodObject<{
|
|
106
110
|
id: z.ZodString;
|
|
107
111
|
framework: z.ZodEnum<{
|
|
112
|
+
astro: "astro";
|
|
108
113
|
vite: "vite";
|
|
109
114
|
next: "next";
|
|
110
115
|
}>;
|
|
@@ -144,6 +149,7 @@ declare const bridgeCurrentResultSchema: z.ZodObject<{
|
|
|
144
149
|
column: z.ZodOptional<z.ZodNumber>;
|
|
145
150
|
origin: z.ZodEnum<{
|
|
146
151
|
"jsx-host": "jsx-host";
|
|
152
|
+
"astro-host": "astro-host";
|
|
147
153
|
"react-fiber": "react-fiber";
|
|
148
154
|
"dom-ancestor": "dom-ancestor";
|
|
149
155
|
none: "none";
|
|
@@ -169,6 +175,7 @@ declare const bridgeCurrentResultSchema: z.ZodObject<{
|
|
|
169
175
|
column: z.ZodOptional<z.ZodNumber>;
|
|
170
176
|
origin: z.ZodEnum<{
|
|
171
177
|
"jsx-host": "jsx-host";
|
|
178
|
+
"astro-host": "astro-host";
|
|
172
179
|
"react-fiber": "react-fiber";
|
|
173
180
|
"dom-ancestor": "dom-ancestor";
|
|
174
181
|
none: "none";
|
|
@@ -211,6 +218,7 @@ declare const bridgeCurrentResultSchema: z.ZodObject<{
|
|
|
211
218
|
language: z.ZodEnum<{
|
|
212
219
|
tsx: "tsx";
|
|
213
220
|
jsx: "jsx";
|
|
221
|
+
astro: "astro";
|
|
214
222
|
}>;
|
|
215
223
|
startLine: z.ZodNumber;
|
|
216
224
|
endLine: z.ZodNumber;
|
|
@@ -234,6 +242,7 @@ declare const bridgeWaitResultSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
234
242
|
session: z.ZodObject<{
|
|
235
243
|
id: z.ZodString;
|
|
236
244
|
framework: z.ZodEnum<{
|
|
245
|
+
astro: "astro";
|
|
237
246
|
vite: "vite";
|
|
238
247
|
next: "next";
|
|
239
248
|
}>;
|
|
@@ -273,6 +282,7 @@ declare const bridgeWaitResultSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
273
282
|
column: z.ZodOptional<z.ZodNumber>;
|
|
274
283
|
origin: z.ZodEnum<{
|
|
275
284
|
"jsx-host": "jsx-host";
|
|
285
|
+
"astro-host": "astro-host";
|
|
276
286
|
"react-fiber": "react-fiber";
|
|
277
287
|
"dom-ancestor": "dom-ancestor";
|
|
278
288
|
none: "none";
|
|
@@ -298,6 +308,7 @@ declare const bridgeWaitResultSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
298
308
|
column: z.ZodOptional<z.ZodNumber>;
|
|
299
309
|
origin: z.ZodEnum<{
|
|
300
310
|
"jsx-host": "jsx-host";
|
|
311
|
+
"astro-host": "astro-host";
|
|
301
312
|
"react-fiber": "react-fiber";
|
|
302
313
|
"dom-ancestor": "dom-ancestor";
|
|
303
314
|
none: "none";
|
|
@@ -340,6 +351,7 @@ declare const bridgeWaitResultSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
340
351
|
language: z.ZodEnum<{
|
|
341
352
|
tsx: "tsx";
|
|
342
353
|
jsx: "jsx";
|
|
354
|
+
astro: "astro";
|
|
343
355
|
}>;
|
|
344
356
|
startLine: z.ZodNumber;
|
|
345
357
|
endLine: z.ZodNumber;
|
|
@@ -361,6 +373,7 @@ declare const bridgeAckResultSchema: z.ZodObject<{
|
|
|
361
373
|
summary: z.ZodObject<{
|
|
362
374
|
sessionId: z.ZodString;
|
|
363
375
|
framework: z.ZodEnum<{
|
|
376
|
+
astro: "astro";
|
|
364
377
|
vite: "vite";
|
|
365
378
|
next: "next";
|
|
366
379
|
}>;
|
|
@@ -551,7 +564,9 @@ interface BridgeActiveStateResult {
|
|
|
551
564
|
readonly activeAdapter: ActiveAdapterSummary | null;
|
|
552
565
|
readonly dispatch: DispatchSummary | null;
|
|
553
566
|
}
|
|
567
|
+
declare function assertPrivateExternalHandoffPath(candidate: string, kind: "directory" | "file"): Promise<Stats>;
|
|
568
|
+
declare function initializePrivateExternalHandoffFile(candidate: string): Promise<void>;
|
|
554
569
|
declare function resolveExternalHandoffRuntimeDirectory(create: boolean): Promise<string>;
|
|
555
570
|
declare function computeExternalHandoffProjectKey(root: string): Promise<string>;
|
|
556
571
|
|
|
557
|
-
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,6 +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 './annotation-
|
|
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';
|
|
4
5
|
|
|
5
6
|
declare const SPOTPATCH_BRIDGE_TOKEN_HEADER: "X-SpotPatch-Bridge-Token";
|
|
6
7
|
declare const SPOTPATCH_BRIDGE_PATHS: Readonly<{
|
|
@@ -20,6 +21,7 @@ declare const externalHandoffDescriptorSchema: z.ZodObject<{
|
|
|
20
21
|
projectKey: z.ZodString;
|
|
21
22
|
sessionId: z.ZodString;
|
|
22
23
|
framework: z.ZodEnum<{
|
|
24
|
+
astro: "astro";
|
|
23
25
|
vite: "vite";
|
|
24
26
|
next: "next";
|
|
25
27
|
}>;
|
|
@@ -70,12 +72,14 @@ declare const bridgeStatusSchema: z.ZodObject<{
|
|
|
70
72
|
projectKey: z.ZodString;
|
|
71
73
|
sessionId: z.ZodString;
|
|
72
74
|
framework: z.ZodEnum<{
|
|
75
|
+
astro: "astro";
|
|
73
76
|
vite: "vite";
|
|
74
77
|
next: "next";
|
|
75
78
|
}>;
|
|
76
79
|
current: z.ZodNullable<z.ZodObject<{
|
|
77
80
|
sessionId: z.ZodString;
|
|
78
81
|
framework: z.ZodEnum<{
|
|
82
|
+
astro: "astro";
|
|
79
83
|
vite: "vite";
|
|
80
84
|
next: "next";
|
|
81
85
|
}>;
|
|
@@ -105,6 +109,7 @@ declare const bridgeCurrentResultSchema: z.ZodObject<{
|
|
|
105
109
|
session: z.ZodObject<{
|
|
106
110
|
id: z.ZodString;
|
|
107
111
|
framework: z.ZodEnum<{
|
|
112
|
+
astro: "astro";
|
|
108
113
|
vite: "vite";
|
|
109
114
|
next: "next";
|
|
110
115
|
}>;
|
|
@@ -144,6 +149,7 @@ declare const bridgeCurrentResultSchema: z.ZodObject<{
|
|
|
144
149
|
column: z.ZodOptional<z.ZodNumber>;
|
|
145
150
|
origin: z.ZodEnum<{
|
|
146
151
|
"jsx-host": "jsx-host";
|
|
152
|
+
"astro-host": "astro-host";
|
|
147
153
|
"react-fiber": "react-fiber";
|
|
148
154
|
"dom-ancestor": "dom-ancestor";
|
|
149
155
|
none: "none";
|
|
@@ -169,6 +175,7 @@ declare const bridgeCurrentResultSchema: z.ZodObject<{
|
|
|
169
175
|
column: z.ZodOptional<z.ZodNumber>;
|
|
170
176
|
origin: z.ZodEnum<{
|
|
171
177
|
"jsx-host": "jsx-host";
|
|
178
|
+
"astro-host": "astro-host";
|
|
172
179
|
"react-fiber": "react-fiber";
|
|
173
180
|
"dom-ancestor": "dom-ancestor";
|
|
174
181
|
none: "none";
|
|
@@ -211,6 +218,7 @@ declare const bridgeCurrentResultSchema: z.ZodObject<{
|
|
|
211
218
|
language: z.ZodEnum<{
|
|
212
219
|
tsx: "tsx";
|
|
213
220
|
jsx: "jsx";
|
|
221
|
+
astro: "astro";
|
|
214
222
|
}>;
|
|
215
223
|
startLine: z.ZodNumber;
|
|
216
224
|
endLine: z.ZodNumber;
|
|
@@ -234,6 +242,7 @@ declare const bridgeWaitResultSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
234
242
|
session: z.ZodObject<{
|
|
235
243
|
id: z.ZodString;
|
|
236
244
|
framework: z.ZodEnum<{
|
|
245
|
+
astro: "astro";
|
|
237
246
|
vite: "vite";
|
|
238
247
|
next: "next";
|
|
239
248
|
}>;
|
|
@@ -273,6 +282,7 @@ declare const bridgeWaitResultSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
273
282
|
column: z.ZodOptional<z.ZodNumber>;
|
|
274
283
|
origin: z.ZodEnum<{
|
|
275
284
|
"jsx-host": "jsx-host";
|
|
285
|
+
"astro-host": "astro-host";
|
|
276
286
|
"react-fiber": "react-fiber";
|
|
277
287
|
"dom-ancestor": "dom-ancestor";
|
|
278
288
|
none: "none";
|
|
@@ -298,6 +308,7 @@ declare const bridgeWaitResultSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
298
308
|
column: z.ZodOptional<z.ZodNumber>;
|
|
299
309
|
origin: z.ZodEnum<{
|
|
300
310
|
"jsx-host": "jsx-host";
|
|
311
|
+
"astro-host": "astro-host";
|
|
301
312
|
"react-fiber": "react-fiber";
|
|
302
313
|
"dom-ancestor": "dom-ancestor";
|
|
303
314
|
none: "none";
|
|
@@ -340,6 +351,7 @@ declare const bridgeWaitResultSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
340
351
|
language: z.ZodEnum<{
|
|
341
352
|
tsx: "tsx";
|
|
342
353
|
jsx: "jsx";
|
|
354
|
+
astro: "astro";
|
|
343
355
|
}>;
|
|
344
356
|
startLine: z.ZodNumber;
|
|
345
357
|
endLine: z.ZodNumber;
|
|
@@ -361,6 +373,7 @@ declare const bridgeAckResultSchema: z.ZodObject<{
|
|
|
361
373
|
summary: z.ZodObject<{
|
|
362
374
|
sessionId: z.ZodString;
|
|
363
375
|
framework: z.ZodEnum<{
|
|
376
|
+
astro: "astro";
|
|
364
377
|
vite: "vite";
|
|
365
378
|
next: "next";
|
|
366
379
|
}>;
|
|
@@ -551,7 +564,9 @@ interface BridgeActiveStateResult {
|
|
|
551
564
|
readonly activeAdapter: ActiveAdapterSummary | null;
|
|
552
565
|
readonly dispatch: DispatchSummary | null;
|
|
553
566
|
}
|
|
567
|
+
declare function assertPrivateExternalHandoffPath(candidate: string, kind: "directory" | "file"): Promise<Stats>;
|
|
568
|
+
declare function initializePrivateExternalHandoffFile(candidate: string): Promise<void>;
|
|
554
569
|
declare function resolveExternalHandoffRuntimeDirectory(create: boolean): Promise<string>;
|
|
555
570
|
declare function computeExternalHandoffProjectKey(root: string): Promise<string>;
|
|
556
571
|
|
|
557
|
-
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 };
|
|
@@ -5,22 +5,24 @@ import {
|
|
|
5
5
|
externalHandoffReportableDispatchPhaseSchema,
|
|
6
6
|
externalHandoffSnapshotSchema,
|
|
7
7
|
externalHandoffSummarySchema
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-JTZFOTPT.js";
|
|
9
9
|
import {
|
|
10
10
|
ERROR_CODES
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-R6QJFNT2.js";
|
|
12
12
|
import {
|
|
13
13
|
EXTERNAL_HANDOFF_ACTIVE_ADAPTER_KINDS,
|
|
14
14
|
EXTERNAL_HANDOFF_BROKER_PROTOCOL_VERSION,
|
|
15
15
|
EXTERNAL_HANDOFF_FRAMEWORKS,
|
|
16
16
|
EXTERNAL_HANDOFF_LIMITS
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-IX6MSCK6.js";
|
|
18
18
|
|
|
19
19
|
// src/external-agent-node.ts
|
|
20
20
|
import { createHash } from "crypto";
|
|
21
|
+
import { execFile } from "child_process";
|
|
21
22
|
import { lstat, mkdir, realpath } from "fs/promises";
|
|
22
23
|
import os from "os";
|
|
23
24
|
import path from "path";
|
|
25
|
+
import { promisify } from "util";
|
|
24
26
|
import { z } from "zod";
|
|
25
27
|
var SPOTPATCH_BRIDGE_TOKEN_HEADER = "X-SpotPatch-Bridge-Token";
|
|
26
28
|
var SPOTPATCH_BRIDGE_PATHS = Object.freeze({
|
|
@@ -34,6 +36,75 @@ var SPOTPATCH_BRIDGE_PATHS = Object.freeze({
|
|
|
34
36
|
activeRelease: "/bridge/v1/active/release"
|
|
35
37
|
});
|
|
36
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
|
+
`;
|
|
37
108
|
var opaqueIdSchema = z.string().min(22).max(128).regex(/^[A-Za-z0-9_-]+$/u);
|
|
38
109
|
var projectKeySchema = z.string().length(64).regex(/^[a-f0-9]+$/u);
|
|
39
110
|
var loopbackEndpointSchema = z.url().refine((value) => {
|
|
@@ -113,46 +184,111 @@ var bridgeActiveStateResultSchema = z.strictObject({
|
|
|
113
184
|
var bridgeActiveHeartbeatResultSchema = bridgeActiveStateResultSchema;
|
|
114
185
|
var bridgeActiveReportResultSchema = bridgeActiveStateResultSchema;
|
|
115
186
|
var bridgeActiveReleaseResultSchema = bridgeActiveStateResultSchema;
|
|
116
|
-
function
|
|
117
|
-
const
|
|
118
|
-
if (
|
|
187
|
+
function windowsPowerShellExecutable() {
|
|
188
|
+
const systemRoot = process.env.SystemRoot ?? process.env.SYSTEMROOT;
|
|
189
|
+
if (systemRoot === void 0 || !path.win32.isAbsolute(systemRoot)) {
|
|
119
190
|
throw new SpotPatchError(ERROR_CODES.BRIDGE_UNAUTHORIZED);
|
|
120
191
|
}
|
|
121
|
-
return
|
|
192
|
+
return path.win32.join(
|
|
193
|
+
systemRoot,
|
|
194
|
+
"System32",
|
|
195
|
+
"WindowsPowerShell",
|
|
196
|
+
"v1.0",
|
|
197
|
+
"powershell.exe"
|
|
198
|
+
);
|
|
122
199
|
}
|
|
123
|
-
async function
|
|
124
|
-
|
|
125
|
-
|
|
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
|
+
}
|
|
222
|
+
}
|
|
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()) {
|
|
126
227
|
throw new SpotPatchError(ERROR_CODES.BRIDGE_UNAUTHORIZED);
|
|
127
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) {
|
|
235
|
+
throw new SpotPatchError(ERROR_CODES.BRIDGE_UNAUTHORIZED);
|
|
236
|
+
}
|
|
237
|
+
return status;
|
|
238
|
+
}
|
|
239
|
+
async function initializePrivateExternalHandoffFile(candidate) {
|
|
240
|
+
if (process.platform === "win32") {
|
|
241
|
+
await verifyWindowsAcl(candidate, "file", true);
|
|
242
|
+
}
|
|
128
243
|
}
|
|
129
|
-
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) {
|
|
130
250
|
const directory = path.join(base, "spotpatch");
|
|
251
|
+
let created = false;
|
|
131
252
|
if (create) {
|
|
132
253
|
try {
|
|
133
254
|
await mkdir(directory, { mode: 448 });
|
|
255
|
+
created = true;
|
|
134
256
|
} catch (error) {
|
|
135
257
|
if (error.code !== "EEXIST") {
|
|
136
258
|
throw error;
|
|
137
259
|
}
|
|
138
260
|
}
|
|
139
261
|
}
|
|
140
|
-
await
|
|
141
|
-
|
|
262
|
+
if (created) await initializeWindowsDirectory(directory);
|
|
263
|
+
await assertPrivateExternalHandoffPath(directory, "directory");
|
|
264
|
+
return realpath(directory);
|
|
142
265
|
}
|
|
143
|
-
async function
|
|
144
|
-
|
|
266
|
+
async function resolveWindowsRuntimeDirectory(create) {
|
|
267
|
+
const configuredBase = process.env.LOCALAPPDATA;
|
|
268
|
+
if (configuredBase !== void 0 && !path.isAbsolute(configuredBase)) {
|
|
145
269
|
throw new SpotPatchError(ERROR_CODES.BRIDGE_UNAUTHORIZED);
|
|
146
270
|
}
|
|
147
|
-
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) {
|
|
148
282
|
const xdgRuntimeDirectory = process.env.XDG_RUNTIME_DIR;
|
|
149
283
|
if (xdgRuntimeDirectory !== void 0 && !path.isAbsolute(xdgRuntimeDirectory)) {
|
|
150
284
|
throw new SpotPatchError(ERROR_CODES.BRIDGE_UNAUTHORIZED);
|
|
151
285
|
}
|
|
152
286
|
if (xdgRuntimeDirectory !== void 0) {
|
|
153
287
|
try {
|
|
154
|
-
|
|
155
|
-
|
|
288
|
+
if (process.platform !== "win32") {
|
|
289
|
+
await assertPrivateExternalHandoffPath(xdgRuntimeDirectory, "directory");
|
|
290
|
+
}
|
|
291
|
+
return await ensurePrivateSubdirectory(xdgRuntimeDirectory, create);
|
|
156
292
|
} catch (error) {
|
|
157
293
|
if (!create && error.code === "ENOENT") {
|
|
158
294
|
throw new SpotPatchError(ERROR_CODES.SESSION_NOT_FOUND);
|
|
@@ -160,6 +296,20 @@ async function resolveExternalHandoffRuntimeDirectory(create) {
|
|
|
160
296
|
throw error;
|
|
161
297
|
}
|
|
162
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
|
+
}
|
|
163
313
|
const fallback = path.join(os.tmpdir(), `spotpatch-${String(uid)}`);
|
|
164
314
|
if (create) {
|
|
165
315
|
try {
|
|
@@ -171,14 +321,14 @@ async function resolveExternalHandoffRuntimeDirectory(create) {
|
|
|
171
321
|
}
|
|
172
322
|
}
|
|
173
323
|
try {
|
|
174
|
-
await
|
|
324
|
+
await assertPrivateExternalHandoffPath(fallback, "directory");
|
|
175
325
|
} catch (error) {
|
|
176
326
|
if (!create && error.code === "ENOENT") {
|
|
177
327
|
throw new SpotPatchError(ERROR_CODES.SESSION_NOT_FOUND);
|
|
178
328
|
}
|
|
179
329
|
throw error;
|
|
180
330
|
}
|
|
181
|
-
return fallback;
|
|
331
|
+
return realpath(fallback);
|
|
182
332
|
}
|
|
183
333
|
async function computeExternalHandoffProjectKey(root) {
|
|
184
334
|
const canonicalRoot = await realpath(root);
|
|
@@ -188,6 +338,7 @@ export {
|
|
|
188
338
|
EXTERNAL_HANDOFF_PROJECT_KEY_SALT,
|
|
189
339
|
SPOTPATCH_BRIDGE_PATHS,
|
|
190
340
|
SPOTPATCH_BRIDGE_TOKEN_HEADER,
|
|
341
|
+
assertPrivateExternalHandoffPath,
|
|
191
342
|
bridgeAckRequestSchema,
|
|
192
343
|
bridgeAckResultSchema,
|
|
193
344
|
bridgeActiveClaimRequestSchema,
|
|
@@ -207,6 +358,7 @@ export {
|
|
|
207
358
|
bridgeWaitResultSchema,
|
|
208
359
|
computeExternalHandoffProjectKey,
|
|
209
360
|
externalHandoffDescriptorSchema,
|
|
361
|
+
initializePrivateExternalHandoffFile,
|
|
210
362
|
resolveExternalHandoffRuntimeDirectory
|
|
211
363
|
};
|
|
212
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":"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","names":[]}
|