@spotpatch/dev-server 0.4.0 → 0.5.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/index.cjs +383 -112
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +44 -2
- package/dist/index.d.ts +44 -2
- package/dist/index.js +380 -100
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
package/dist/index.cjs
CHANGED
|
@@ -36,6 +36,7 @@ __export(index_exports, {
|
|
|
36
36
|
createAgentJobManager: () => createAgentJobManager,
|
|
37
37
|
createIntegrationFileChange: () => createIntegrationFileChange,
|
|
38
38
|
createRuntimeAiConfig: () => createRuntimeAiConfig,
|
|
39
|
+
createRuntimeDataFlowConfig: () => createRuntimeDataFlowConfig,
|
|
39
40
|
createSession: () => createSession,
|
|
40
41
|
createSourceRegistrationService: () => createSourceRegistrationService,
|
|
41
42
|
createSourceRegistry: () => createSourceRegistry,
|
|
@@ -785,7 +786,7 @@ var DEFAULT_EXCLUDE = Object.freeze([
|
|
|
785
786
|
/(?:^|\/)dist(?:\/|$)/,
|
|
786
787
|
/(?:^|\/)coverage(?:\/|$)/
|
|
787
788
|
]);
|
|
788
|
-
var DEFAULT_INCLUDE = Object.freeze([/(?:^|[/\\])src[/\\].+\.(?:jsx|tsx)$/]);
|
|
789
|
+
var DEFAULT_INCLUDE = Object.freeze([/(?:^|[/\\])src[/\\].+\.(?:js|jsx|ts|tsx)$/]);
|
|
789
790
|
var DEFAULT_BUDGET = Object.freeze({
|
|
790
791
|
totalCharacters: 16e3,
|
|
791
792
|
domCharacters: 3e3,
|
|
@@ -806,7 +807,12 @@ var DEFAULT_OPTIONS = Object.freeze({
|
|
|
806
807
|
debug: false,
|
|
807
808
|
locale: "auto",
|
|
808
809
|
maxTargets: 8,
|
|
809
|
-
ai: false
|
|
810
|
+
ai: false,
|
|
811
|
+
dataFlow: Object.freeze({
|
|
812
|
+
enabled: false,
|
|
813
|
+
runtime: "dispatch",
|
|
814
|
+
limits: import_shared2.DEFAULT_DATA_FLOW_LIMITS
|
|
815
|
+
})
|
|
810
816
|
});
|
|
811
817
|
var PROFILE_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
|
|
812
818
|
var ENV_NAME_PATTERN = /^[A-Z][A-Z0-9_]{1,127}$/;
|
|
@@ -1098,6 +1104,36 @@ function assertPositiveBudget(budget) {
|
|
|
1098
1104
|
}
|
|
1099
1105
|
}
|
|
1100
1106
|
}
|
|
1107
|
+
function resolveDataFlowOptions(options) {
|
|
1108
|
+
if (options === void 0 || options === false) {
|
|
1109
|
+
return DEFAULT_OPTIONS.dataFlow;
|
|
1110
|
+
}
|
|
1111
|
+
const candidate = options;
|
|
1112
|
+
if (typeof candidate !== "object" || candidate === null) {
|
|
1113
|
+
throw new RangeError("SpotPatch dataFlow configuration is invalid.");
|
|
1114
|
+
}
|
|
1115
|
+
const runtime = options.runtime ?? "dispatch";
|
|
1116
|
+
if (runtime !== "dispatch") {
|
|
1117
|
+
throw new RangeError("SpotPatch dataFlow runtime mode is invalid.");
|
|
1118
|
+
}
|
|
1119
|
+
return Object.freeze({
|
|
1120
|
+
enabled: true,
|
|
1121
|
+
runtime,
|
|
1122
|
+
limits: import_shared2.DEFAULT_DATA_FLOW_LIMITS
|
|
1123
|
+
});
|
|
1124
|
+
}
|
|
1125
|
+
function createRuntimeDataFlowConfig(options) {
|
|
1126
|
+
return Object.freeze({
|
|
1127
|
+
enabled: options.enabled,
|
|
1128
|
+
runtime: options.runtime,
|
|
1129
|
+
limits: Object.freeze({
|
|
1130
|
+
observationMaxEntries: options.limits.observationMaxEntries,
|
|
1131
|
+
observationMaxBytes: options.limits.observationMaxBytes,
|
|
1132
|
+
observationTtlMs: options.limits.observationTtlMs,
|
|
1133
|
+
reportMaxBytes: options.limits.reportMaxBytes
|
|
1134
|
+
})
|
|
1135
|
+
});
|
|
1136
|
+
}
|
|
1101
1137
|
function resolveOptions(options = {}, environmentAi) {
|
|
1102
1138
|
if (options.trustedFastMode !== void 0 && typeof options.trustedFastMode !== "boolean") {
|
|
1103
1139
|
throw new RangeError("SpotPatch trustedFastMode must be a boolean.");
|
|
@@ -1133,7 +1169,8 @@ function resolveOptions(options = {}, environmentAi) {
|
|
|
1133
1169
|
debug: options.debug ?? DEFAULT_OPTIONS.debug,
|
|
1134
1170
|
locale,
|
|
1135
1171
|
maxTargets,
|
|
1136
|
-
ai: resolveAiOptions(options.ai ?? environmentAi)
|
|
1172
|
+
ai: resolveAiOptions(options.ai ?? environmentAi),
|
|
1173
|
+
dataFlow: resolveDataFlowOptions(options.dataFlow)
|
|
1137
1174
|
};
|
|
1138
1175
|
if (resolved.shortcut.trim().length === 0 || resolved.shortcut.length > 128 || resolved.shortcut.includes("\0")) {
|
|
1139
1176
|
throw new RangeError("SpotPatch shortcut is invalid.");
|
|
@@ -1319,33 +1356,58 @@ function createSourceRegistry(options = {}) {
|
|
|
1319
1356
|
const createId = options.createId ?? createRandomSourceId;
|
|
1320
1357
|
const pathToId = /* @__PURE__ */ new Map();
|
|
1321
1358
|
const idToPath = /* @__PURE__ */ new Map();
|
|
1359
|
+
const componentAnchors = /* @__PURE__ */ new Map();
|
|
1360
|
+
const componentIdsByPath = /* @__PURE__ */ new Map();
|
|
1361
|
+
function registerSourcePath(absolutePath) {
|
|
1362
|
+
const normalizedPath = normalizeAbsolutePath(absolutePath);
|
|
1363
|
+
const existingId = pathToId.get(normalizedPath);
|
|
1364
|
+
if (existingId !== void 0) {
|
|
1365
|
+
return existingId;
|
|
1366
|
+
}
|
|
1367
|
+
let fileId = createId();
|
|
1368
|
+
while (idToPath.has(fileId)) fileId = createId();
|
|
1369
|
+
pathToId.set(normalizedPath, fileId);
|
|
1370
|
+
idToPath.set(fileId, normalizedPath);
|
|
1371
|
+
return fileId;
|
|
1372
|
+
}
|
|
1322
1373
|
return Object.freeze({
|
|
1323
1374
|
register(absolutePath) {
|
|
1375
|
+
return registerSourcePath(absolutePath);
|
|
1376
|
+
},
|
|
1377
|
+
registerDataFlowComponents(absolutePath, sourceVersion, components) {
|
|
1324
1378
|
const normalizedPath = normalizeAbsolutePath(absolutePath);
|
|
1325
|
-
const
|
|
1326
|
-
|
|
1327
|
-
|
|
1379
|
+
const previousIds = componentIdsByPath.get(normalizedPath);
|
|
1380
|
+
for (const componentSourceId of previousIds ?? []) {
|
|
1381
|
+
componentAnchors.delete(componentSourceId);
|
|
1328
1382
|
}
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1383
|
+
const fileId = registerSourcePath(normalizedPath);
|
|
1384
|
+
const currentIds = /* @__PURE__ */ new Set();
|
|
1385
|
+
for (const component of components) {
|
|
1386
|
+
currentIds.add(component.componentSourceId);
|
|
1387
|
+
componentAnchors.set(
|
|
1388
|
+
component.componentSourceId,
|
|
1389
|
+
Object.freeze({ ...component, fileId, sourceVersion })
|
|
1390
|
+
);
|
|
1332
1391
|
}
|
|
1333
|
-
|
|
1334
|
-
idToPath.set(fileId, normalizedPath);
|
|
1335
|
-
return fileId;
|
|
1392
|
+
componentIdsByPath.set(normalizedPath, currentIds);
|
|
1336
1393
|
},
|
|
1337
1394
|
resolve(fileId) {
|
|
1338
1395
|
return idToPath.get(fileId);
|
|
1339
1396
|
},
|
|
1397
|
+
resolveDataFlowComponent(componentSourceId) {
|
|
1398
|
+
return componentAnchors.get(componentSourceId);
|
|
1399
|
+
},
|
|
1340
1400
|
clear() {
|
|
1341
1401
|
pathToId.clear();
|
|
1342
1402
|
idToPath.clear();
|
|
1403
|
+
componentAnchors.clear();
|
|
1404
|
+
componentIdsByPath.clear();
|
|
1343
1405
|
}
|
|
1344
1406
|
});
|
|
1345
1407
|
}
|
|
1346
1408
|
|
|
1347
1409
|
// src/server/middleware.ts
|
|
1348
|
-
var
|
|
1410
|
+
var import_shared11 = require("@spotpatch/shared");
|
|
1349
1411
|
|
|
1350
1412
|
// src/server/agent-http.ts
|
|
1351
1413
|
var import_shared7 = require("@spotpatch/shared");
|
|
@@ -2158,10 +2220,177 @@ function createEditorLauncher(dependencies = DEFAULT_DEPENDENCIES2) {
|
|
|
2158
2220
|
}
|
|
2159
2221
|
var launchConfiguredEditor = createEditorLauncher();
|
|
2160
2222
|
|
|
2161
|
-
// src/server/
|
|
2223
|
+
// src/server/data-flow-http.ts
|
|
2162
2224
|
var import_node_crypto4 = require("crypto");
|
|
2163
|
-
var
|
|
2225
|
+
var import_analyzer = require("@spotpatch/analyzer");
|
|
2164
2226
|
var import_shared8 = require("@spotpatch/shared");
|
|
2227
|
+
function envelopeBytes(report) {
|
|
2228
|
+
return Buffer.byteLength(JSON.stringify({ ok: true, data: report }), "utf8");
|
|
2229
|
+
}
|
|
2230
|
+
function limitDataFlowReportToBytes(report, maximumBytes) {
|
|
2231
|
+
const structurallyLimited = (0, import_shared8.limitDataFlowReportCollections)(report);
|
|
2232
|
+
if (envelopeBytes(structurallyLimited) <= maximumBytes) {
|
|
2233
|
+
return structurallyLimited;
|
|
2234
|
+
}
|
|
2235
|
+
let limited = (0, import_shared8.limitDataFlowReportCollections)(structurallyLimited, {
|
|
2236
|
+
forceTruncation: true,
|
|
2237
|
+
maximumDependencies: 0,
|
|
2238
|
+
truncatedBy: "bytes"
|
|
2239
|
+
});
|
|
2240
|
+
if (envelopeBytes(limited) > maximumBytes) {
|
|
2241
|
+
throw new import_shared8.SpotPatchError(import_shared8.ERROR_CODES.INTERNAL_ERROR);
|
|
2242
|
+
}
|
|
2243
|
+
for (let maximumDependencies = 1; maximumDependencies <= structurallyLimited.dependencies.length; maximumDependencies += 1) {
|
|
2244
|
+
const candidate = (0, import_shared8.limitDataFlowReportCollections)(structurallyLimited, {
|
|
2245
|
+
forceTruncation: true,
|
|
2246
|
+
maximumDependencies,
|
|
2247
|
+
truncatedBy: "bytes"
|
|
2248
|
+
});
|
|
2249
|
+
if (envelopeBytes(candidate) > maximumBytes) break;
|
|
2250
|
+
limited = candidate;
|
|
2251
|
+
}
|
|
2252
|
+
return limited;
|
|
2253
|
+
}
|
|
2254
|
+
function createDataFlowAnalyzer(options) {
|
|
2255
|
+
if (!options.options.dataFlow.enabled) return void 0;
|
|
2256
|
+
return (0, import_analyzer.createStaticDataFlowAnalyzer)({
|
|
2257
|
+
root: options.root,
|
|
2258
|
+
registryEpoch: options.session.id,
|
|
2259
|
+
registerSource: (absolutePath) => options.registry.register(absolutePath),
|
|
2260
|
+
limits: options.options.dataFlow.limits
|
|
2261
|
+
});
|
|
2262
|
+
}
|
|
2263
|
+
async function analyzeTarget(request, analyzer, options) {
|
|
2264
|
+
const resolvedRequest = (() => {
|
|
2265
|
+
if ("componentSourceId" in request) {
|
|
2266
|
+
const anchor = options.registry.resolveDataFlowComponent(
|
|
2267
|
+
request.componentSourceId
|
|
2268
|
+
);
|
|
2269
|
+
if (anchor?.sourceVersion !== request.sourceVersion) {
|
|
2270
|
+
throw new import_shared8.SpotPatchError(import_shared8.ERROR_CODES.DATA_FLOW_SOURCE_STALE);
|
|
2271
|
+
}
|
|
2272
|
+
return anchor;
|
|
2273
|
+
}
|
|
2274
|
+
return request;
|
|
2275
|
+
})();
|
|
2276
|
+
const absolutePath = await resolveSourceFile({
|
|
2277
|
+
fileId: resolvedRequest.fileId,
|
|
2278
|
+
registry: options.registry,
|
|
2279
|
+
root: options.root
|
|
2280
|
+
});
|
|
2281
|
+
const report = analyzer.analyzeComponent({
|
|
2282
|
+
absolutePath,
|
|
2283
|
+
line: resolvedRequest.line,
|
|
2284
|
+
column: resolvedRequest.column
|
|
2285
|
+
});
|
|
2286
|
+
if (resolvedRequest.sourceVersion !== void 0 && resolvedRequest.sourceVersion !== report.component.source.sourceVersion) {
|
|
2287
|
+
throw new import_shared8.SpotPatchError(import_shared8.ERROR_CODES.DATA_FLOW_SOURCE_STALE);
|
|
2288
|
+
}
|
|
2289
|
+
return limitDataFlowReportToBytes(
|
|
2290
|
+
report,
|
|
2291
|
+
options.options.dataFlow.limits.reportMaxBytes
|
|
2292
|
+
);
|
|
2293
|
+
}
|
|
2294
|
+
function requireAnalyzer(analyzer) {
|
|
2295
|
+
if (analyzer === void 0) {
|
|
2296
|
+
throw new import_shared8.SpotPatchError(import_shared8.ERROR_CODES.DATA_FLOW_DISABLED);
|
|
2297
|
+
}
|
|
2298
|
+
return analyzer;
|
|
2299
|
+
}
|
|
2300
|
+
async function handleComponentDataFlowReport(request, analyzer, options) {
|
|
2301
|
+
const parsed = import_shared8.dataFlowComponentReportRequestSchema.safeParse(
|
|
2302
|
+
await readJsonRequestBody(
|
|
2303
|
+
request,
|
|
2304
|
+
options.options.dataFlow.limits.protocolRequestMaxBytes
|
|
2305
|
+
)
|
|
2306
|
+
);
|
|
2307
|
+
if (!parsed.success) {
|
|
2308
|
+
throw new import_shared8.SpotPatchError(import_shared8.ERROR_CODES.INVALID_REQUEST);
|
|
2309
|
+
}
|
|
2310
|
+
return analyzeTarget(parsed.data, requireAnalyzer(analyzer), options);
|
|
2311
|
+
}
|
|
2312
|
+
async function handlePageDataFlowReport(request, analyzer, options) {
|
|
2313
|
+
const parsed = import_shared8.dataFlowPageReportRequestSchema.safeParse(
|
|
2314
|
+
await readJsonRequestBody(
|
|
2315
|
+
request,
|
|
2316
|
+
options.options.dataFlow.limits.protocolRequestMaxBytes
|
|
2317
|
+
)
|
|
2318
|
+
);
|
|
2319
|
+
if (!parsed.success) {
|
|
2320
|
+
throw new import_shared8.SpotPatchError(import_shared8.ERROR_CODES.INVALID_REQUEST);
|
|
2321
|
+
}
|
|
2322
|
+
const activeAnalyzer = requireAnalyzer(analyzer);
|
|
2323
|
+
const componentReports = await Promise.all(
|
|
2324
|
+
parsed.data.targets.map((target) => analyzeTarget(target, activeAnalyzer, options))
|
|
2325
|
+
);
|
|
2326
|
+
const dependencies = new Map(
|
|
2327
|
+
componentReports.flatMap(
|
|
2328
|
+
(report2) => report2.dependencies.map((dependency) => [dependency.id, dependency])
|
|
2329
|
+
)
|
|
2330
|
+
);
|
|
2331
|
+
const evidence = new Map(
|
|
2332
|
+
componentReports.flatMap(
|
|
2333
|
+
(report2) => report2.evidence.map((entry) => [entry.id, entry])
|
|
2334
|
+
)
|
|
2335
|
+
);
|
|
2336
|
+
const diagnostics = new Map(
|
|
2337
|
+
componentReports.flatMap(
|
|
2338
|
+
(report2) => report2.diagnostics.map((entry) => [entry.id, entry])
|
|
2339
|
+
)
|
|
2340
|
+
);
|
|
2341
|
+
const analyzedVersions = new Set(
|
|
2342
|
+
componentReports.flatMap((report2) => report2.baseline.analyzedSourceVersions)
|
|
2343
|
+
);
|
|
2344
|
+
const reportId = `page_${(0, import_node_crypto4.createHash)("sha256").update(componentReports.map((report2) => report2.reportId).join("\0")).digest("base64url").slice(0, 22)}`;
|
|
2345
|
+
const complete = componentReports.every((report2) => report2.completeness.complete);
|
|
2346
|
+
const report = Object.freeze({
|
|
2347
|
+
schemaVersion: import_shared8.DATA_FLOW_SCHEMA_VERSION,
|
|
2348
|
+
reportId,
|
|
2349
|
+
baseline: Object.freeze({
|
|
2350
|
+
registryEpoch: options.session.id,
|
|
2351
|
+
analyzerVersion: componentReports[0]?.baseline.analyzerVersion ?? "unavailable",
|
|
2352
|
+
adapterSetHash: componentReports[0]?.baseline.adapterSetHash ?? "unavailable",
|
|
2353
|
+
analyzedSourceVersions: Object.freeze([...analyzedVersions].sort())
|
|
2354
|
+
}),
|
|
2355
|
+
capability: Object.freeze({
|
|
2356
|
+
enabled: true,
|
|
2357
|
+
staticAnalysis: complete ? "available" : "partial",
|
|
2358
|
+
runtimeObservation: "dispatch-only",
|
|
2359
|
+
responseShape: "consumed-fields-only",
|
|
2360
|
+
aiAssistance: "disabled",
|
|
2361
|
+
reasons: Object.freeze(
|
|
2362
|
+
componentReports.flatMap((report2) => report2.capability.reasons)
|
|
2363
|
+
)
|
|
2364
|
+
}),
|
|
2365
|
+
dependencies: Object.freeze([...dependencies.values()]),
|
|
2366
|
+
evidence: Object.freeze([...evidence.values()]),
|
|
2367
|
+
diagnostics: Object.freeze([...diagnostics.values()]),
|
|
2368
|
+
completeness: Object.freeze({
|
|
2369
|
+
complete,
|
|
2370
|
+
visitedModules: componentReports.reduce(
|
|
2371
|
+
(total, report2) => total + report2.completeness.visitedModules,
|
|
2372
|
+
0
|
|
2373
|
+
),
|
|
2374
|
+
visitedCallsites: componentReports.reduce(
|
|
2375
|
+
(total, report2) => total + report2.completeness.visitedCallsites,
|
|
2376
|
+
0
|
|
2377
|
+
),
|
|
2378
|
+
frontierCount: componentReports.reduce(
|
|
2379
|
+
(total, report2) => total + report2.completeness.frontierCount,
|
|
2380
|
+
0
|
|
2381
|
+
)
|
|
2382
|
+
})
|
|
2383
|
+
});
|
|
2384
|
+
return limitDataFlowReportToBytes(
|
|
2385
|
+
report,
|
|
2386
|
+
options.options.dataFlow.limits.reportMaxBytes
|
|
2387
|
+
);
|
|
2388
|
+
}
|
|
2389
|
+
|
|
2390
|
+
// src/server/request-security.ts
|
|
2391
|
+
var import_node_crypto5 = require("crypto");
|
|
2392
|
+
var import_node_net = require("net");
|
|
2393
|
+
var import_shared9 = require("@spotpatch/shared");
|
|
2165
2394
|
function getSingleHeader(request, name) {
|
|
2166
2395
|
const value = request.headers[name.toLowerCase()];
|
|
2167
2396
|
return Array.isArray(value) ? value[0] : value;
|
|
@@ -2172,7 +2401,7 @@ function tokensMatch(actual, expected) {
|
|
|
2172
2401
|
}
|
|
2173
2402
|
const actualBytes = Buffer.from(actual);
|
|
2174
2403
|
const expectedBytes = Buffer.from(expected);
|
|
2175
|
-
return actualBytes.byteLength === expectedBytes.byteLength && (0,
|
|
2404
|
+
return actualBytes.byteLength === expectedBytes.byteLength && (0, import_node_crypto5.timingSafeEqual)(actualBytes, expectedBytes);
|
|
2176
2405
|
}
|
|
2177
2406
|
function isLoopbackHostname(hostname) {
|
|
2178
2407
|
const normalized = hostname.toLowerCase().replace(/^\[|\]$/g, "");
|
|
@@ -2206,32 +2435,32 @@ function parseOrigin(value) {
|
|
|
2206
2435
|
}
|
|
2207
2436
|
}
|
|
2208
2437
|
function assertRequestAuthorized(request, options) {
|
|
2209
|
-
const actualToken = getSingleHeader(request,
|
|
2438
|
+
const actualToken = getSingleHeader(request, import_shared9.SPOTPATCH_TOKEN_HEADER);
|
|
2210
2439
|
if (!tokensMatch(actualToken, options.sessionToken)) {
|
|
2211
|
-
throw new
|
|
2440
|
+
throw new import_shared9.SpotPatchError(import_shared9.ERROR_CODES.INVALID_TOKEN);
|
|
2212
2441
|
}
|
|
2213
2442
|
const hostHeader = getSingleHeader(request, "host");
|
|
2214
2443
|
const originHeader = getSingleHeader(request, "origin");
|
|
2215
2444
|
const host = hostHeader === void 0 ? void 0 : parseHost(hostHeader);
|
|
2216
2445
|
const origin = originHeader === void 0 ? void 0 : parseOrigin(originHeader);
|
|
2217
2446
|
if (host === void 0 || origin === void 0) {
|
|
2218
|
-
throw new
|
|
2447
|
+
throw new import_shared9.SpotPatchError(import_shared9.ERROR_CODES.ORIGIN_NOT_ALLOWED);
|
|
2219
2448
|
}
|
|
2220
2449
|
const hostIsLoopback = isLoopbackHostname(host.hostname);
|
|
2221
2450
|
const originIsLoopback = isLoopbackHostname(origin.hostname);
|
|
2222
2451
|
if (!options.allowLan) {
|
|
2223
2452
|
if (!hostIsLoopback || !originIsLoopback) {
|
|
2224
|
-
throw new
|
|
2453
|
+
throw new import_shared9.SpotPatchError(import_shared9.ERROR_CODES.ORIGIN_NOT_ALLOWED);
|
|
2225
2454
|
}
|
|
2226
2455
|
return;
|
|
2227
2456
|
}
|
|
2228
2457
|
if (!originIsLoopback && origin.host.toLowerCase() !== host.host.toLowerCase()) {
|
|
2229
|
-
throw new
|
|
2458
|
+
throw new import_shared9.SpotPatchError(import_shared9.ERROR_CODES.ORIGIN_NOT_ALLOWED);
|
|
2230
2459
|
}
|
|
2231
2460
|
}
|
|
2232
2461
|
|
|
2233
2462
|
// src/server/runtime-bootstrap.ts
|
|
2234
|
-
var
|
|
2463
|
+
var import_shared10 = require("@spotpatch/shared");
|
|
2235
2464
|
function getSingleHeader2(request, name) {
|
|
2236
2465
|
const value = request.headers[name.toLowerCase()];
|
|
2237
2466
|
return Array.isArray(value) ? value[0] : value;
|
|
@@ -2246,7 +2475,7 @@ function resolveRuntimeBootstrapOptions(options) {
|
|
|
2246
2475
|
if (expectedOrigin.origin !== options.expectedOrigin || expectedOrigin.protocol !== "http:" || !isLoopbackHostname(expectedOrigin.hostname)) {
|
|
2247
2476
|
throw new TypeError("The SpotPatch bootstrap origin must be a loopback origin.");
|
|
2248
2477
|
}
|
|
2249
|
-
const parsedConfig =
|
|
2478
|
+
const parsedConfig = import_shared10.runtimeConfigSchema.safeParse(options.runtimeConfig);
|
|
2250
2479
|
if (!parsedConfig.success) {
|
|
2251
2480
|
throw new TypeError("The SpotPatch Runtime configuration is invalid.");
|
|
2252
2481
|
}
|
|
@@ -2258,7 +2487,7 @@ function resolveRuntimeBootstrapOptions(options) {
|
|
|
2258
2487
|
function assertRuntimeBootstrapRequest(request, expectedOrigin) {
|
|
2259
2488
|
const contentType = getSingleHeader2(request, "content-type")?.split(";", 1)[0]?.trim().toLowerCase();
|
|
2260
2489
|
if (request.method !== "POST" || contentType !== "application/json") {
|
|
2261
|
-
throw new
|
|
2490
|
+
throw new import_shared10.SpotPatchError(import_shared10.ERROR_CODES.INVALID_REQUEST);
|
|
2262
2491
|
}
|
|
2263
2492
|
const host = getSingleHeader2(request, "host");
|
|
2264
2493
|
let hostIsLoopback = false;
|
|
@@ -2270,90 +2499,96 @@ function assertRuntimeBootstrapRequest(request, expectedOrigin) {
|
|
|
2270
2499
|
}
|
|
2271
2500
|
}
|
|
2272
2501
|
if (!hostIsLoopback || getSingleHeader2(request, "origin") !== expectedOrigin || getSingleHeader2(request, "sec-fetch-site") !== "same-origin") {
|
|
2273
|
-
throw new
|
|
2502
|
+
throw new import_shared10.SpotPatchError(import_shared10.ERROR_CODES.ORIGIN_NOT_ALLOWED);
|
|
2274
2503
|
}
|
|
2275
2504
|
}
|
|
2276
2505
|
async function readRuntimeBootstrap(request, options) {
|
|
2277
2506
|
assertRuntimeBootstrapRequest(request, options.expectedOrigin);
|
|
2278
|
-
const parsedBody =
|
|
2507
|
+
const parsedBody = import_shared10.runtimeBootstrapRequestSchema.safeParse(
|
|
2279
2508
|
await readJsonRequestBody(request)
|
|
2280
2509
|
);
|
|
2281
2510
|
if (!parsedBody.success) {
|
|
2282
|
-
throw new
|
|
2511
|
+
throw new import_shared10.SpotPatchError(import_shared10.ERROR_CODES.INVALID_REQUEST);
|
|
2283
2512
|
}
|
|
2284
2513
|
return options.runtimeConfig;
|
|
2285
2514
|
}
|
|
2286
2515
|
|
|
2287
2516
|
// src/server/middleware.ts
|
|
2288
2517
|
var STATUS_BY_ERROR = Object.freeze({
|
|
2289
|
-
[
|
|
2290
|
-
[
|
|
2291
|
-
[
|
|
2292
|
-
[
|
|
2293
|
-
[
|
|
2294
|
-
[
|
|
2295
|
-
[
|
|
2296
|
-
[
|
|
2297
|
-
[
|
|
2298
|
-
[
|
|
2299
|
-
[
|
|
2300
|
-
[
|
|
2301
|
-
[
|
|
2302
|
-
[
|
|
2303
|
-
[
|
|
2304
|
-
[
|
|
2305
|
-
[
|
|
2306
|
-
[
|
|
2307
|
-
[
|
|
2308
|
-
[
|
|
2309
|
-
[
|
|
2310
|
-
[
|
|
2311
|
-
[
|
|
2312
|
-
[
|
|
2313
|
-
[
|
|
2314
|
-
[
|
|
2315
|
-
[
|
|
2316
|
-
[
|
|
2317
|
-
[
|
|
2318
|
-
[
|
|
2319
|
-
[
|
|
2320
|
-
[
|
|
2321
|
-
[
|
|
2518
|
+
[import_shared11.ERROR_CODES.INVALID_REQUEST]: 400,
|
|
2519
|
+
[import_shared11.ERROR_CODES.INVALID_TOKEN]: 401,
|
|
2520
|
+
[import_shared11.ERROR_CODES.ORIGIN_NOT_ALLOWED]: 403,
|
|
2521
|
+
[import_shared11.ERROR_CODES.SOURCE_NOT_FOUND]: 404,
|
|
2522
|
+
[import_shared11.ERROR_CODES.SOURCE_OUTSIDE_ROOT]: 403,
|
|
2523
|
+
[import_shared11.ERROR_CODES.SOURCE_TOO_LARGE]: 413,
|
|
2524
|
+
[import_shared11.ERROR_CODES.EDITOR_OPEN_FAILED]: 500,
|
|
2525
|
+
[import_shared11.ERROR_CODES.DATA_FLOW_DISABLED]: 404,
|
|
2526
|
+
[import_shared11.ERROR_CODES.DATA_FLOW_SOURCE_STALE]: 409,
|
|
2527
|
+
[import_shared11.ERROR_CODES.DATA_FLOW_ANALYSIS_CANCELLED]: 409,
|
|
2528
|
+
[import_shared11.ERROR_CODES.AI_DISABLED]: 404,
|
|
2529
|
+
[import_shared11.ERROR_CODES.PROVIDER_NOT_CONFIGURED]: 503,
|
|
2530
|
+
[import_shared11.ERROR_CODES.PROVIDER_AUTH_FAILED]: 502,
|
|
2531
|
+
[import_shared11.ERROR_CODES.PROVIDER_PROTOCOL_UNSUPPORTED]: 502,
|
|
2532
|
+
[import_shared11.ERROR_CODES.MODEL_NOT_ALLOWED]: 400,
|
|
2533
|
+
[import_shared11.ERROR_CODES.MODEL_TOOL_CALL_UNSUPPORTED]: 422,
|
|
2534
|
+
[import_shared11.ERROR_CODES.PROVIDER_RATE_LIMITED]: 429,
|
|
2535
|
+
[import_shared11.ERROR_CODES.AGENT_BUSY]: 409,
|
|
2536
|
+
[import_shared11.ERROR_CODES.AGENT_LIMIT_EXCEEDED]: 413,
|
|
2537
|
+
[import_shared11.ERROR_CODES.AGENT_CANCELLED]: 409,
|
|
2538
|
+
[import_shared11.ERROR_CODES.WORKTREE_DIRTY]: 409,
|
|
2539
|
+
[import_shared11.ERROR_CODES.WORKTREE_NOT_REPOSITORY]: 409,
|
|
2540
|
+
[import_shared11.ERROR_CODES.WORKTREE_OPERATION_IN_PROGRESS]: 409,
|
|
2541
|
+
[import_shared11.ERROR_CODES.WORKTREE_CONFLICTED]: 409,
|
|
2542
|
+
[import_shared11.ERROR_CODES.WORKTREE_LOCAL_CHANGES_TOO_LARGE]: 413,
|
|
2543
|
+
[import_shared11.ERROR_CODES.WORKTREE_UNTRACKED_UNSUPPORTED]: 409,
|
|
2544
|
+
[import_shared11.ERROR_CODES.WORKTREE_LOCAL_CHANGES_UNSUPPORTED]: 409,
|
|
2545
|
+
[import_shared11.ERROR_CODES.TOOL_DENIED]: 403,
|
|
2546
|
+
[import_shared11.ERROR_CODES.TOOL_INPUT_INVALID]: 422,
|
|
2547
|
+
[import_shared11.ERROR_CODES.TOOL_ARGUMENTS_INVALID]: 422,
|
|
2548
|
+
[import_shared11.ERROR_CODES.TOOL_CALL_ID_CONFLICT]: 422,
|
|
2549
|
+
[import_shared11.ERROR_CODES.TOOL_PATH_DENIED]: 403,
|
|
2550
|
+
[import_shared11.ERROR_CODES.PATCH_REJECTED]: 422,
|
|
2551
|
+
[import_shared11.ERROR_CODES.VALIDATION_FAILED]: 422,
|
|
2552
|
+
[import_shared11.ERROR_CODES.APPLY_CONFLICT]: 409,
|
|
2553
|
+
[import_shared11.ERROR_CODES.INTERNAL_ERROR]: 500
|
|
2322
2554
|
});
|
|
2323
2555
|
var PUBLIC_MESSAGES = Object.freeze({
|
|
2324
|
-
[
|
|
2325
|
-
[
|
|
2326
|
-
[
|
|
2327
|
-
[
|
|
2328
|
-
[
|
|
2329
|
-
[
|
|
2330
|
-
[
|
|
2331
|
-
[
|
|
2332
|
-
[
|
|
2333
|
-
[
|
|
2334
|
-
[
|
|
2335
|
-
[
|
|
2336
|
-
[
|
|
2337
|
-
[
|
|
2338
|
-
[
|
|
2339
|
-
[
|
|
2340
|
-
[
|
|
2341
|
-
[
|
|
2342
|
-
[
|
|
2343
|
-
[
|
|
2344
|
-
[
|
|
2345
|
-
[
|
|
2346
|
-
[
|
|
2347
|
-
[
|
|
2348
|
-
[
|
|
2349
|
-
[
|
|
2350
|
-
[
|
|
2351
|
-
[
|
|
2352
|
-
[
|
|
2353
|
-
[
|
|
2354
|
-
[
|
|
2355
|
-
[
|
|
2356
|
-
[
|
|
2556
|
+
[import_shared11.ERROR_CODES.INVALID_REQUEST]: "The request is invalid.",
|
|
2557
|
+
[import_shared11.ERROR_CODES.INVALID_TOKEN]: "The session token is invalid.",
|
|
2558
|
+
[import_shared11.ERROR_CODES.ORIGIN_NOT_ALLOWED]: "The request origin is not allowed.",
|
|
2559
|
+
[import_shared11.ERROR_CODES.SOURCE_NOT_FOUND]: "The source file is unavailable.",
|
|
2560
|
+
[import_shared11.ERROR_CODES.SOURCE_OUTSIDE_ROOT]: "The source file is outside the project root.",
|
|
2561
|
+
[import_shared11.ERROR_CODES.SOURCE_TOO_LARGE]: "The source file exceeds the size limit.",
|
|
2562
|
+
[import_shared11.ERROR_CODES.EDITOR_OPEN_FAILED]: "The editor request could not be started.",
|
|
2563
|
+
[import_shared11.ERROR_CODES.DATA_FLOW_DISABLED]: "Component data-flow analysis is not enabled.",
|
|
2564
|
+
[import_shared11.ERROR_CODES.DATA_FLOW_SOURCE_STALE]: "The selected source version is stale.",
|
|
2565
|
+
[import_shared11.ERROR_CODES.DATA_FLOW_ANALYSIS_CANCELLED]: "The data-flow analysis was cancelled.",
|
|
2566
|
+
[import_shared11.ERROR_CODES.AI_DISABLED]: "AI execution is not enabled.",
|
|
2567
|
+
[import_shared11.ERROR_CODES.PROVIDER_NOT_CONFIGURED]: "The AI provider is unavailable.",
|
|
2568
|
+
[import_shared11.ERROR_CODES.PROVIDER_AUTH_FAILED]: "The AI provider rejected authentication.",
|
|
2569
|
+
[import_shared11.ERROR_CODES.PROVIDER_PROTOCOL_UNSUPPORTED]: "The AI provider protocol is unsupported.",
|
|
2570
|
+
[import_shared11.ERROR_CODES.MODEL_NOT_ALLOWED]: "The selected model is not allowed.",
|
|
2571
|
+
[import_shared11.ERROR_CODES.MODEL_TOOL_CALL_UNSUPPORTED]: "The selected model cannot run SpotPatch tools.",
|
|
2572
|
+
[import_shared11.ERROR_CODES.PROVIDER_RATE_LIMITED]: "The AI provider is rate limited.",
|
|
2573
|
+
[import_shared11.ERROR_CODES.AGENT_BUSY]: "Another Agent job is already running.",
|
|
2574
|
+
[import_shared11.ERROR_CODES.AGENT_LIMIT_EXCEEDED]: "The Agent job exceeded a safety limit.",
|
|
2575
|
+
[import_shared11.ERROR_CODES.AGENT_CANCELLED]: "The Agent job was cancelled.",
|
|
2576
|
+
[import_shared11.ERROR_CODES.WORKTREE_DIRTY]: "Local changes require explicit inclusion consent.",
|
|
2577
|
+
[import_shared11.ERROR_CODES.WORKTREE_NOT_REPOSITORY]: "The project root is not a Git repository.",
|
|
2578
|
+
[import_shared11.ERROR_CODES.WORKTREE_OPERATION_IN_PROGRESS]: "A Git operation is currently in progress.",
|
|
2579
|
+
[import_shared11.ERROR_CODES.WORKTREE_CONFLICTED]: "The local workspace contains unresolved merge conflicts.",
|
|
2580
|
+
[import_shared11.ERROR_CODES.WORKTREE_LOCAL_CHANGES_TOO_LARGE]: "The local workspace exceeds the safe isolation size limit.",
|
|
2581
|
+
[import_shared11.ERROR_CODES.WORKTREE_UNTRACKED_UNSUPPORTED]: "An untracked path cannot be isolated safely.",
|
|
2582
|
+
[import_shared11.ERROR_CODES.WORKTREE_LOCAL_CHANGES_UNSUPPORTED]: "The local workspace state cannot be isolated safely.",
|
|
2583
|
+
[import_shared11.ERROR_CODES.TOOL_DENIED]: "The Agent tool request was denied.",
|
|
2584
|
+
[import_shared11.ERROR_CODES.TOOL_INPUT_INVALID]: "The Agent tool input was invalid.",
|
|
2585
|
+
[import_shared11.ERROR_CODES.TOOL_ARGUMENTS_INVALID]: "The Agent tool arguments are invalid.",
|
|
2586
|
+
[import_shared11.ERROR_CODES.TOOL_CALL_ID_CONFLICT]: "A tool call ID conflicts within one Agent turn.",
|
|
2587
|
+
[import_shared11.ERROR_CODES.TOOL_PATH_DENIED]: "The Agent tool path was denied.",
|
|
2588
|
+
[import_shared11.ERROR_CODES.PATCH_REJECTED]: "The proposed patch was rejected.",
|
|
2589
|
+
[import_shared11.ERROR_CODES.VALIDATION_FAILED]: "The proposed change failed validation.",
|
|
2590
|
+
[import_shared11.ERROR_CODES.APPLY_CONFLICT]: "The change conflicts with the current worktree.",
|
|
2591
|
+
[import_shared11.ERROR_CODES.INTERNAL_ERROR]: "The request could not be completed."
|
|
2357
2592
|
});
|
|
2358
2593
|
function writeJson(response, status, payload) {
|
|
2359
2594
|
response.statusCode = status;
|
|
@@ -2362,11 +2597,11 @@ function writeJson(response, status, payload) {
|
|
|
2362
2597
|
response.end(JSON.stringify(payload));
|
|
2363
2598
|
}
|
|
2364
2599
|
function asSpotPatchError(error) {
|
|
2365
|
-
return error instanceof
|
|
2600
|
+
return error instanceof import_shared11.SpotPatchError ? error : new import_shared11.SpotPatchError(import_shared11.ERROR_CODES.INTERNAL_ERROR, void 0, { cause: error });
|
|
2366
2601
|
}
|
|
2367
2602
|
function writeError(response, error, logger) {
|
|
2368
2603
|
const normalized = asSpotPatchError(error);
|
|
2369
|
-
if (normalized.code ===
|
|
2604
|
+
if (normalized.code === import_shared11.ERROR_CODES.INTERNAL_ERROR) {
|
|
2370
2605
|
logger?.warn("[spotpatch:server] Internal request failure.");
|
|
2371
2606
|
}
|
|
2372
2607
|
writeJson(response, STATUS_BY_ERROR[normalized.code], {
|
|
@@ -2385,11 +2620,11 @@ function requestPath(request) {
|
|
|
2385
2620
|
}
|
|
2386
2621
|
}
|
|
2387
2622
|
async function handleSourceContext(request, options) {
|
|
2388
|
-
const parsed =
|
|
2623
|
+
const parsed = import_shared11.sourceContextRequestSchema.safeParse(
|
|
2389
2624
|
await readJsonRequestBody(request)
|
|
2390
2625
|
);
|
|
2391
2626
|
if (!parsed.success) {
|
|
2392
|
-
throw new
|
|
2627
|
+
throw new import_shared11.SpotPatchError(import_shared11.ERROR_CODES.INVALID_REQUEST);
|
|
2393
2628
|
}
|
|
2394
2629
|
return readSourceContext({
|
|
2395
2630
|
request: parsed.data,
|
|
@@ -2400,9 +2635,9 @@ async function handleSourceContext(request, options) {
|
|
|
2400
2635
|
});
|
|
2401
2636
|
}
|
|
2402
2637
|
async function handleOpenEditor(request, options) {
|
|
2403
|
-
const parsed =
|
|
2638
|
+
const parsed = import_shared11.openEditorRequestSchema.safeParse(await readJsonRequestBody(request));
|
|
2404
2639
|
if (!parsed.success) {
|
|
2405
|
-
throw new
|
|
2640
|
+
throw new import_shared11.SpotPatchError(import_shared11.ERROR_CODES.INVALID_REQUEST);
|
|
2406
2641
|
}
|
|
2407
2642
|
const body = parsed.data;
|
|
2408
2643
|
const sourcePath = await resolveSourceFile({
|
|
@@ -2419,22 +2654,23 @@ async function handleOpenEditor(request, options) {
|
|
|
2419
2654
|
options.logger?.warn(
|
|
2420
2655
|
`[spotpatch:server] ${options.options.editor === "auto" ? "The detected editor" : options.options.editor} rejected an editor request.`
|
|
2421
2656
|
);
|
|
2422
|
-
throw new
|
|
2657
|
+
throw new import_shared11.SpotPatchError(import_shared11.ERROR_CODES.EDITOR_OPEN_FAILED, void 0, {
|
|
2423
2658
|
cause: error
|
|
2424
2659
|
});
|
|
2425
2660
|
}
|
|
2426
2661
|
}
|
|
2427
2662
|
function createSpotPatchMiddleware(options) {
|
|
2428
2663
|
const bootstrap = options.bootstrap === void 0 ? void 0 : resolveRuntimeBootstrapOptions(options.bootstrap);
|
|
2664
|
+
const dataFlowAnalyzer = createDataFlowAnalyzer(options);
|
|
2429
2665
|
return (request, response, next) => {
|
|
2430
2666
|
const path8 = requestPath(request);
|
|
2431
2667
|
const agentRoute = matchAgentRequestPath(path8);
|
|
2432
|
-
if (path8 !==
|
|
2668
|
+
if (path8 !== import_shared11.SPOTPATCH_ENDPOINTS.sourceContext && path8 !== import_shared11.SPOTPATCH_ENDPOINTS.openEditor && path8 !== import_shared11.SPOTPATCH_ENDPOINTS.dataFlowComponentReport && path8 !== import_shared11.SPOTPATCH_ENDPOINTS.dataFlowPageReport && agentRoute === void 0 && !path8.startsWith(`${import_shared11.SPOTPATCH_API_BASE}/`)) {
|
|
2433
2669
|
next();
|
|
2434
2670
|
return;
|
|
2435
2671
|
}
|
|
2436
2672
|
const handle = async () => {
|
|
2437
|
-
if (path8 ===
|
|
2673
|
+
if (path8 === import_shared11.SPOTPATCH_ENDPOINTS.bootstrap && bootstrap !== void 0) {
|
|
2438
2674
|
const data = await readRuntimeBootstrap(
|
|
2439
2675
|
request,
|
|
2440
2676
|
bootstrap
|
|
@@ -2446,24 +2682,44 @@ function createSpotPatchMiddleware(options) {
|
|
|
2446
2682
|
allowLan: options.options.allowLan,
|
|
2447
2683
|
sessionToken: options.session.token
|
|
2448
2684
|
});
|
|
2449
|
-
if (path8 ===
|
|
2685
|
+
if (path8 === import_shared11.SPOTPATCH_ENDPOINTS.sourceContext) {
|
|
2450
2686
|
if (request.method !== "POST") {
|
|
2451
|
-
throw new
|
|
2687
|
+
throw new import_shared11.SpotPatchError(import_shared11.ERROR_CODES.INVALID_REQUEST);
|
|
2452
2688
|
}
|
|
2453
2689
|
const data = await handleSourceContext(request, options);
|
|
2454
2690
|
writeJson(response, 200, { ok: true, data });
|
|
2455
2691
|
return;
|
|
2456
2692
|
}
|
|
2457
|
-
if (path8 ===
|
|
2693
|
+
if (path8 === import_shared11.SPOTPATCH_ENDPOINTS.openEditor) {
|
|
2458
2694
|
if (request.method !== "POST") {
|
|
2459
|
-
throw new
|
|
2695
|
+
throw new import_shared11.SpotPatchError(import_shared11.ERROR_CODES.INVALID_REQUEST);
|
|
2460
2696
|
}
|
|
2461
2697
|
const data = await handleOpenEditor(request, options);
|
|
2462
2698
|
writeJson(response, 200, { ok: true, data });
|
|
2463
2699
|
return;
|
|
2464
2700
|
}
|
|
2701
|
+
if (path8 === import_shared11.SPOTPATCH_ENDPOINTS.dataFlowComponentReport) {
|
|
2702
|
+
if (request.method !== "POST") {
|
|
2703
|
+
throw new import_shared11.SpotPatchError(import_shared11.ERROR_CODES.INVALID_REQUEST);
|
|
2704
|
+
}
|
|
2705
|
+
const data = await handleComponentDataFlowReport(
|
|
2706
|
+
request,
|
|
2707
|
+
dataFlowAnalyzer,
|
|
2708
|
+
options
|
|
2709
|
+
);
|
|
2710
|
+
writeJson(response, 200, { ok: true, data });
|
|
2711
|
+
return;
|
|
2712
|
+
}
|
|
2713
|
+
if (path8 === import_shared11.SPOTPATCH_ENDPOINTS.dataFlowPageReport) {
|
|
2714
|
+
if (request.method !== "POST") {
|
|
2715
|
+
throw new import_shared11.SpotPatchError(import_shared11.ERROR_CODES.INVALID_REQUEST);
|
|
2716
|
+
}
|
|
2717
|
+
const data = await handlePageDataFlowReport(request, dataFlowAnalyzer, options);
|
|
2718
|
+
writeJson(response, 200, { ok: true, data });
|
|
2719
|
+
return;
|
|
2720
|
+
}
|
|
2465
2721
|
if (agentRoute === void 0) {
|
|
2466
|
-
throw new
|
|
2722
|
+
throw new import_shared11.SpotPatchError(import_shared11.ERROR_CODES.INVALID_REQUEST);
|
|
2467
2723
|
}
|
|
2468
2724
|
await handleAgentRequest(
|
|
2469
2725
|
request,
|
|
@@ -2482,7 +2738,7 @@ function createSpotPatchMiddleware(options) {
|
|
|
2482
2738
|
}
|
|
2483
2739
|
|
|
2484
2740
|
// src/server/source-registration.ts
|
|
2485
|
-
var
|
|
2741
|
+
var import_node_crypto6 = require("crypto");
|
|
2486
2742
|
var import_promises6 = require("fs/promises");
|
|
2487
2743
|
var import_node_path7 = __toESM(require("path"), 1);
|
|
2488
2744
|
var import_compiler = require("@spotpatch/compiler");
|
|
@@ -2505,7 +2761,7 @@ function identitiesMatch(actual, expected) {
|
|
|
2505
2761
|
}
|
|
2506
2762
|
const actualBytes = Buffer.from(actual);
|
|
2507
2763
|
const expectedBytes = Buffer.from(expected);
|
|
2508
|
-
return actualBytes.byteLength === expectedBytes.byteLength && (0,
|
|
2764
|
+
return actualBytes.byteLength === expectedBytes.byteLength && (0, import_node_crypto6.timingSafeEqual)(actualBytes, expectedBytes);
|
|
2509
2765
|
}
|
|
2510
2766
|
function isWithinRoot(root, candidate) {
|
|
2511
2767
|
const relative = import_node_path7.default.relative(root, candidate);
|
|
@@ -2600,11 +2856,11 @@ async function createSourceRegistrationService(input) {
|
|
|
2600
2856
|
}
|
|
2601
2857
|
|
|
2602
2858
|
// src/session/session.ts
|
|
2603
|
-
var
|
|
2859
|
+
var import_node_crypto7 = require("crypto");
|
|
2604
2860
|
function createSession() {
|
|
2605
2861
|
return Object.freeze({
|
|
2606
|
-
id: (0,
|
|
2607
|
-
token: (0,
|
|
2862
|
+
id: (0, import_node_crypto7.randomBytes)(16).toString("base64url"),
|
|
2863
|
+
token: (0, import_node_crypto7.randomBytes)(16).toString("base64url")
|
|
2608
2864
|
});
|
|
2609
2865
|
}
|
|
2610
2866
|
|
|
@@ -2614,6 +2870,7 @@ var OPTION_KEYS = Object.freeze([
|
|
|
2614
2870
|
"allowLan",
|
|
2615
2871
|
"budget",
|
|
2616
2872
|
"debug",
|
|
2873
|
+
"dataFlow",
|
|
2617
2874
|
"editor",
|
|
2618
2875
|
"enabled",
|
|
2619
2876
|
"exclude",
|
|
@@ -2701,6 +2958,9 @@ function serializeResolvedSpotPatchOptions(options) {
|
|
|
2701
2958
|
allowLan: options.allowLan,
|
|
2702
2959
|
budget: options.budget,
|
|
2703
2960
|
debug: options.debug,
|
|
2961
|
+
dataFlow: options.dataFlow.enabled ? Object.freeze({
|
|
2962
|
+
runtime: options.dataFlow.runtime
|
|
2963
|
+
}) : false,
|
|
2704
2964
|
editor: options.editor,
|
|
2705
2965
|
enabled: options.enabled,
|
|
2706
2966
|
exclude: Object.freeze(options.exclude.map(serializeFilter)),
|
|
@@ -2743,6 +3003,15 @@ function parseBudget(value) {
|
|
|
2743
3003
|
);
|
|
2744
3004
|
return Object.freeze(budget);
|
|
2745
3005
|
}
|
|
3006
|
+
function parseDataFlow(value) {
|
|
3007
|
+
if (value === false) return false;
|
|
3008
|
+
if (!isRecord2(value) || !hasExactKeys(value, ["runtime"]) || value.runtime !== "dispatch") {
|
|
3009
|
+
throw new TypeError("The SpotPatch data-flow transport is invalid.");
|
|
3010
|
+
}
|
|
3011
|
+
return Object.freeze({
|
|
3012
|
+
runtime: value.runtime
|
|
3013
|
+
});
|
|
3014
|
+
}
|
|
2746
3015
|
function parseSerializedSpotPatchOptions(value) {
|
|
2747
3016
|
if (!isRecord2(value) || !hasExactKeys(value, OPTION_KEYS)) {
|
|
2748
3017
|
throw new TypeError("The SpotPatch options transport is invalid.");
|
|
@@ -2756,6 +3025,7 @@ function parseSerializedSpotPatchOptions(value) {
|
|
|
2756
3025
|
allowLan: value.allowLan,
|
|
2757
3026
|
budget: parseBudget(value.budget),
|
|
2758
3027
|
debug: value.debug,
|
|
3028
|
+
dataFlow: parseDataFlow(value.dataFlow),
|
|
2759
3029
|
editor: value.editor,
|
|
2760
3030
|
enabled: value.enabled,
|
|
2761
3031
|
exclude: parseFilterList(value.exclude),
|
|
@@ -2779,6 +3049,7 @@ function parseSerializedSpotPatchOptions(value) {
|
|
|
2779
3049
|
createAgentJobManager,
|
|
2780
3050
|
createIntegrationFileChange,
|
|
2781
3051
|
createRuntimeAiConfig,
|
|
3052
|
+
createRuntimeDataFlowConfig,
|
|
2782
3053
|
createSession,
|
|
2783
3054
|
createSourceRegistrationService,
|
|
2784
3055
|
createSourceRegistry,
|