@c4a/extract 0.6.0-beta.4 → 0.6.0-beta.6
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/README.md +6 -1
- package/bin/c4a-extract-code.js +87 -1
- package/index.js +115 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -131,7 +131,7 @@ When `snapshot` input is provided, the runner builds these files:
|
|
|
131
131
|
During projection, code-owned Sections receive code `source_ref` values derived from these rows:
|
|
132
132
|
|
|
133
133
|
- package rows: `src-N#package:<package>@<hash>`
|
|
134
|
-
- symbol rows: `src-N#symbol:<
|
|
134
|
+
- symbol rows: `src-N#symbol:<file>:<symbol>:<kind>@<hash>`
|
|
135
135
|
|
|
136
136
|
These refs are verified against the raw code snapshot JSONL indexes. They are
|
|
137
137
|
separate from prose evidence refs, because code snapshots use
|
|
@@ -212,6 +212,11 @@ project flow: better symbols/relations produce better draft candidates, stable
|
|
|
212
212
|
`repo:<source>#symbol:...` source refs, review evidence, approved Markdown, and
|
|
213
213
|
package output.
|
|
214
214
|
|
|
215
|
+
Approved codegraph Markdown localizes canonical refs as
|
|
216
|
+
`src-N#symbol:<file>:<symbol>:<kind>@<digest>`. The file segment is part of the
|
|
217
|
+
deterministic evidence identity used by verification; agents copy the complete
|
|
218
|
+
ref as an opaque token.
|
|
219
|
+
|
|
215
220
|
## Development
|
|
216
221
|
|
|
217
222
|
```bash
|
package/bin/c4a-extract-code.js
CHANGED
|
@@ -14298,9 +14298,77 @@ var detectModuleAt = async (repoPath, modulePath, ref, pathFilter2) => {
|
|
|
14298
14298
|
return buildModule(repoRoot, moduleDir, name, nestedSet, ref, pathFilter2, gitFiles);
|
|
14299
14299
|
};
|
|
14300
14300
|
|
|
14301
|
+
// src/errors.ts
|
|
14302
|
+
var NO_ENTRY_DETECTED = "NO_ENTRY_DETECTED";
|
|
14303
|
+
|
|
14304
|
+
class ExtractionInputError extends Error {
|
|
14305
|
+
code;
|
|
14306
|
+
detail;
|
|
14307
|
+
constructor(code, message, detail) {
|
|
14308
|
+
super(message);
|
|
14309
|
+
this.name = "ExtractionInputError";
|
|
14310
|
+
this.code = code;
|
|
14311
|
+
this.detail = detail;
|
|
14312
|
+
}
|
|
14313
|
+
}
|
|
14314
|
+
|
|
14301
14315
|
// src/repository.ts
|
|
14302
14316
|
var PACKAGE_JSON = "package.json";
|
|
14303
14317
|
var toPosixPath2 = (value) => value.split(path2.sep).join("/");
|
|
14318
|
+
function safeSourceRelativePath(value) {
|
|
14319
|
+
const slashPath = value.trim().replace(/\\/gu, "/");
|
|
14320
|
+
const normalized = path2.posix.normalize(slashPath).replace(/^\.\//u, "");
|
|
14321
|
+
if (normalized.length === 0 || normalized === "." || normalized === ".." || normalized.startsWith("../") || normalized.startsWith("/") || /^[A-Za-z]:\//u.test(normalized)) {
|
|
14322
|
+
throw new Error(`Extraction entry must be a source-relative file path: ${value}`);
|
|
14323
|
+
}
|
|
14324
|
+
return normalized;
|
|
14325
|
+
}
|
|
14326
|
+
function moduleRelativeEntryPath(modulePath, sourcePath) {
|
|
14327
|
+
if (modulePath === ".")
|
|
14328
|
+
return sourcePath;
|
|
14329
|
+
const prefix = `${normalizeRelativePath(modulePath)}/`;
|
|
14330
|
+
if (!sourcePath.startsWith(prefix)) {
|
|
14331
|
+
throw new Error(`Extraction entry is outside the selected module ${modulePath}: ${sourcePath}`);
|
|
14332
|
+
}
|
|
14333
|
+
return sourcePath.slice(prefix.length);
|
|
14334
|
+
}
|
|
14335
|
+
function entrySubpath(filePath, index) {
|
|
14336
|
+
if (index === 0)
|
|
14337
|
+
return ".";
|
|
14338
|
+
const withoutExtension = filePath.replace(/\.(?:d\.)?(?:ts|tsx|mts|cts)$/u, "");
|
|
14339
|
+
return `./${withoutExtension}`;
|
|
14340
|
+
}
|
|
14341
|
+
function selectedEntryFiles(input) {
|
|
14342
|
+
const selection = input.selection ?? { mode: "auto" };
|
|
14343
|
+
const includedSourceFiles = new Set(input.module.files.map(safeSourceRelativePath));
|
|
14344
|
+
if (selection.mode === "auto") {
|
|
14345
|
+
if (input.detected.entries.length === 0) {
|
|
14346
|
+
throw new ExtractionInputError(NO_ENTRY_DETECTED, 'No TypeScript entry files were detected from package.json. Configure extractTs entries in the Context project, or use mode: "scan"; do not modify the source repository solely for Context.', { mode: "auto", module: input.module.path });
|
|
14347
|
+
}
|
|
14348
|
+
for (const entry of input.detected.entries) {
|
|
14349
|
+
const sourcePath = input.module.path === "." ? safeSourceRelativePath(entry.path) : safeSourceRelativePath(`${input.module.path}/${entry.path}`);
|
|
14350
|
+
if (!includedSourceFiles.has(sourcePath)) {
|
|
14351
|
+
throw new Error(`Auto-detected entry is outside extractTs include: ${sourcePath}. Update include or configure entries in the Context project.`);
|
|
14352
|
+
}
|
|
14353
|
+
}
|
|
14354
|
+
return input.detected.entries;
|
|
14355
|
+
}
|
|
14356
|
+
const sourceEntries = selection.mode === "scan" ? [...includedSourceFiles].sort() : [...new Set(selection.entries.map(safeSourceRelativePath))];
|
|
14357
|
+
if (sourceEntries.length === 0) {
|
|
14358
|
+
throw new ExtractionInputError(NO_ENTRY_DETECTED, selection.mode === "scan" ? "No TypeScript files match extractTs include for scan mode." : "extractTs entries must contain at least one source-relative file path.", { mode: selection.mode, module: input.module.path });
|
|
14359
|
+
}
|
|
14360
|
+
return sourceEntries.map((sourcePath, index) => {
|
|
14361
|
+
if (!includedSourceFiles.has(sourcePath)) {
|
|
14362
|
+
throw new Error(`Configured extraction entry is missing or outside extractTs include: ${sourcePath}. Update entries or include in the Context project.`);
|
|
14363
|
+
}
|
|
14364
|
+
const modulePath = moduleRelativeEntryPath(input.module.path, sourcePath);
|
|
14365
|
+
return {
|
|
14366
|
+
path: modulePath,
|
|
14367
|
+
subpath: entrySubpath(modulePath, index),
|
|
14368
|
+
type: "library"
|
|
14369
|
+
};
|
|
14370
|
+
});
|
|
14371
|
+
}
|
|
14304
14372
|
var normalizeRelativePath = (value) => {
|
|
14305
14373
|
const normalized = toPosixPath2(value).replace(/^\.\/+/, "").replace(/\/+/g, "/");
|
|
14306
14374
|
return normalized || ".";
|
|
@@ -14468,7 +14536,15 @@ var runRepositoryExtraction = async (input) => {
|
|
|
14468
14536
|
module_name: module.name,
|
|
14469
14537
|
module_path: module.path
|
|
14470
14538
|
});
|
|
14471
|
-
const
|
|
14539
|
+
const detectedEntries = await plugin.detectEntries(manifest, fs);
|
|
14540
|
+
const entryDetection = {
|
|
14541
|
+
...detectedEntries,
|
|
14542
|
+
entries: selectedEntryFiles({
|
|
14543
|
+
module,
|
|
14544
|
+
detected: detectedEntries,
|
|
14545
|
+
...input.entrySelection !== undefined ? { selection: input.entrySelection } : {}
|
|
14546
|
+
})
|
|
14547
|
+
};
|
|
14472
14548
|
input.onProgress?.({ phase: "parsing", progress: 20, module_name: module.name, module_path: module.path });
|
|
14473
14549
|
const moduleDoc = await extractModuleDoc(entryDetection, fs);
|
|
14474
14550
|
const rawExtraction = await plugin.extractSymbols(entryDetection.entries, fs);
|
|
@@ -14491,6 +14567,11 @@ var pluginSpecSchema = exports_external.object({
|
|
|
14491
14567
|
package: exports_external.string().min(1),
|
|
14492
14568
|
exportName: exports_external.string().min(1).optional()
|
|
14493
14569
|
});
|
|
14570
|
+
var entrySelectionSchema = exports_external.discriminatedUnion("mode", [
|
|
14571
|
+
exports_external.object({ mode: exports_external.literal("auto") }),
|
|
14572
|
+
exports_external.object({ mode: exports_external.literal("configured"), entries: exports_external.array(exports_external.string().min(1)) }),
|
|
14573
|
+
exports_external.object({ mode: exports_external.literal("scan") })
|
|
14574
|
+
]);
|
|
14494
14575
|
var codeExtractRunnerInputSchema = exports_external.object({
|
|
14495
14576
|
repoPath: exports_external.string().min(1),
|
|
14496
14577
|
modules: exports_external.array(exports_external.string().min(1)).optional(),
|
|
@@ -14498,6 +14579,7 @@ var codeExtractRunnerInputSchema = exports_external.object({
|
|
|
14498
14579
|
commitHash: exports_external.string().min(1).nullable().optional(),
|
|
14499
14580
|
moduleCommits: exports_external.record(exports_external.string().nullable()).optional(),
|
|
14500
14581
|
pathFilter: PathFilterConfigSchema.optional(),
|
|
14582
|
+
entrySelection: entrySelectionSchema.optional(),
|
|
14501
14583
|
plugins: exports_external.array(pluginSpecSchema).min(1),
|
|
14502
14584
|
snapshot: exports_external.object({
|
|
14503
14585
|
sourceId: exports_external.string().min(1),
|
|
@@ -14552,6 +14634,9 @@ var loadRunnerPlugins = async (pluginSpecs, cwd = process.cwd()) => {
|
|
|
14552
14634
|
};
|
|
14553
14635
|
var runCodeExtractRunner = async (rawInput, cwd = process.cwd()) => {
|
|
14554
14636
|
const input = codeExtractRunnerInputSchema.parse(rawInput);
|
|
14637
|
+
if (input.entrySelection?.mode === "configured" && input.entrySelection.entries.length === 0) {
|
|
14638
|
+
throw new ExtractionInputError(NO_ENTRY_DETECTED, "Configured extraction entries must contain at least one source-relative file path.", { mode: "configured" });
|
|
14639
|
+
}
|
|
14555
14640
|
const events = [];
|
|
14556
14641
|
const plugins = await loadRunnerPlugins(input.plugins, cwd);
|
|
14557
14642
|
const extraction = await runRepositoryExtraction({
|
|
@@ -14561,6 +14646,7 @@ var runCodeExtractRunner = async (rawInput, cwd = process.cwd()) => {
|
|
|
14561
14646
|
...input.commitHash !== undefined ? { commitHash: input.commitHash } : {},
|
|
14562
14647
|
...input.moduleCommits ? { moduleCommits: input.moduleCommits } : {},
|
|
14563
14648
|
...input.pathFilter ? { pathFilter: input.pathFilter } : {},
|
|
14649
|
+
...input.entrySelection ? { entrySelection: input.entrySelection } : {},
|
|
14564
14650
|
plugins,
|
|
14565
14651
|
onProgress: (event) => events.push({ type: "progress", ...event })
|
|
14566
14652
|
});
|
package/index.js
CHANGED
|
@@ -15474,7 +15474,8 @@ var DEFAULT_SOURCE_SPAN_HASH_LENGTH = 12;
|
|
|
15474
15474
|
var BOM = "\uFEFF";
|
|
15475
15475
|
var HASH_ID_RE = /^(?:sha256:)?[a-f0-9]{64}$/u;
|
|
15476
15476
|
var SOURCE_SPAN_HASH_RE = /^[a-f0-9]{8,64}$/u;
|
|
15477
|
-
var
|
|
15477
|
+
var DOCUMENT_SOURCE_SLUG_RE = /^[a-z0-9][a-z0-9._-]*$/u;
|
|
15478
|
+
var DOCUMENT_SOURCE_BATCH_RE = /^\d{8}\/[a-z0-9][a-z0-9._-]*$/u;
|
|
15478
15479
|
function isRecord(value) {
|
|
15479
15480
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
15480
15481
|
}
|
|
@@ -15499,8 +15500,20 @@ function assertDocumentSourceType(value) {
|
|
|
15499
15500
|
}
|
|
15500
15501
|
function normalizeDocumentSourceName(name) {
|
|
15501
15502
|
const value = name.trim();
|
|
15502
|
-
if (!
|
|
15503
|
-
throw new TypeError(`document source name must be a lowercase path-safe slug: ${name}`);
|
|
15503
|
+
if (!DOCUMENT_SOURCE_SLUG_RE.test(value) && !DOCUMENT_SOURCE_BATCH_RE.test(value)) {
|
|
15504
|
+
throw new TypeError(`document source name must be a lowercase path-safe slug or YYYYMMDD/module identity: ${name}`);
|
|
15505
|
+
}
|
|
15506
|
+
if (DOCUMENT_SOURCE_BATCH_RE.test(value)) {
|
|
15507
|
+
const dateName = value.slice(0, 8);
|
|
15508
|
+
const year = Number(dateName.slice(0, 4));
|
|
15509
|
+
const month = Number(dateName.slice(4, 6));
|
|
15510
|
+
const day = Number(dateName.slice(6, 8));
|
|
15511
|
+
const date = new Date(0);
|
|
15512
|
+
date.setUTCHours(0, 0, 0, 0);
|
|
15513
|
+
date.setUTCFullYear(year, month - 1, day);
|
|
15514
|
+
if (date.getUTCFullYear() !== year || date.getUTCMonth() !== month - 1 || date.getUTCDate() !== day) {
|
|
15515
|
+
throw new TypeError(`document source batch must be a valid calendar date: ${name}`);
|
|
15516
|
+
}
|
|
15504
15517
|
}
|
|
15505
15518
|
return value;
|
|
15506
15519
|
}
|
|
@@ -15530,14 +15543,20 @@ function decodeSnapshotLocatorPath(path2) {
|
|
|
15530
15543
|
}
|
|
15531
15544
|
}
|
|
15532
15545
|
function parseDocumentSourceLocator(source2) {
|
|
15533
|
-
const match = /^(file|lark):(
|
|
15534
|
-
if (match?.[1] === undefined || match[2] === undefined
|
|
15546
|
+
const match = /^(file|lark):(.+)$/u.exec(source2);
|
|
15547
|
+
if (match?.[1] === undefined || match[2] === undefined)
|
|
15548
|
+
return null;
|
|
15549
|
+
const segments = match[2].split("/");
|
|
15550
|
+
const batched = /^\d{8}$/u.test(segments[0] ?? "") && segments.length >= 3;
|
|
15551
|
+
const sourceName = batched ? `${segments[0]}/${segments[1]}` : segments[0];
|
|
15552
|
+
const documentPath = segments.slice(batched ? 2 : 1).join("/");
|
|
15553
|
+
if (sourceName === undefined || documentPath.length === 0)
|
|
15535
15554
|
return null;
|
|
15536
15555
|
try {
|
|
15537
15556
|
return {
|
|
15538
15557
|
sourceType: match[1],
|
|
15539
|
-
sourceName: normalizeDocumentSourceName(
|
|
15540
|
-
documentPath: decodeSnapshotLocatorPath(
|
|
15558
|
+
sourceName: normalizeDocumentSourceName(sourceName),
|
|
15559
|
+
documentPath: decodeSnapshotLocatorPath(documentPath)
|
|
15541
15560
|
};
|
|
15542
15561
|
} catch {
|
|
15543
15562
|
return null;
|
|
@@ -16405,9 +16424,77 @@ var detectModuleAt = async (repoPath, modulePath, ref, pathFilter2) => {
|
|
|
16405
16424
|
return buildModule(repoRoot, moduleDir, name, nestedSet, ref, pathFilter2, gitFiles);
|
|
16406
16425
|
};
|
|
16407
16426
|
|
|
16427
|
+
// src/errors.ts
|
|
16428
|
+
var NO_ENTRY_DETECTED = "NO_ENTRY_DETECTED";
|
|
16429
|
+
|
|
16430
|
+
class ExtractionInputError extends Error {
|
|
16431
|
+
code;
|
|
16432
|
+
detail;
|
|
16433
|
+
constructor(code, message, detail) {
|
|
16434
|
+
super(message);
|
|
16435
|
+
this.name = "ExtractionInputError";
|
|
16436
|
+
this.code = code;
|
|
16437
|
+
this.detail = detail;
|
|
16438
|
+
}
|
|
16439
|
+
}
|
|
16440
|
+
|
|
16408
16441
|
// src/repository.ts
|
|
16409
16442
|
var PACKAGE_JSON = "package.json";
|
|
16410
16443
|
var toPosixPath2 = (value) => value.split(path2.sep).join("/");
|
|
16444
|
+
function safeSourceRelativePath(value) {
|
|
16445
|
+
const slashPath = value.trim().replace(/\\/gu, "/");
|
|
16446
|
+
const normalized = path2.posix.normalize(slashPath).replace(/^\.\//u, "");
|
|
16447
|
+
if (normalized.length === 0 || normalized === "." || normalized === ".." || normalized.startsWith("../") || normalized.startsWith("/") || /^[A-Za-z]:\//u.test(normalized)) {
|
|
16448
|
+
throw new Error(`Extraction entry must be a source-relative file path: ${value}`);
|
|
16449
|
+
}
|
|
16450
|
+
return normalized;
|
|
16451
|
+
}
|
|
16452
|
+
function moduleRelativeEntryPath(modulePath, sourcePath) {
|
|
16453
|
+
if (modulePath === ".")
|
|
16454
|
+
return sourcePath;
|
|
16455
|
+
const prefix = `${normalizeRelativePath(modulePath)}/`;
|
|
16456
|
+
if (!sourcePath.startsWith(prefix)) {
|
|
16457
|
+
throw new Error(`Extraction entry is outside the selected module ${modulePath}: ${sourcePath}`);
|
|
16458
|
+
}
|
|
16459
|
+
return sourcePath.slice(prefix.length);
|
|
16460
|
+
}
|
|
16461
|
+
function entrySubpath(filePath, index) {
|
|
16462
|
+
if (index === 0)
|
|
16463
|
+
return ".";
|
|
16464
|
+
const withoutExtension = filePath.replace(/\.(?:d\.)?(?:ts|tsx|mts|cts)$/u, "");
|
|
16465
|
+
return `./${withoutExtension}`;
|
|
16466
|
+
}
|
|
16467
|
+
function selectedEntryFiles(input) {
|
|
16468
|
+
const selection = input.selection ?? { mode: "auto" };
|
|
16469
|
+
const includedSourceFiles = new Set(input.module.files.map(safeSourceRelativePath));
|
|
16470
|
+
if (selection.mode === "auto") {
|
|
16471
|
+
if (input.detected.entries.length === 0) {
|
|
16472
|
+
throw new ExtractionInputError(NO_ENTRY_DETECTED, 'No TypeScript entry files were detected from package.json. Configure extractTs entries in the Context project, or use mode: "scan"; do not modify the source repository solely for Context.', { mode: "auto", module: input.module.path });
|
|
16473
|
+
}
|
|
16474
|
+
for (const entry of input.detected.entries) {
|
|
16475
|
+
const sourcePath = input.module.path === "." ? safeSourceRelativePath(entry.path) : safeSourceRelativePath(`${input.module.path}/${entry.path}`);
|
|
16476
|
+
if (!includedSourceFiles.has(sourcePath)) {
|
|
16477
|
+
throw new Error(`Auto-detected entry is outside extractTs include: ${sourcePath}. Update include or configure entries in the Context project.`);
|
|
16478
|
+
}
|
|
16479
|
+
}
|
|
16480
|
+
return input.detected.entries;
|
|
16481
|
+
}
|
|
16482
|
+
const sourceEntries = selection.mode === "scan" ? [...includedSourceFiles].sort() : [...new Set(selection.entries.map(safeSourceRelativePath))];
|
|
16483
|
+
if (sourceEntries.length === 0) {
|
|
16484
|
+
throw new ExtractionInputError(NO_ENTRY_DETECTED, selection.mode === "scan" ? "No TypeScript files match extractTs include for scan mode." : "extractTs entries must contain at least one source-relative file path.", { mode: selection.mode, module: input.module.path });
|
|
16485
|
+
}
|
|
16486
|
+
return sourceEntries.map((sourcePath, index) => {
|
|
16487
|
+
if (!includedSourceFiles.has(sourcePath)) {
|
|
16488
|
+
throw new Error(`Configured extraction entry is missing or outside extractTs include: ${sourcePath}. Update entries or include in the Context project.`);
|
|
16489
|
+
}
|
|
16490
|
+
const modulePath = moduleRelativeEntryPath(input.module.path, sourcePath);
|
|
16491
|
+
return {
|
|
16492
|
+
path: modulePath,
|
|
16493
|
+
subpath: entrySubpath(modulePath, index),
|
|
16494
|
+
type: "library"
|
|
16495
|
+
};
|
|
16496
|
+
});
|
|
16497
|
+
}
|
|
16411
16498
|
var normalizeRelativePath = (value) => {
|
|
16412
16499
|
const normalized = toPosixPath2(value).replace(/^\.\/+/, "").replace(/\/+/g, "/");
|
|
16413
16500
|
return normalized || ".";
|
|
@@ -16575,7 +16662,15 @@ var runRepositoryExtraction = async (input) => {
|
|
|
16575
16662
|
module_name: module2.name,
|
|
16576
16663
|
module_path: module2.path
|
|
16577
16664
|
});
|
|
16578
|
-
const
|
|
16665
|
+
const detectedEntries = await plugin.detectEntries(manifest, fs2);
|
|
16666
|
+
const entryDetection = {
|
|
16667
|
+
...detectedEntries,
|
|
16668
|
+
entries: selectedEntryFiles({
|
|
16669
|
+
module: module2,
|
|
16670
|
+
detected: detectedEntries,
|
|
16671
|
+
...input.entrySelection !== undefined ? { selection: input.entrySelection } : {}
|
|
16672
|
+
})
|
|
16673
|
+
};
|
|
16579
16674
|
input.onProgress?.({ phase: "parsing", progress: 20, module_name: module2.name, module_path: module2.path });
|
|
16580
16675
|
const moduleDoc = await extractModuleDoc(entryDetection, fs2);
|
|
16581
16676
|
const rawExtraction = await plugin.extractSymbols(entryDetection.entries, fs2);
|
|
@@ -16920,6 +17015,11 @@ var pluginSpecSchema = exports_external.object({
|
|
|
16920
17015
|
package: exports_external.string().min(1),
|
|
16921
17016
|
exportName: exports_external.string().min(1).optional()
|
|
16922
17017
|
});
|
|
17018
|
+
var entrySelectionSchema = exports_external.discriminatedUnion("mode", [
|
|
17019
|
+
exports_external.object({ mode: exports_external.literal("auto") }),
|
|
17020
|
+
exports_external.object({ mode: exports_external.literal("configured"), entries: exports_external.array(exports_external.string().min(1)) }),
|
|
17021
|
+
exports_external.object({ mode: exports_external.literal("scan") })
|
|
17022
|
+
]);
|
|
16923
17023
|
var codeExtractRunnerInputSchema = exports_external.object({
|
|
16924
17024
|
repoPath: exports_external.string().min(1),
|
|
16925
17025
|
modules: exports_external.array(exports_external.string().min(1)).optional(),
|
|
@@ -16927,6 +17027,7 @@ var codeExtractRunnerInputSchema = exports_external.object({
|
|
|
16927
17027
|
commitHash: exports_external.string().min(1).nullable().optional(),
|
|
16928
17028
|
moduleCommits: exports_external.record(exports_external.string().nullable()).optional(),
|
|
16929
17029
|
pathFilter: PathFilterConfigSchema.optional(),
|
|
17030
|
+
entrySelection: entrySelectionSchema.optional(),
|
|
16930
17031
|
plugins: exports_external.array(pluginSpecSchema).min(1),
|
|
16931
17032
|
snapshot: exports_external.object({
|
|
16932
17033
|
sourceId: exports_external.string().min(1),
|
|
@@ -16981,6 +17082,9 @@ var loadRunnerPlugins = async (pluginSpecs, cwd = process.cwd()) => {
|
|
|
16981
17082
|
};
|
|
16982
17083
|
var runCodeExtractRunner = async (rawInput, cwd = process.cwd()) => {
|
|
16983
17084
|
const input = codeExtractRunnerInputSchema.parse(rawInput);
|
|
17085
|
+
if (input.entrySelection?.mode === "configured" && input.entrySelection.entries.length === 0) {
|
|
17086
|
+
throw new ExtractionInputError(NO_ENTRY_DETECTED, "Configured extraction entries must contain at least one source-relative file path.", { mode: "configured" });
|
|
17087
|
+
}
|
|
16984
17088
|
const events = [];
|
|
16985
17089
|
const plugins = await loadRunnerPlugins(input.plugins, cwd);
|
|
16986
17090
|
const extraction = await runRepositoryExtraction({
|
|
@@ -16990,6 +17094,7 @@ var runCodeExtractRunner = async (rawInput, cwd = process.cwd()) => {
|
|
|
16990
17094
|
...input.commitHash !== undefined ? { commitHash: input.commitHash } : {},
|
|
16991
17095
|
...input.moduleCommits ? { moduleCommits: input.moduleCommits } : {},
|
|
16992
17096
|
...input.pathFilter ? { pathFilter: input.pathFilter } : {},
|
|
17097
|
+
...input.entrySelection ? { entrySelection: input.entrySelection } : {},
|
|
16993
17098
|
plugins,
|
|
16994
17099
|
onProgress: (event) => events.push({ type: "progress", ...event })
|
|
16995
17100
|
});
|
|
@@ -17237,7 +17342,9 @@ export {
|
|
|
17237
17342
|
buildCodeSnapshot,
|
|
17238
17343
|
SCAN_EXCLUDED_DIRS,
|
|
17239
17344
|
PACKAGE_JSON,
|
|
17345
|
+
NO_ENTRY_DETECTED,
|
|
17240
17346
|
ExtractionPluginRegistry,
|
|
17347
|
+
ExtractionInputError,
|
|
17241
17348
|
DOCUMENT_SNAPSHOT_MANIFEST_SCHEMA_VERSION,
|
|
17242
17349
|
DOCUMENT_EVIDENCE_NORMALIZER_VERSION,
|
|
17243
17350
|
DEFAULT_SOURCE_SPAN_HASH_LENGTH,
|