@spotpatch/dev-server 0.2.0 → 0.3.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 +406 -59
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +32 -2
- package/dist/index.d.ts +32 -2
- package/dist/index.js +404 -53
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -32,19 +32,25 @@ var index_exports = {};
|
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
DEFAULT_EXCLUDE: () => DEFAULT_EXCLUDE,
|
|
34
34
|
DEFAULT_OPTIONS: () => DEFAULT_OPTIONS,
|
|
35
|
+
applyIntegrationPlan: () => applyIntegrationPlan,
|
|
35
36
|
createAgentJobManager: () => createAgentJobManager,
|
|
37
|
+
createIntegrationFileChange: () => createIntegrationFileChange,
|
|
36
38
|
createRuntimeAiConfig: () => createRuntimeAiConfig,
|
|
37
39
|
createSession: () => createSession,
|
|
38
40
|
createSourceRegistrationService: () => createSourceRegistrationService,
|
|
39
41
|
createSourceRegistry: () => createSourceRegistry,
|
|
40
42
|
createSpotPatchMiddleware: () => createSpotPatchMiddleware,
|
|
43
|
+
discoverProjectValidationCheck: () => discoverProjectValidationCheck,
|
|
44
|
+
integrationPathExists: () => integrationPathExists,
|
|
41
45
|
isLoopbackHostname: () => isLoopbackHostname,
|
|
42
46
|
parseSerializedSpotPatchOptions: () => parseSerializedSpotPatchOptions,
|
|
47
|
+
readIntegrationFile: () => readIntegrationFile,
|
|
43
48
|
readJsonRequestBody: () => readJsonRequestBody,
|
|
44
49
|
readRuntimeBootstrap: () => readRuntimeBootstrap,
|
|
45
50
|
resolveCredentialEnvironment: () => resolveCredentialEnvironment,
|
|
46
51
|
resolveEnvironmentAiConfiguration: () => resolveEnvironmentAiConfiguration,
|
|
47
52
|
resolveOptions: () => resolveOptions,
|
|
53
|
+
resolveProjectOptions: () => resolveProjectOptions,
|
|
48
54
|
resolveRuntimeBootstrapOptions: () => resolveRuntimeBootstrapOptions,
|
|
49
55
|
serializeResolvedSpotPatchOptions: () => serializeResolvedSpotPatchOptions
|
|
50
56
|
});
|
|
@@ -322,7 +328,7 @@ function createAgentJobManager(options) {
|
|
|
322
328
|
transition(job, "completed", "No source changes were proposed.");
|
|
323
329
|
return;
|
|
324
330
|
}
|
|
325
|
-
const shouldApplyDirectly =
|
|
331
|
+
const shouldApplyDirectly = job.applyMode === "auto" && preparedChange.autoApplyEligible || job.applyMode === "trusted-auto" && job.trustedFastModeConsent;
|
|
326
332
|
if (shouldApplyDirectly) {
|
|
327
333
|
try {
|
|
328
334
|
await applyChange(job, preparedChange);
|
|
@@ -398,8 +404,11 @@ function createAgentJobManager(options) {
|
|
|
398
404
|
if (closed) {
|
|
399
405
|
throw new import_shared.SpotPatchError(import_shared.ERROR_CODES.AI_DISABLED);
|
|
400
406
|
}
|
|
401
|
-
const
|
|
402
|
-
|
|
407
|
+
const configuredApplyMode = options.ai.execution.applyMode;
|
|
408
|
+
const requestedApplyMode = request.applyMode ?? (request.trustedFastModeConsent === true ? "trusted-auto" : configuredApplyMode);
|
|
409
|
+
const applyModeAllowed = configuredApplyMode === "trusted-auto" ? requestedApplyMode === "review" || requestedApplyMode === "trusted-auto" : requestedApplyMode === configuredApplyMode;
|
|
410
|
+
const trustedConsentMatches = requestedApplyMode === "trusted-auto" === (request.trustedFastModeConsent === true);
|
|
411
|
+
if (!applyModeAllowed || !trustedConsentMatches) {
|
|
403
412
|
throw new import_shared.SpotPatchError(import_shared.ERROR_CODES.INVALID_REQUEST);
|
|
404
413
|
}
|
|
405
414
|
if (hasActiveJob()) {
|
|
@@ -420,6 +429,7 @@ function createAgentJobManager(options) {
|
|
|
420
429
|
const timestamp = dependencies.now();
|
|
421
430
|
const job = {
|
|
422
431
|
annotation: request.annotation,
|
|
432
|
+
applyMode: requestedApplyMode,
|
|
423
433
|
controller: new AbortController(),
|
|
424
434
|
createdAt: timestamp,
|
|
425
435
|
credential: selection.credential,
|
|
@@ -591,6 +601,171 @@ function resolveEnvironmentAiConfiguration(environment) {
|
|
|
591
601
|
});
|
|
592
602
|
}
|
|
593
603
|
|
|
604
|
+
// src/integration/file-plan.ts
|
|
605
|
+
var import_node_crypto2 = require("crypto");
|
|
606
|
+
var import_promises = require("fs/promises");
|
|
607
|
+
var import_node_path = __toESM(require("path"), 1);
|
|
608
|
+
function isMissingPathError(error) {
|
|
609
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
610
|
+
}
|
|
611
|
+
function isPathWithin(root, target) {
|
|
612
|
+
const relative = import_node_path.default.relative(root, target);
|
|
613
|
+
return relative === "" || relative !== ".." && !relative.startsWith(`..${import_node_path.default.sep}`) && !import_node_path.default.isAbsolute(relative);
|
|
614
|
+
}
|
|
615
|
+
function relativePathWithin(root, target) {
|
|
616
|
+
const relative = import_node_path.default.relative(root, target);
|
|
617
|
+
if (relative.length === 0 || !isPathWithin(root, target)) {
|
|
618
|
+
throw new Error("SpotPatch init refuses to modify a path outside the app root.");
|
|
619
|
+
}
|
|
620
|
+
return relative.split(import_node_path.default.sep).join("/");
|
|
621
|
+
}
|
|
622
|
+
async function integrationPathExists(absolutePath) {
|
|
623
|
+
try {
|
|
624
|
+
await (0, import_promises.access)(absolutePath);
|
|
625
|
+
return true;
|
|
626
|
+
} catch {
|
|
627
|
+
return false;
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
async function readIntegrationFile(absolutePath) {
|
|
631
|
+
const metadata = await (0, import_promises.lstat)(absolutePath);
|
|
632
|
+
if (!metadata.isFile() || metadata.isSymbolicLink()) {
|
|
633
|
+
throw new Error(
|
|
634
|
+
`SpotPatch refuses to modify the non-regular file ${import_node_path.default.basename(absolutePath)}.`
|
|
635
|
+
);
|
|
636
|
+
}
|
|
637
|
+
return (0, import_promises.readFile)(absolutePath, "utf8");
|
|
638
|
+
}
|
|
639
|
+
function createIntegrationFileChange(appRoot, absolutePath, nextContent, previousContent) {
|
|
640
|
+
if (previousContent === nextContent) {
|
|
641
|
+
return void 0;
|
|
642
|
+
}
|
|
643
|
+
const root = import_node_path.default.resolve(appRoot);
|
|
644
|
+
const target = import_node_path.default.resolve(absolutePath);
|
|
645
|
+
return Object.freeze({
|
|
646
|
+
absolutePath: target,
|
|
647
|
+
nextContent,
|
|
648
|
+
...previousContent === void 0 ? {} : { previousContent },
|
|
649
|
+
relativePath: relativePathWithin(root, target)
|
|
650
|
+
});
|
|
651
|
+
}
|
|
652
|
+
function temporaryPath(absolutePath, label) {
|
|
653
|
+
return import_node_path.default.join(
|
|
654
|
+
import_node_path.default.dirname(absolutePath),
|
|
655
|
+
`.${import_node_path.default.basename(absolutePath)}.spotpatch-${label}-${String(process.pid)}-${(0, import_node_crypto2.randomBytes)(8).toString("hex")}`
|
|
656
|
+
);
|
|
657
|
+
}
|
|
658
|
+
async function writeAtomic(absolutePath, content, mode) {
|
|
659
|
+
await (0, import_promises.mkdir)(import_node_path.default.dirname(absolutePath), { recursive: true });
|
|
660
|
+
const stagedPath = temporaryPath(absolutePath, "stage");
|
|
661
|
+
try {
|
|
662
|
+
await (0, import_promises.writeFile)(stagedPath, content, { encoding: "utf8", flag: "wx", mode });
|
|
663
|
+
await (0, import_promises.rename)(stagedPath, absolutePath);
|
|
664
|
+
} catch (error) {
|
|
665
|
+
await (0, import_promises.unlink)(stagedPath).catch(() => void 0);
|
|
666
|
+
throw error;
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
async function rollbackChange(change) {
|
|
670
|
+
const currentContent = await readIntegrationFile(change.absolutePath);
|
|
671
|
+
if (currentContent !== change.nextContent) {
|
|
672
|
+
throw new Error(
|
|
673
|
+
`SpotPatch init cannot restore ${change.relativePath} because it changed during initialization.`
|
|
674
|
+
);
|
|
675
|
+
}
|
|
676
|
+
if (change.previousContent === void 0) {
|
|
677
|
+
await (0, import_promises.unlink)(change.absolutePath);
|
|
678
|
+
return;
|
|
679
|
+
}
|
|
680
|
+
const mode = (await (0, import_promises.stat)(change.absolutePath)).mode & 511;
|
|
681
|
+
await writeAtomic(change.absolutePath, change.previousContent, mode);
|
|
682
|
+
}
|
|
683
|
+
async function assertSafeTarget(appRoot, realAppRoot, change) {
|
|
684
|
+
const target = import_node_path.default.resolve(change.absolutePath);
|
|
685
|
+
const relativePath = relativePathWithin(appRoot, target);
|
|
686
|
+
if (target !== change.absolutePath || relativePath !== change.relativePath || import_node_path.default.dirname(target) === target) {
|
|
687
|
+
throw new Error("SpotPatch init received an invalid integration file plan.");
|
|
688
|
+
}
|
|
689
|
+
let targetMetadata;
|
|
690
|
+
try {
|
|
691
|
+
targetMetadata = await (0, import_promises.lstat)(target);
|
|
692
|
+
} catch (error) {
|
|
693
|
+
if (!isMissingPathError(error)) {
|
|
694
|
+
throw error;
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
if (targetMetadata?.isSymbolicLink()) {
|
|
698
|
+
throw new Error(
|
|
699
|
+
`SpotPatch refuses to modify the symbolic link ${change.relativePath}.`
|
|
700
|
+
);
|
|
701
|
+
}
|
|
702
|
+
const containmentAnchor = await (0, import_promises.realpath)(
|
|
703
|
+
targetMetadata === void 0 ? import_node_path.default.dirname(target) : target
|
|
704
|
+
);
|
|
705
|
+
if (!isPathWithin(realAppRoot, containmentAnchor)) {
|
|
706
|
+
throw new Error("SpotPatch init refuses to modify a path outside the app root.");
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
async function assertCurrentBaseline(change) {
|
|
710
|
+
if (change.previousContent === void 0) {
|
|
711
|
+
try {
|
|
712
|
+
await (0, import_promises.lstat)(change.absolutePath);
|
|
713
|
+
} catch (error) {
|
|
714
|
+
if (isMissingPathError(error)) {
|
|
715
|
+
return;
|
|
716
|
+
}
|
|
717
|
+
throw error;
|
|
718
|
+
}
|
|
719
|
+
throw new Error(
|
|
720
|
+
`SpotPatch init cannot create ${change.relativePath} because it now exists.`
|
|
721
|
+
);
|
|
722
|
+
}
|
|
723
|
+
const currentContent = await readIntegrationFile(change.absolutePath);
|
|
724
|
+
if (currentContent !== change.previousContent) {
|
|
725
|
+
throw new Error(
|
|
726
|
+
`SpotPatch init cannot update ${change.relativePath} because it changed after the preview.`
|
|
727
|
+
);
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
async function applyIntegrationPlan(plan) {
|
|
731
|
+
if (plan.changes.length === 0) {
|
|
732
|
+
return;
|
|
733
|
+
}
|
|
734
|
+
const appRoot = import_node_path.default.resolve(plan.appRoot);
|
|
735
|
+
const realAppRoot = await (0, import_promises.realpath)(appRoot);
|
|
736
|
+
const targets = /* @__PURE__ */ new Set();
|
|
737
|
+
for (const change of plan.changes) {
|
|
738
|
+
if (targets.has(change.absolutePath)) {
|
|
739
|
+
throw new Error("SpotPatch init received duplicate integration file changes.");
|
|
740
|
+
}
|
|
741
|
+
targets.add(change.absolutePath);
|
|
742
|
+
await assertSafeTarget(appRoot, realAppRoot, change);
|
|
743
|
+
await assertCurrentBaseline(change);
|
|
744
|
+
}
|
|
745
|
+
const applied = [];
|
|
746
|
+
try {
|
|
747
|
+
for (const change of plan.changes) {
|
|
748
|
+
await assertCurrentBaseline(change);
|
|
749
|
+
const mode = change.previousContent === void 0 ? 384 : (await (0, import_promises.stat)(change.absolutePath)).mode & 511;
|
|
750
|
+
await writeAtomic(change.absolutePath, change.nextContent, mode);
|
|
751
|
+
applied.push(change);
|
|
752
|
+
}
|
|
753
|
+
} catch (error) {
|
|
754
|
+
const rollbackResults = await Promise.allSettled(
|
|
755
|
+
applied.reverse().map(rollbackChange)
|
|
756
|
+
);
|
|
757
|
+
if (rollbackResults.some((result) => result.status === "rejected")) {
|
|
758
|
+
throw new Error(
|
|
759
|
+
"SpotPatch init failed and could not completely restore the previous files.",
|
|
760
|
+
{ cause: error }
|
|
761
|
+
);
|
|
762
|
+
}
|
|
763
|
+
throw new Error("SpotPatch init failed; all written files were restored.", {
|
|
764
|
+
cause: error
|
|
765
|
+
});
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
|
|
594
769
|
// src/options.ts
|
|
595
770
|
var import_shared2 = require("@spotpatch/shared");
|
|
596
771
|
var import_zod = require("zod");
|
|
@@ -916,6 +1091,9 @@ function assertPositiveBudget(budget) {
|
|
|
916
1091
|
}
|
|
917
1092
|
}
|
|
918
1093
|
function resolveOptions(options = {}, environmentAi) {
|
|
1094
|
+
if (options.trustedFastMode !== void 0 && typeof options.trustedFastMode !== "boolean") {
|
|
1095
|
+
throw new RangeError("SpotPatch trustedFastMode must be a boolean.");
|
|
1096
|
+
}
|
|
919
1097
|
const budget = Object.freeze({
|
|
920
1098
|
...DEFAULT_OPTIONS.budget,
|
|
921
1099
|
...options.budget
|
|
@@ -955,17 +1133,179 @@ function resolveOptions(options = {}, environmentAi) {
|
|
|
955
1133
|
return Object.freeze(resolved);
|
|
956
1134
|
}
|
|
957
1135
|
|
|
1136
|
+
// src/project-validation.ts
|
|
1137
|
+
var import_node_child_process = require("child_process");
|
|
1138
|
+
var import_promises2 = require("fs/promises");
|
|
1139
|
+
var import_node_module = require("module");
|
|
1140
|
+
var import_node_path2 = __toESM(require("path"), 1);
|
|
1141
|
+
var import_node_util = require("util");
|
|
1142
|
+
var execFileAsync = (0, import_node_util.promisify)(import_node_child_process.execFile);
|
|
1143
|
+
var TYPESCRIPT_CHECK_ID = "spotpatch-typecheck";
|
|
1144
|
+
var TYPESCRIPT_CHECK_LABEL = "TypeScript";
|
|
1145
|
+
function isRecord(value) {
|
|
1146
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1147
|
+
}
|
|
1148
|
+
async function isRegularFile(absolutePath) {
|
|
1149
|
+
try {
|
|
1150
|
+
const metadata = await (0, import_promises2.lstat)(absolutePath);
|
|
1151
|
+
return metadata.isFile() && !metadata.isSymbolicLink();
|
|
1152
|
+
} catch {
|
|
1153
|
+
return false;
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
async function readManifest(appRoot) {
|
|
1157
|
+
const manifestPath = import_node_path2.default.join(appRoot, "package.json");
|
|
1158
|
+
if (!await isRegularFile(manifestPath)) {
|
|
1159
|
+
return void 0;
|
|
1160
|
+
}
|
|
1161
|
+
try {
|
|
1162
|
+
const value = JSON.parse(await (0, import_promises2.readFile)(manifestPath, "utf8"));
|
|
1163
|
+
return isRecord(value) ? value : void 0;
|
|
1164
|
+
} catch {
|
|
1165
|
+
return void 0;
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
function declaresTypeScript(manifest) {
|
|
1169
|
+
return [
|
|
1170
|
+
manifest.dependencies,
|
|
1171
|
+
manifest.devDependencies,
|
|
1172
|
+
manifest.peerDependencies
|
|
1173
|
+
].some(
|
|
1174
|
+
(dependencies) => isRecord(dependencies) && typeof dependencies.typescript === "string"
|
|
1175
|
+
);
|
|
1176
|
+
}
|
|
1177
|
+
async function findGitRoot(appRoot) {
|
|
1178
|
+
try {
|
|
1179
|
+
const result = await execFileAsync("git", ["rev-parse", "--show-toplevel"], {
|
|
1180
|
+
cwd: appRoot,
|
|
1181
|
+
encoding: "utf8",
|
|
1182
|
+
timeout: 5e3,
|
|
1183
|
+
windowsHide: true
|
|
1184
|
+
});
|
|
1185
|
+
const root = await (0, import_promises2.realpath)(result.stdout.trim());
|
|
1186
|
+
const relative = import_node_path2.default.relative(root, appRoot);
|
|
1187
|
+
if (relative === "" || !relative.startsWith(`..${import_node_path2.default.sep}`) && relative !== ".." && !import_node_path2.default.isAbsolute(relative)) {
|
|
1188
|
+
return root;
|
|
1189
|
+
}
|
|
1190
|
+
} catch {
|
|
1191
|
+
return void 0;
|
|
1192
|
+
}
|
|
1193
|
+
return void 0;
|
|
1194
|
+
}
|
|
1195
|
+
async function resolveTypeScriptCli(appRoot) {
|
|
1196
|
+
const resolveFromApplication = (0, import_node_module.createRequire)(import_node_path2.default.join(appRoot, "package.json"));
|
|
1197
|
+
try {
|
|
1198
|
+
const packagePath = resolveFromApplication.resolve("typescript/package.json");
|
|
1199
|
+
const cliPath = import_node_path2.default.join(import_node_path2.default.dirname(packagePath), "bin", "tsc");
|
|
1200
|
+
await (0, import_promises2.access)(cliPath);
|
|
1201
|
+
return await (0, import_promises2.realpath)(cliPath);
|
|
1202
|
+
} catch {
|
|
1203
|
+
return void 0;
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
function portableRelativePath(from, to) {
|
|
1207
|
+
return import_node_path2.default.relative(from, to).split(import_node_path2.default.sep).join("/");
|
|
1208
|
+
}
|
|
1209
|
+
async function discoverProjectValidationCheck(options) {
|
|
1210
|
+
const appRoot = await (0, import_promises2.realpath)(options.appRoot);
|
|
1211
|
+
const tsconfigPath = import_node_path2.default.join(appRoot, "tsconfig.json");
|
|
1212
|
+
const [manifest, projectRoot, hasTsconfig] = await Promise.all([
|
|
1213
|
+
readManifest(appRoot),
|
|
1214
|
+
findGitRoot(appRoot),
|
|
1215
|
+
isRegularFile(tsconfigPath)
|
|
1216
|
+
]);
|
|
1217
|
+
if (manifest === void 0 || projectRoot === void 0 || !hasTsconfig || !declaresTypeScript(manifest)) {
|
|
1218
|
+
return void 0;
|
|
1219
|
+
}
|
|
1220
|
+
const cliPath = await resolveTypeScriptCli(appRoot);
|
|
1221
|
+
if (cliPath === void 0) {
|
|
1222
|
+
return void 0;
|
|
1223
|
+
}
|
|
1224
|
+
const projectPath = portableRelativePath(projectRoot, tsconfigPath);
|
|
1225
|
+
if (projectPath.length === 0 || projectPath.startsWith("../")) {
|
|
1226
|
+
return void 0;
|
|
1227
|
+
}
|
|
1228
|
+
return Object.freeze({
|
|
1229
|
+
id: TYPESCRIPT_CHECK_ID,
|
|
1230
|
+
label: TYPESCRIPT_CHECK_LABEL,
|
|
1231
|
+
command: process.execPath,
|
|
1232
|
+
args: Object.freeze([
|
|
1233
|
+
cliPath,
|
|
1234
|
+
"--noEmit",
|
|
1235
|
+
"--pretty",
|
|
1236
|
+
"false",
|
|
1237
|
+
"--project",
|
|
1238
|
+
projectPath
|
|
1239
|
+
]),
|
|
1240
|
+
required: true,
|
|
1241
|
+
timeoutMs: options.timeoutMs
|
|
1242
|
+
});
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1245
|
+
// src/project-options.ts
|
|
1246
|
+
function hasRequiredCheck(ai) {
|
|
1247
|
+
return Object.values(ai.execution.checks).some((check) => check.required);
|
|
1248
|
+
}
|
|
1249
|
+
function availableCheckId(checks, preferred) {
|
|
1250
|
+
if (checks[preferred] === void 0) {
|
|
1251
|
+
return preferred;
|
|
1252
|
+
}
|
|
1253
|
+
let suffix = 2;
|
|
1254
|
+
while (checks[`${preferred}-${String(suffix)}`] !== void 0) {
|
|
1255
|
+
suffix += 1;
|
|
1256
|
+
}
|
|
1257
|
+
return `${preferred}-${String(suffix)}`;
|
|
1258
|
+
}
|
|
1259
|
+
async function resolveProjectOptions(input) {
|
|
1260
|
+
const userOptions = input.options ?? {};
|
|
1261
|
+
const resolved = resolveOptions(userOptions, input.environmentAi);
|
|
1262
|
+
if (!userOptions.trustedFastMode || resolved.ai === false) {
|
|
1263
|
+
return resolved;
|
|
1264
|
+
}
|
|
1265
|
+
if (resolved.ai.execution.applyMode === "auto") {
|
|
1266
|
+
throw new RangeError(
|
|
1267
|
+
"SpotPatch trustedFastMode cannot be combined with applyMode auto."
|
|
1268
|
+
);
|
|
1269
|
+
}
|
|
1270
|
+
let checks = resolved.ai.execution.checks;
|
|
1271
|
+
if (!hasRequiredCheck(resolved.ai)) {
|
|
1272
|
+
const discovered = await discoverProjectValidationCheck({
|
|
1273
|
+
appRoot: input.appRoot,
|
|
1274
|
+
timeoutMs: resolved.ai.execution.limits.checkTimeoutMs
|
|
1275
|
+
});
|
|
1276
|
+
if (discovered === void 0) {
|
|
1277
|
+
throw new RangeError(
|
|
1278
|
+
"SpotPatch trustedFastMode requires a configured required check or a local TypeScript project with tsconfig.json."
|
|
1279
|
+
);
|
|
1280
|
+
}
|
|
1281
|
+
const id = availableCheckId(checks, discovered.id);
|
|
1282
|
+
checks = Object.freeze({
|
|
1283
|
+
...checks,
|
|
1284
|
+
[id]: Object.freeze({ ...discovered, id })
|
|
1285
|
+
});
|
|
1286
|
+
}
|
|
1287
|
+
const ai = Object.freeze({
|
|
1288
|
+
...resolved.ai,
|
|
1289
|
+
execution: Object.freeze({
|
|
1290
|
+
...resolved.ai.execution,
|
|
1291
|
+
applyMode: "trusted-auto",
|
|
1292
|
+
checks
|
|
1293
|
+
})
|
|
1294
|
+
});
|
|
1295
|
+
return Object.freeze({ ...resolved, ai });
|
|
1296
|
+
}
|
|
1297
|
+
|
|
958
1298
|
// src/registry/source-registry.ts
|
|
959
|
-
var
|
|
1299
|
+
var import_node_path3 = __toESM(require("path"), 1);
|
|
960
1300
|
|
|
961
1301
|
// src/registry/source-id.ts
|
|
962
|
-
var
|
|
1302
|
+
var import_node_crypto3 = require("crypto");
|
|
963
1303
|
var SOURCE_ID_BYTES = 8;
|
|
964
|
-
var createRandomSourceId = () => (0,
|
|
1304
|
+
var createRandomSourceId = () => (0, import_node_crypto3.randomBytes)(SOURCE_ID_BYTES).toString("base64url");
|
|
965
1305
|
|
|
966
1306
|
// src/registry/source-registry.ts
|
|
967
1307
|
function normalizeAbsolutePath(absolutePath) {
|
|
968
|
-
return
|
|
1308
|
+
return import_node_path3.default.normalize(import_node_path3.default.resolve(absolutePath));
|
|
969
1309
|
}
|
|
970
1310
|
function createSourceRegistry(options = {}) {
|
|
971
1311
|
const createId = options.createId ?? createRandomSourceId;
|
|
@@ -1003,13 +1343,13 @@ var import_shared10 = require("@spotpatch/shared");
|
|
|
1003
1343
|
var import_shared7 = require("@spotpatch/shared");
|
|
1004
1344
|
|
|
1005
1345
|
// src/server/agent-request.ts
|
|
1006
|
-
var
|
|
1007
|
-
var
|
|
1346
|
+
var import_promises5 = require("fs/promises");
|
|
1347
|
+
var import_node_path6 = __toESM(require("path"), 1);
|
|
1008
1348
|
var import_shared5 = require("@spotpatch/shared");
|
|
1009
1349
|
|
|
1010
1350
|
// src/server/source-context.ts
|
|
1011
|
-
var
|
|
1012
|
-
var
|
|
1351
|
+
var import_promises4 = require("fs/promises");
|
|
1352
|
+
var import_node_path5 = __toESM(require("path"), 1);
|
|
1013
1353
|
var import_shared4 = require("@spotpatch/shared");
|
|
1014
1354
|
|
|
1015
1355
|
// src/server/extract-code-context.ts
|
|
@@ -1239,8 +1579,8 @@ function extractCodeContext(options) {
|
|
|
1239
1579
|
}
|
|
1240
1580
|
|
|
1241
1581
|
// src/server/source-file.ts
|
|
1242
|
-
var
|
|
1243
|
-
var
|
|
1582
|
+
var import_promises3 = require("fs/promises");
|
|
1583
|
+
var import_node_path4 = __toESM(require("path"), 1);
|
|
1244
1584
|
var import_shared3 = require("@spotpatch/shared");
|
|
1245
1585
|
|
|
1246
1586
|
// src/server/constants.ts
|
|
@@ -1258,8 +1598,8 @@ async function assertInsideRoot(root, candidate) {
|
|
|
1258
1598
|
let realCandidate;
|
|
1259
1599
|
try {
|
|
1260
1600
|
[realRoot, realCandidate] = await Promise.all([
|
|
1261
|
-
(0,
|
|
1262
|
-
(0,
|
|
1601
|
+
(0, import_promises3.realpath)(root),
|
|
1602
|
+
(0, import_promises3.realpath)(candidate)
|
|
1263
1603
|
]);
|
|
1264
1604
|
} catch (error) {
|
|
1265
1605
|
if (isMissingFileError(error)) {
|
|
@@ -1269,8 +1609,8 @@ async function assertInsideRoot(root, candidate) {
|
|
|
1269
1609
|
}
|
|
1270
1610
|
throw error;
|
|
1271
1611
|
}
|
|
1272
|
-
const relative =
|
|
1273
|
-
const outside = relative.startsWith(`..${
|
|
1612
|
+
const relative = import_node_path4.default.relative(realRoot, realCandidate);
|
|
1613
|
+
const outside = relative.startsWith(`..${import_node_path4.default.sep}`) || relative === ".." || import_node_path4.default.isAbsolute(relative);
|
|
1274
1614
|
if (outside) {
|
|
1275
1615
|
throw new import_shared3.SpotPatchError(import_shared3.ERROR_CODES.SOURCE_OUTSIDE_ROOT);
|
|
1276
1616
|
}
|
|
@@ -1282,12 +1622,12 @@ async function resolveSourceFile(options) {
|
|
|
1282
1622
|
throw new import_shared3.SpotPatchError(import_shared3.ERROR_CODES.SOURCE_NOT_FOUND);
|
|
1283
1623
|
}
|
|
1284
1624
|
const sourcePath = await assertInsideRoot(options.root, registeredPath);
|
|
1285
|
-
if (!ALLOWED_EXTENSIONS.has(
|
|
1625
|
+
if (!ALLOWED_EXTENSIONS.has(import_node_path4.default.extname(sourcePath).toLowerCase())) {
|
|
1286
1626
|
throw new import_shared3.SpotPatchError(import_shared3.ERROR_CODES.SOURCE_NOT_FOUND);
|
|
1287
1627
|
}
|
|
1288
1628
|
let sourceStat;
|
|
1289
1629
|
try {
|
|
1290
|
-
sourceStat = await (0,
|
|
1630
|
+
sourceStat = await (0, import_promises3.stat)(sourcePath);
|
|
1291
1631
|
} catch (error) {
|
|
1292
1632
|
if (isMissingFileError(error)) {
|
|
1293
1633
|
throw new import_shared3.SpotPatchError(import_shared3.ERROR_CODES.SOURCE_NOT_FOUND, void 0, {
|
|
@@ -1307,7 +1647,7 @@ async function resolveSourceFile(options) {
|
|
|
1307
1647
|
|
|
1308
1648
|
// src/server/source-context.ts
|
|
1309
1649
|
function toDisplayPath(root, sourcePath) {
|
|
1310
|
-
return
|
|
1650
|
+
return import_node_path5.default.relative(root, sourcePath).split(import_node_path5.default.sep).join("/");
|
|
1311
1651
|
}
|
|
1312
1652
|
async function readSourceContext(options) {
|
|
1313
1653
|
const sourcePath = await resolveSourceFile({
|
|
@@ -1317,7 +1657,7 @@ async function readSourceContext(options) {
|
|
|
1317
1657
|
});
|
|
1318
1658
|
let source;
|
|
1319
1659
|
try {
|
|
1320
|
-
source = await (0,
|
|
1660
|
+
source = await (0, import_promises4.readFile)(sourcePath, "utf8");
|
|
1321
1661
|
} catch (error) {
|
|
1322
1662
|
if (error instanceof Error && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR")) {
|
|
1323
1663
|
throw new import_shared4.SpotPatchError(import_shared4.ERROR_CODES.SOURCE_NOT_FOUND, void 0, {
|
|
@@ -1330,11 +1670,11 @@ async function readSourceContext(options) {
|
|
|
1330
1670
|
if (options.request.line > lines.length) {
|
|
1331
1671
|
throw new import_shared4.SpotPatchError(import_shared4.ERROR_CODES.INVALID_REQUEST);
|
|
1332
1672
|
}
|
|
1333
|
-
const extension =
|
|
1673
|
+
const extension = import_node_path5.default.extname(sourcePath).toLowerCase();
|
|
1334
1674
|
return extractCodeContext({
|
|
1335
1675
|
source,
|
|
1336
1676
|
sourcePath,
|
|
1337
|
-
relativePath: toDisplayPath(await (0,
|
|
1677
|
+
relativePath: toDisplayPath(await (0, import_promises4.realpath)(options.root), sourcePath),
|
|
1338
1678
|
language: extension === ".tsx" ? "tsx" : "jsx",
|
|
1339
1679
|
line: options.request.line,
|
|
1340
1680
|
column: options.request.column,
|
|
@@ -1370,7 +1710,7 @@ async function authorizeSourceRef(source, registry, root) {
|
|
|
1370
1710
|
registry,
|
|
1371
1711
|
root
|
|
1372
1712
|
});
|
|
1373
|
-
const relativePath =
|
|
1713
|
+
const relativePath = import_node_path6.default.relative(await (0, import_promises5.realpath)(root), sourcePath).split(import_node_path6.default.sep).join("/");
|
|
1374
1714
|
if (source.relativePath !== void 0 && source.relativePath !== relativePath) {
|
|
1375
1715
|
throw new import_shared5.SpotPatchError(import_shared5.ERROR_CODES.INVALID_REQUEST);
|
|
1376
1716
|
}
|
|
@@ -1475,6 +1815,7 @@ async function authorizeAgentJobRequest(input) {
|
|
|
1475
1815
|
});
|
|
1476
1816
|
return Object.freeze({
|
|
1477
1817
|
annotation,
|
|
1818
|
+
...input.request.applyMode === void 0 ? {} : { applyMode: input.request.applyMode },
|
|
1478
1819
|
providerProfileId: input.request.providerProfileId,
|
|
1479
1820
|
modelProfileId: input.request.modelProfileId,
|
|
1480
1821
|
providerDataConsent: true,
|
|
@@ -1541,21 +1882,21 @@ var EVENT_STREAM_END_STATUSES = /* @__PURE__ */ new Set([
|
|
|
1541
1882
|
"reverted",
|
|
1542
1883
|
"failed"
|
|
1543
1884
|
]);
|
|
1544
|
-
function matchAgentRequestPath(
|
|
1545
|
-
if (
|
|
1885
|
+
function matchAgentRequestPath(path8) {
|
|
1886
|
+
if (path8 === import_shared7.SPOTPATCH_ENDPOINTS.agentCapability) {
|
|
1546
1887
|
return Object.freeze({ kind: "capability" });
|
|
1547
1888
|
}
|
|
1548
|
-
if (
|
|
1889
|
+
if (path8 === import_shared7.SPOTPATCH_ENDPOINTS.agentWorkspaceHealth) {
|
|
1549
1890
|
return Object.freeze({ kind: "workspace-health" });
|
|
1550
1891
|
}
|
|
1551
|
-
if (
|
|
1892
|
+
if (path8 === import_shared7.SPOTPATCH_ENDPOINTS.agentJobs) {
|
|
1552
1893
|
return Object.freeze({ kind: "create-job" });
|
|
1553
1894
|
}
|
|
1554
1895
|
const prefix = `${import_shared7.SPOTPATCH_ENDPOINTS.agentJobs}/`;
|
|
1555
|
-
if (!
|
|
1896
|
+
if (!path8.startsWith(prefix)) {
|
|
1556
1897
|
return void 0;
|
|
1557
1898
|
}
|
|
1558
|
-
const segments =
|
|
1899
|
+
const segments = path8.slice(prefix.length).split("/");
|
|
1559
1900
|
const jobId = segments[0];
|
|
1560
1901
|
const action = segments[1];
|
|
1561
1902
|
if (segments.length !== 2 || jobId === void 0 || !AGENT_JOB_ID_PATTERN.test(jobId) || action === void 0 || !AGENT_JOB_ACTIONS.has(action)) {
|
|
@@ -1725,7 +2066,7 @@ async function handleAgentRequest(request, response, options, route, writeSucces
|
|
|
1725
2066
|
}
|
|
1726
2067
|
|
|
1727
2068
|
// src/server/editor.ts
|
|
1728
|
-
var
|
|
2069
|
+
var import_node_child_process2 = require("child_process");
|
|
1729
2070
|
var import_launch_editor = __toESM(require("launch-editor"), 1);
|
|
1730
2071
|
var EDITOR_STARTUP_GRACE_MS = 300;
|
|
1731
2072
|
function normalizedEditorEnvironment(environment) {
|
|
@@ -1752,7 +2093,7 @@ function editorCommand(editor) {
|
|
|
1752
2093
|
var DEFAULT_DEPENDENCIES2 = Object.freeze({
|
|
1753
2094
|
environment: process.env,
|
|
1754
2095
|
fallbackLauncher: import_launch_editor.default,
|
|
1755
|
-
processSpawner: (command, arguments_, options) => (0,
|
|
2096
|
+
processSpawner: (command, arguments_, options) => (0, import_node_child_process2.spawn)(command, [...arguments_], options),
|
|
1756
2097
|
startupGraceMs: EDITOR_STARTUP_GRACE_MS
|
|
1757
2098
|
});
|
|
1758
2099
|
function createEditorLauncher(dependencies = DEFAULT_DEPENDENCIES2) {
|
|
@@ -1810,7 +2151,7 @@ function createEditorLauncher(dependencies = DEFAULT_DEPENDENCIES2) {
|
|
|
1810
2151
|
var launchConfiguredEditor = createEditorLauncher();
|
|
1811
2152
|
|
|
1812
2153
|
// src/server/request-security.ts
|
|
1813
|
-
var
|
|
2154
|
+
var import_node_crypto4 = require("crypto");
|
|
1814
2155
|
var import_node_net = require("net");
|
|
1815
2156
|
var import_shared8 = require("@spotpatch/shared");
|
|
1816
2157
|
function getSingleHeader(request, name) {
|
|
@@ -1823,7 +2164,7 @@ function tokensMatch(actual, expected) {
|
|
|
1823
2164
|
}
|
|
1824
2165
|
const actualBytes = Buffer.from(actual);
|
|
1825
2166
|
const expectedBytes = Buffer.from(expected);
|
|
1826
|
-
return actualBytes.byteLength === expectedBytes.byteLength && (0,
|
|
2167
|
+
return actualBytes.byteLength === expectedBytes.byteLength && (0, import_node_crypto4.timingSafeEqual)(actualBytes, expectedBytes);
|
|
1827
2168
|
}
|
|
1828
2169
|
function isLoopbackHostname(hostname) {
|
|
1829
2170
|
const normalized = hostname.toLowerCase().replace(/^\[|\]$/g, "");
|
|
@@ -2078,14 +2419,14 @@ async function handleOpenEditor(request, options) {
|
|
|
2078
2419
|
function createSpotPatchMiddleware(options) {
|
|
2079
2420
|
const bootstrap = options.bootstrap === void 0 ? void 0 : resolveRuntimeBootstrapOptions(options.bootstrap);
|
|
2080
2421
|
return (request, response, next) => {
|
|
2081
|
-
const
|
|
2082
|
-
const agentRoute = matchAgentRequestPath(
|
|
2083
|
-
if (
|
|
2422
|
+
const path8 = requestPath(request);
|
|
2423
|
+
const agentRoute = matchAgentRequestPath(path8);
|
|
2424
|
+
if (path8 !== import_shared10.SPOTPATCH_ENDPOINTS.sourceContext && path8 !== import_shared10.SPOTPATCH_ENDPOINTS.openEditor && agentRoute === void 0 && !path8.startsWith(`${import_shared10.SPOTPATCH_API_BASE}/`)) {
|
|
2084
2425
|
next();
|
|
2085
2426
|
return;
|
|
2086
2427
|
}
|
|
2087
2428
|
const handle = async () => {
|
|
2088
|
-
if (
|
|
2429
|
+
if (path8 === import_shared10.SPOTPATCH_ENDPOINTS.bootstrap && bootstrap !== void 0) {
|
|
2089
2430
|
const data = await readRuntimeBootstrap(
|
|
2090
2431
|
request,
|
|
2091
2432
|
bootstrap
|
|
@@ -2097,7 +2438,7 @@ function createSpotPatchMiddleware(options) {
|
|
|
2097
2438
|
allowLan: options.options.allowLan,
|
|
2098
2439
|
sessionToken: options.session.token
|
|
2099
2440
|
});
|
|
2100
|
-
if (
|
|
2441
|
+
if (path8 === import_shared10.SPOTPATCH_ENDPOINTS.sourceContext) {
|
|
2101
2442
|
if (request.method !== "POST") {
|
|
2102
2443
|
throw new import_shared10.SpotPatchError(import_shared10.ERROR_CODES.INVALID_REQUEST);
|
|
2103
2444
|
}
|
|
@@ -2105,7 +2446,7 @@ function createSpotPatchMiddleware(options) {
|
|
|
2105
2446
|
writeJson(response, 200, { ok: true, data });
|
|
2106
2447
|
return;
|
|
2107
2448
|
}
|
|
2108
|
-
if (
|
|
2449
|
+
if (path8 === import_shared10.SPOTPATCH_ENDPOINTS.openEditor) {
|
|
2109
2450
|
if (request.method !== "POST") {
|
|
2110
2451
|
throw new import_shared10.SpotPatchError(import_shared10.ERROR_CODES.INVALID_REQUEST);
|
|
2111
2452
|
}
|
|
@@ -2133,9 +2474,9 @@ function createSpotPatchMiddleware(options) {
|
|
|
2133
2474
|
}
|
|
2134
2475
|
|
|
2135
2476
|
// src/server/source-registration.ts
|
|
2136
|
-
var
|
|
2137
|
-
var
|
|
2138
|
-
var
|
|
2477
|
+
var import_node_crypto5 = require("crypto");
|
|
2478
|
+
var import_promises6 = require("fs/promises");
|
|
2479
|
+
var import_node_path7 = __toESM(require("path"), 1);
|
|
2139
2480
|
var import_compiler = require("@spotpatch/compiler");
|
|
2140
2481
|
var import_zod2 = require("zod");
|
|
2141
2482
|
var REGISTRATION_BODY_LIMIT_BYTES = 4096;
|
|
@@ -2156,14 +2497,14 @@ function identitiesMatch(actual, expected) {
|
|
|
2156
2497
|
}
|
|
2157
2498
|
const actualBytes = Buffer.from(actual);
|
|
2158
2499
|
const expectedBytes = Buffer.from(expected);
|
|
2159
|
-
return actualBytes.byteLength === expectedBytes.byteLength && (0,
|
|
2500
|
+
return actualBytes.byteLength === expectedBytes.byteLength && (0, import_node_crypto5.timingSafeEqual)(actualBytes, expectedBytes);
|
|
2160
2501
|
}
|
|
2161
2502
|
function isWithinRoot(root, candidate) {
|
|
2162
|
-
const relative =
|
|
2163
|
-
return relative === "" || !relative.startsWith(`..${
|
|
2503
|
+
const relative = import_node_path7.default.relative(root, candidate);
|
|
2504
|
+
return relative === "" || !relative.startsWith(`..${import_node_path7.default.sep}`) && relative !== ".." && !import_node_path7.default.isAbsolute(relative);
|
|
2164
2505
|
}
|
|
2165
2506
|
function hasForbiddenSegment(root, candidate) {
|
|
2166
|
-
return
|
|
2507
|
+
return import_node_path7.default.relative(root, candidate).split(import_node_path7.default.sep).some((segment) => FORBIDDEN_SOURCE_SEGMENTS.has(segment));
|
|
2167
2508
|
}
|
|
2168
2509
|
function writeJson2(response, statusCode, payload) {
|
|
2169
2510
|
const body = JSON.stringify(payload);
|
|
@@ -2185,15 +2526,15 @@ function requestComesFromLoopbackWorker(request) {
|
|
|
2185
2526
|
}
|
|
2186
2527
|
}
|
|
2187
2528
|
async function resolveAuthorizedSource(root, requestedPath, shouldTransform) {
|
|
2188
|
-
if (!
|
|
2529
|
+
if (!import_node_path7.default.isAbsolute(requestedPath) || requestedPath.includes("\0")) {
|
|
2189
2530
|
return void 0;
|
|
2190
2531
|
}
|
|
2191
2532
|
try {
|
|
2192
|
-
const sourceStat = await (0,
|
|
2533
|
+
const sourceStat = await (0, import_promises6.lstat)(requestedPath);
|
|
2193
2534
|
if (!sourceStat.isFile() || sourceStat.isSymbolicLink()) {
|
|
2194
2535
|
return void 0;
|
|
2195
2536
|
}
|
|
2196
|
-
const resolvedPath = await (0,
|
|
2537
|
+
const resolvedPath = await (0, import_promises6.realpath)(requestedPath);
|
|
2197
2538
|
if (!isWithinRoot(root, resolvedPath) || hasForbiddenSegment(root, resolvedPath) || !shouldTransform(resolvedPath)) {
|
|
2198
2539
|
return void 0;
|
|
2199
2540
|
}
|
|
@@ -2206,7 +2547,7 @@ async function createSourceRegistrationService(input) {
|
|
|
2206
2547
|
if (!REGISTRATION_IDENTITY_PATTERN.test(input.internalSecret) || !REGISTRATION_IDENTITY_PATTERN.test(input.registryEpoch)) {
|
|
2207
2548
|
throw new TypeError("The source registration identity is invalid.");
|
|
2208
2549
|
}
|
|
2209
|
-
const root = await (0,
|
|
2550
|
+
const root = await (0, import_promises6.realpath)(input.root);
|
|
2210
2551
|
const sourceFilter = (0, import_compiler.createSourceFilter)(root, input.options);
|
|
2211
2552
|
const handler = (request, response) => {
|
|
2212
2553
|
const handle = async () => {
|
|
@@ -2251,11 +2592,11 @@ async function createSourceRegistrationService(input) {
|
|
|
2251
2592
|
}
|
|
2252
2593
|
|
|
2253
2594
|
// src/session/session.ts
|
|
2254
|
-
var
|
|
2595
|
+
var import_node_crypto6 = require("crypto");
|
|
2255
2596
|
function createSession() {
|
|
2256
2597
|
return Object.freeze({
|
|
2257
|
-
id: (0,
|
|
2258
|
-
token: (0,
|
|
2598
|
+
id: (0, import_node_crypto6.randomBytes)(16).toString("base64url"),
|
|
2599
|
+
token: (0, import_node_crypto6.randomBytes)(16).toString("base64url")
|
|
2259
2600
|
});
|
|
2260
2601
|
}
|
|
2261
2602
|
|
|
@@ -2283,7 +2624,7 @@ var BUDGET_KEYS = Object.freeze([
|
|
|
2283
2624
|
"maxComponentDepth"
|
|
2284
2625
|
]);
|
|
2285
2626
|
var REGEXP_FLAGS_PATTERN = /^(?!.*(.).*\1)[dgimsuvy]*$/u;
|
|
2286
|
-
function
|
|
2627
|
+
function isRecord2(value) {
|
|
2287
2628
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2288
2629
|
}
|
|
2289
2630
|
function hasExactKeys(value, keys) {
|
|
@@ -2368,7 +2709,7 @@ function parseFilterList(value) {
|
|
|
2368
2709
|
}
|
|
2369
2710
|
return Object.freeze(
|
|
2370
2711
|
value.map((entry) => {
|
|
2371
|
-
if (!
|
|
2712
|
+
if (!isRecord2(entry)) {
|
|
2372
2713
|
throw new TypeError("The SpotPatch filter transport is invalid.");
|
|
2373
2714
|
}
|
|
2374
2715
|
if (entry.kind === "string" && hasExactKeys(entry, ["kind", "value"]) && typeof entry.value === "string" && entry.value.length > 0 && entry.value.length <= 1024 && !entry.value.includes("\0")) {
|
|
@@ -2386,7 +2727,7 @@ function parseFilterList(value) {
|
|
|
2386
2727
|
);
|
|
2387
2728
|
}
|
|
2388
2729
|
function parseBudget(value) {
|
|
2389
|
-
if (!
|
|
2730
|
+
if (!isRecord2(value) || !hasExactKeys(value, BUDGET_KEYS)) {
|
|
2390
2731
|
throw new TypeError("The SpotPatch budget transport is invalid.");
|
|
2391
2732
|
}
|
|
2392
2733
|
const budget = Object.fromEntries(
|
|
@@ -2395,10 +2736,10 @@ function parseBudget(value) {
|
|
|
2395
2736
|
return Object.freeze(budget);
|
|
2396
2737
|
}
|
|
2397
2738
|
function parseSerializedSpotPatchOptions(value) {
|
|
2398
|
-
if (!
|
|
2739
|
+
if (!isRecord2(value) || !hasExactKeys(value, OPTION_KEYS)) {
|
|
2399
2740
|
throw new TypeError("The SpotPatch options transport is invalid.");
|
|
2400
2741
|
}
|
|
2401
|
-
if (typeof value.enabled !== "boolean" || typeof value.redact !== "boolean" || typeof value.allowLan !== "boolean" || typeof value.debug !== "boolean" || typeof value.shortcut !== "string" || typeof value.maxTargets !== "number" || typeof value.editor !== "string" || typeof value.locale !== "string" || value.ai !== false && !
|
|
2742
|
+
if (typeof value.enabled !== "boolean" || typeof value.redact !== "boolean" || typeof value.allowLan !== "boolean" || typeof value.debug !== "boolean" || typeof value.shortcut !== "string" || typeof value.maxTargets !== "number" || typeof value.editor !== "string" || typeof value.locale !== "string" || value.ai !== false && !isRecord2(value.ai)) {
|
|
2402
2743
|
throw new TypeError("The SpotPatch options transport is invalid.");
|
|
2403
2744
|
}
|
|
2404
2745
|
try {
|
|
@@ -2426,19 +2767,25 @@ function parseSerializedSpotPatchOptions(value) {
|
|
|
2426
2767
|
0 && (module.exports = {
|
|
2427
2768
|
DEFAULT_EXCLUDE,
|
|
2428
2769
|
DEFAULT_OPTIONS,
|
|
2770
|
+
applyIntegrationPlan,
|
|
2429
2771
|
createAgentJobManager,
|
|
2772
|
+
createIntegrationFileChange,
|
|
2430
2773
|
createRuntimeAiConfig,
|
|
2431
2774
|
createSession,
|
|
2432
2775
|
createSourceRegistrationService,
|
|
2433
2776
|
createSourceRegistry,
|
|
2434
2777
|
createSpotPatchMiddleware,
|
|
2778
|
+
discoverProjectValidationCheck,
|
|
2779
|
+
integrationPathExists,
|
|
2435
2780
|
isLoopbackHostname,
|
|
2436
2781
|
parseSerializedSpotPatchOptions,
|
|
2782
|
+
readIntegrationFile,
|
|
2437
2783
|
readJsonRequestBody,
|
|
2438
2784
|
readRuntimeBootstrap,
|
|
2439
2785
|
resolveCredentialEnvironment,
|
|
2440
2786
|
resolveEnvironmentAiConfiguration,
|
|
2441
2787
|
resolveOptions,
|
|
2788
|
+
resolveProjectOptions,
|
|
2442
2789
|
resolveRuntimeBootstrapOptions,
|
|
2443
2790
|
serializeResolvedSpotPatchOptions
|
|
2444
2791
|
});
|