@ninjaxtools/slopdex 0.9.0 → 0.10.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/.agents/skills/slopdex/SKILL.md +22 -65
- package/README.md +28 -50
- package/dist/cli.js +72 -39
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.js +33 -7
- package/dist/index.js.map +1 -1
- package/docs/implementation.md +5 -3
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -346,6 +346,13 @@ function pythonIsMethod(node) {
|
|
|
346
346
|
const definition = node.parent?.type === "decorated_definition" ? node.parent : node;
|
|
347
347
|
return definition.parent?.parent?.type === "class_definition";
|
|
348
348
|
}
|
|
349
|
+
function pythonDocstring(body, content) {
|
|
350
|
+
const statement = body?.namedChildren[0];
|
|
351
|
+
if (statement?.type !== "expression_statement") return null;
|
|
352
|
+
const value = statement.namedChildren[0];
|
|
353
|
+
if (value?.type !== "string" && value?.type !== "concatenated_string") return null;
|
|
354
|
+
return content.slice(value.startIndex, value.endIndex);
|
|
355
|
+
}
|
|
349
356
|
function goReceiver(node) {
|
|
350
357
|
let type = node.childForFieldName("receiver")?.namedChildren[0]?.childForFieldName("type");
|
|
351
358
|
while (type?.type === "pointer_type") type = type.namedChildren[0] ?? null;
|
|
@@ -359,12 +366,14 @@ function collectNativeCallables(root, content, language) {
|
|
|
359
366
|
if ((!body || body.isMissing) && !node.hasError) return false;
|
|
360
367
|
const sourceNode = language === "python" && node.parent?.type === "decorated_definition" ? node.parent : node;
|
|
361
368
|
const header = content.slice(node.startIndex, body?.startIndex ?? node.endIndex).trimEnd();
|
|
369
|
+
const documentation = language === "python" && body ? pythonDocstring(body, content) : null;
|
|
362
370
|
candidates.push({
|
|
363
371
|
node: sourceNode,
|
|
364
372
|
name,
|
|
365
373
|
kind,
|
|
366
374
|
scope,
|
|
367
|
-
signature: bound ? `${name} = ${header}` : header
|
|
375
|
+
signature: bound ? `${name} = ${header}` : header,
|
|
376
|
+
...documentation ? { documentation } : {}
|
|
368
377
|
});
|
|
369
378
|
if (body) walk2(body, [...scope, name]);
|
|
370
379
|
return true;
|
|
@@ -789,7 +798,7 @@ function extractCallables(relativePath, content) {
|
|
|
789
798
|
const errors = parseDiagnostics(tree.rootNode, content, relativePath, language, candidates);
|
|
790
799
|
const occurrences = /* @__PURE__ */ new Map();
|
|
791
800
|
const callables = [];
|
|
792
|
-
for (const { node, name, kind, scope, signature: candidateSignature } of candidates) {
|
|
801
|
+
for (const { node, name, kind, scope, signature: candidateSignature, documentation } of candidates) {
|
|
793
802
|
const qualifiedName = [...scope, name].join(".");
|
|
794
803
|
const baseIdentity = `${relativePath}\0${qualifiedName}\0${kind}`;
|
|
795
804
|
const occurrence = occurrences.get(baseIdentity) ?? 0;
|
|
@@ -804,6 +813,8 @@ function extractCallables(relativePath, content) {
|
|
|
804
813
|
`kind: ${kind}`,
|
|
805
814
|
`symbol: ${qualifiedName}`,
|
|
806
815
|
signature ? `signature: ${signature}` : null,
|
|
816
|
+
documentation ? `documentation:
|
|
817
|
+
${documentation}` : null,
|
|
807
818
|
"source:",
|
|
808
819
|
source
|
|
809
820
|
].filter((value) => value !== null).join("\n");
|
|
@@ -1105,6 +1116,13 @@ var IndexDatabase = class {
|
|
|
1105
1116
|
this.#setMetadata("generation", String(expectedGeneration + 1));
|
|
1106
1117
|
});
|
|
1107
1118
|
}
|
|
1119
|
+
disableSummaries() {
|
|
1120
|
+
if (!this.summariesEnabled()) return;
|
|
1121
|
+
this.#transaction(() => {
|
|
1122
|
+
this.#setMetadata("summaries_enabled", "false");
|
|
1123
|
+
this.#setMetadata("generation", String(this.getGeneration() + 1));
|
|
1124
|
+
});
|
|
1125
|
+
}
|
|
1108
1126
|
getWorkingTreeFiles() {
|
|
1109
1127
|
return this.#db.prepare(`
|
|
1110
1128
|
SELECT path, previous_path AS previousPath
|
|
@@ -1988,7 +2006,7 @@ var CodeIndex = class {
|
|
|
1988
2006
|
async #attachEmbeddings(files, signal) {
|
|
1989
2007
|
if (this.#database.summariesEnabled()) {
|
|
1990
2008
|
if (JSON.stringify(this.#database.summaryProfile()) !== JSON.stringify(this.summaryProvider.profile)) {
|
|
1991
|
-
throw new CodeIndexError("Summary provider or model differs from this index; run
|
|
2009
|
+
throw new CodeIndexError("Summary provider or model differs from this index; run summaries enable (useSummaries() in the library) with the new provider first.");
|
|
1992
2010
|
}
|
|
1993
2011
|
await this.#attachSummaries(files, signal);
|
|
1994
2012
|
}
|
|
@@ -2087,8 +2105,12 @@ var CodeIndex = class {
|
|
|
2087
2105
|
}))), this.summaryProvider.profile, generation);
|
|
2088
2106
|
return { summariesCreated, summariesEnabled: true };
|
|
2089
2107
|
}
|
|
2108
|
+
disableSummaries() {
|
|
2109
|
+
this.#database.disableSummaries();
|
|
2110
|
+
return { summariesCreated: 0, summariesEnabled: false };
|
|
2111
|
+
}
|
|
2090
2112
|
async searchSummary(options) {
|
|
2091
|
-
if (!this.#database.summariesEnabled()) throw new CodeIndexError("Summaries are not enabled; run
|
|
2113
|
+
if (!this.#database.summariesEnabled()) throw new CodeIndexError("Summaries are not enabled; run summaries enable first.");
|
|
2092
2114
|
if (!options.query.trim()) throw new CodeIndexError("query must not be empty.");
|
|
2093
2115
|
const limit = options.limit ?? 10;
|
|
2094
2116
|
assertPositiveInteger(limit, "limit");
|
|
@@ -2225,7 +2247,7 @@ function normalizeProfile(profile) {
|
|
|
2225
2247
|
provider: profile.provider,
|
|
2226
2248
|
model: profile.model,
|
|
2227
2249
|
dimensions: profile.dimensions,
|
|
2228
|
-
strategyVersion: profile.strategyVersion ?? "callable-
|
|
2250
|
+
strategyVersion: profile.strategyVersion ?? "callable-v2"
|
|
2229
2251
|
};
|
|
2230
2252
|
}
|
|
2231
2253
|
function emptyStats(checkpoint) {
|
|
@@ -2602,7 +2624,7 @@ var JinaEmbeddingProvider = class {
|
|
|
2602
2624
|
provider: "jina",
|
|
2603
2625
|
model,
|
|
2604
2626
|
dimensions,
|
|
2605
|
-
strategyVersion: "callable-
|
|
2627
|
+
strategyVersion: "callable-v2:code-query-passage"
|
|
2606
2628
|
};
|
|
2607
2629
|
this.#url = options.baseUrl ?? "https://api.jina.ai/v1/embeddings";
|
|
2608
2630
|
}
|
|
@@ -2652,7 +2674,7 @@ var OpenAIEmbeddingProvider = class {
|
|
|
2652
2674
|
const model = options.model ?? "text-embedding-3-large";
|
|
2653
2675
|
const dimensions = options.dimensions ?? 3072;
|
|
2654
2676
|
if (!Number.isInteger(dimensions) || dimensions < 1) throw new Error("dimensions must be a positive integer.");
|
|
2655
|
-
this.profile = { provider: "openai", model, dimensions, strategyVersion: "callable-
|
|
2677
|
+
this.profile = { provider: "openai", model, dimensions, strategyVersion: "callable-v2" };
|
|
2656
2678
|
this.#url = `${(options.baseUrl ?? "https://api.openai.com/v1").replace(/\/$/, "")}/embeddings`;
|
|
2657
2679
|
}
|
|
2658
2680
|
embedDocuments(inputs, options) {
|
|
@@ -2918,8 +2940,9 @@ var parsed = (() => {
|
|
|
2918
2940
|
}
|
|
2919
2941
|
})();
|
|
2920
2942
|
var [command, ...positionals] = parsed.positionals;
|
|
2943
|
+
var summariesAction = command === "summaries" ? positionals[0] : void 0;
|
|
2921
2944
|
if (parsed.values.version) {
|
|
2922
|
-
const version = true ? "0.
|
|
2945
|
+
const version = true ? "0.10.0" : JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8")).version;
|
|
2923
2946
|
process.stdout.write(`${version}
|
|
2924
2947
|
`);
|
|
2925
2948
|
process.exit(0);
|
|
@@ -2962,7 +2985,7 @@ async function main() {
|
|
|
2962
2985
|
if (command === "index-errors") {
|
|
2963
2986
|
const indexPath = path10.resolve(parsed.values.index ?? config.indexPath ?? path10.join(rootDir, ".slopdex/index.sqlite"));
|
|
2964
2987
|
const errors = existsSync(indexPath) ? readIndexErrors(indexPath) : [];
|
|
2965
|
-
if (outputFormat("
|
|
2988
|
+
if (outputFormat("summary") === "summary") {
|
|
2966
2989
|
process.stdout.write(errors.length === 0 ? "No indexing errors.\n" : `${errors.map(
|
|
2967
2990
|
(error) => `${error.path}${error.startLine === null ? "" : `:${error.startLine}:${error.startColumn}`} ${error.qualifiedName ? `:: ${error.qualifiedName} ` : ""}[${error.code}]
|
|
2968
2991
|
${error.message}`
|
|
@@ -2988,12 +3011,15 @@ async function main() {
|
|
|
2988
3011
|
const updateTarget = command === "update-git" ? parsed.values.target ?? "HEAD" : "HEAD";
|
|
2989
3012
|
const { summaryProvider: _summaryProvider, ...refreshOptions } = indexOptions;
|
|
2990
3013
|
const updateStats = await ensureIndexUpdated(
|
|
2991
|
-
command === "
|
|
3014
|
+
command === "summaries" && summariesAction === "enable" ? refreshOptions : indexOptions,
|
|
2992
3015
|
"index",
|
|
2993
3016
|
updateTarget,
|
|
2994
3017
|
parsed.values["rebuild-on-divergence"],
|
|
2995
3018
|
parsed.values["force-reindex"],
|
|
2996
|
-
parsed.values["no-reindex"]
|
|
3019
|
+
parsed.values["no-reindex"],
|
|
3020
|
+
command === "summaries" && summariesAction === "disable" ? (refreshIndex2) => {
|
|
3021
|
+
refreshIndex2.disableSummaries();
|
|
3022
|
+
} : void 0
|
|
2997
3023
|
);
|
|
2998
3024
|
const index = new CodeIndex(indexOptions);
|
|
2999
3025
|
try {
|
|
@@ -3013,22 +3039,23 @@ async function main() {
|
|
|
3013
3039
|
printJson(updateStats);
|
|
3014
3040
|
break;
|
|
3015
3041
|
}
|
|
3016
|
-
case "
|
|
3017
|
-
printJson(await index.useSummaries());
|
|
3042
|
+
case "summaries":
|
|
3043
|
+
printJson(summariesAction === "enable" ? await index.useSummaries() : index.disableSummaries());
|
|
3018
3044
|
break;
|
|
3019
3045
|
case "search":
|
|
3020
3046
|
case "search-summary": {
|
|
3021
3047
|
const query = positionals.join(" ").trim();
|
|
3022
3048
|
if (!query) throw new CodeIndexError(`${command} requires a query.`);
|
|
3023
3049
|
const threshold = similarityThreshold();
|
|
3050
|
+
const nameRegex = qualifiedNameRegex();
|
|
3024
3051
|
const results = await (command === "search-summary" ? index.searchSummary.bind(index) : index.similaritySearch.bind(index))({
|
|
3025
3052
|
query,
|
|
3026
|
-
...
|
|
3053
|
+
...nameRegex !== void 0 ? { nameRegex } : {},
|
|
3027
3054
|
limit: numberOption(parsed.values.limit, 10, "limit"),
|
|
3028
3055
|
minSimilarity: threshold.min,
|
|
3029
3056
|
...threshold.max !== void 0 ? { maxSimilarity: threshold.max } : {}
|
|
3030
3057
|
});
|
|
3031
|
-
const format = outputFormat("
|
|
3058
|
+
const format = outputFormat("summary");
|
|
3032
3059
|
if (format === "clusters") throw new CodeIndexError("clusters format is only available for cross-search.");
|
|
3033
3060
|
if (format === "summary") {
|
|
3034
3061
|
process.stdout.write(`${command === "search-summary" ? results.map((match) => `${formatSimilaritySummary([match])}
|
|
@@ -3049,10 +3076,9 @@ async function main() {
|
|
|
3049
3076
|
limit: positiveIntegerOption(parsed.values.limit, 50, "limit"),
|
|
3050
3077
|
minSimilarity: threshold.min,
|
|
3051
3078
|
...threshold.max !== void 0 ? { maxSimilarity: threshold.max } : {},
|
|
3052
|
-
minLines: minimumLines()
|
|
3053
|
-
...parsed.values.regex !== void 0 ? { nameRegex: parsed.values.regex } : {}
|
|
3079
|
+
minLines: minimumLines()
|
|
3054
3080
|
});
|
|
3055
|
-
const format = outputFormat("
|
|
3081
|
+
const format = outputFormat("summary");
|
|
3056
3082
|
if (format === "clusters") throw new CodeIndexError("clusters format is only available for cross-search.");
|
|
3057
3083
|
if (format === "summary") process.stdout.write(`${formatCohesionSummary(report)}
|
|
3058
3084
|
`);
|
|
@@ -3109,8 +3135,7 @@ async function runCrossSearch(source, sourceOptions, provider) {
|
|
|
3109
3135
|
...threshold.max !== void 0 ? { maxSimilarity: threshold.max } : {},
|
|
3110
3136
|
includeSymmetricDuplicates: parsed.values["include-symmetric-duplicates"],
|
|
3111
3137
|
crossFileOnly: parsed.values["cross-file-only"],
|
|
3112
|
-
minLines: minimumLines()
|
|
3113
|
-
...parsed.values.regex !== void 0 ? { nameRegex: parsed.values.regex } : {}
|
|
3138
|
+
minLines: minimumLines()
|
|
3114
3139
|
};
|
|
3115
3140
|
try {
|
|
3116
3141
|
if (format === "clusters") {
|
|
@@ -3137,13 +3162,14 @@ async function runCrossSearch(source, sourceOptions, provider) {
|
|
|
3137
3162
|
target?.close();
|
|
3138
3163
|
}
|
|
3139
3164
|
}
|
|
3140
|
-
async function ensureIndexUpdated(options, label, target, rebuildOnDivergence, forceRebuild, noReindex) {
|
|
3165
|
+
async function ensureIndexUpdated(options, label, target, rebuildOnDivergence, forceRebuild, noReindex, beforeRefresh) {
|
|
3141
3166
|
diagnosticIndexes.add(resolveIndexPath(options));
|
|
3142
3167
|
const initialized = await initializeMissingIndex(options, label, target, noReindex);
|
|
3143
3168
|
if (initialized) return initialized;
|
|
3144
3169
|
try {
|
|
3145
3170
|
const index = new CodeIndex(options);
|
|
3146
3171
|
try {
|
|
3172
|
+
beforeRefresh?.(index);
|
|
3147
3173
|
return await refreshIndex(index, label, target, rebuildOnDivergence, noReindex);
|
|
3148
3174
|
} finally {
|
|
3149
3175
|
index.close();
|
|
@@ -3274,19 +3300,24 @@ function numberOption(value, defaultValue, name) {
|
|
|
3274
3300
|
return parsedValue;
|
|
3275
3301
|
}
|
|
3276
3302
|
function validateInvocation() {
|
|
3277
|
-
|
|
3303
|
+
const nameRegex = qualifiedNameRegex();
|
|
3304
|
+
if (nameRegex !== void 0) {
|
|
3278
3305
|
if (!["search", "search-summary", "cross-search", "cohesion"].includes(command)) {
|
|
3279
|
-
throw new CodeIndexError("-e/--regexp is only available for search, search-summary, cross-search, and cohesion.");
|
|
3306
|
+
throw new CodeIndexError("-e/--regexp/--regex is only available for search, search-summary, cross-search, and cohesion.");
|
|
3280
3307
|
}
|
|
3281
|
-
compileNameRegex(parsed.values.
|
|
3308
|
+
compileNameRegex(nameRegex, parsed.values.regex !== void 0 ? "--regex value" : "-e/--regexp value");
|
|
3282
3309
|
}
|
|
3283
3310
|
switch (command) {
|
|
3284
3311
|
case "index-errors":
|
|
3285
|
-
if (outputFormat("
|
|
3312
|
+
if (outputFormat("summary") === "clusters") throw new CodeIndexError("clusters format is only available for cross-search.");
|
|
3286
3313
|
return;
|
|
3287
3314
|
case "status":
|
|
3288
3315
|
case "update-git":
|
|
3289
|
-
|
|
3316
|
+
return;
|
|
3317
|
+
case "summaries":
|
|
3318
|
+
if (positionals.length !== 1 || summariesAction !== "enable" && summariesAction !== "disable") {
|
|
3319
|
+
throw new CodeIndexError("summaries requires enable or disable.");
|
|
3320
|
+
}
|
|
3290
3321
|
return;
|
|
3291
3322
|
case "update-files":
|
|
3292
3323
|
if (positionals.length === 0) throw new CodeIndexError("update-files requires at least one path.");
|
|
@@ -3299,7 +3330,7 @@ function validateInvocation() {
|
|
|
3299
3330
|
if (!positionals.join(" ").trim()) throw new CodeIndexError(`${command} requires a query.`);
|
|
3300
3331
|
validateLimit(10);
|
|
3301
3332
|
similarityThreshold();
|
|
3302
|
-
if (outputFormat("
|
|
3333
|
+
if (outputFormat("summary") === "clusters") throw new CodeIndexError("clusters format is only available for cross-search.");
|
|
3303
3334
|
return;
|
|
3304
3335
|
}
|
|
3305
3336
|
case "cross-search":
|
|
@@ -3313,16 +3344,14 @@ function validateInvocation() {
|
|
|
3313
3344
|
similarityThreshold();
|
|
3314
3345
|
outputFormat("clusters");
|
|
3315
3346
|
minimumLines();
|
|
3316
|
-
functionNameRegex();
|
|
3317
3347
|
crossSearchSourceFilter();
|
|
3318
3348
|
return;
|
|
3319
3349
|
case "cohesion":
|
|
3320
3350
|
positiveIntegerOption(parsed.values.limit, 50, "limit");
|
|
3321
3351
|
positiveIntegerOption(parsed.values.neighbors, 20, "neighbors");
|
|
3322
3352
|
cohesionThreshold();
|
|
3323
|
-
if (outputFormat("
|
|
3353
|
+
if (outputFormat("summary") === "clusters") throw new CodeIndexError("clusters format is only available for cross-search.");
|
|
3324
3354
|
minimumLines();
|
|
3325
|
-
functionNameRegex();
|
|
3326
3355
|
crossSearchSourceFilter();
|
|
3327
3356
|
return;
|
|
3328
3357
|
default:
|
|
@@ -3368,15 +3397,19 @@ function minimumLines() {
|
|
|
3368
3397
|
if (!Number.isInteger(value) || value < 1) throw new CodeIndexError("min-lines must be a positive integer.");
|
|
3369
3398
|
return value;
|
|
3370
3399
|
}
|
|
3371
|
-
function
|
|
3372
|
-
|
|
3400
|
+
function qualifiedNameRegex() {
|
|
3401
|
+
if (parsed.values.regexp !== void 0 && parsed.values.regex !== void 0 && parsed.values.regexp !== parsed.values.regex) {
|
|
3402
|
+
throw new CodeIndexError("-e/--regexp and --regex are aliases and cannot use different values.");
|
|
3403
|
+
}
|
|
3404
|
+
return parsed.values.regexp ?? parsed.values.regex;
|
|
3373
3405
|
}
|
|
3374
3406
|
function crossSearchSourceFilter() {
|
|
3375
3407
|
const changedSince = parsed.values["changed-since"];
|
|
3376
3408
|
const uncommitted = parsed.values.uncommitted;
|
|
3409
|
+
const nameRegex = qualifiedNameRegex();
|
|
3377
3410
|
const restrictions = {
|
|
3378
3411
|
...parsed.values["source-path"] ? { path: parsed.values["source-path"] } : {},
|
|
3379
|
-
...
|
|
3412
|
+
...nameRegex !== void 0 ? { nameRegex } : {}
|
|
3380
3413
|
};
|
|
3381
3414
|
if (changedSince) return { type: "changed-since", commit: changedSince, ...uncommitted ? { uncommitted: true } : {}, ...restrictions };
|
|
3382
3415
|
if (uncommitted) return { type: "uncommitted", ...restrictions };
|
|
@@ -3439,7 +3472,7 @@ Commands:
|
|
|
3439
3472
|
delete-files <path...> Remove specific files from the index
|
|
3440
3473
|
update-git Index a Git snapshot plus working-tree changes
|
|
3441
3474
|
search <query> Search functions by semantic similarity
|
|
3442
|
-
|
|
3475
|
+
summaries <enable|disable> Enable or disable automatic purpose summaries
|
|
3443
3476
|
search-summary <query> Search functions using summary embeddings
|
|
3444
3477
|
cross-search Find nearest functions for each source function
|
|
3445
3478
|
cohesion Rank related functions separated across the repository
|
|
@@ -3543,13 +3576,13 @@ Options:
|
|
|
3543
3576
|
--limit <number> Search result limit
|
|
3544
3577
|
--neighbors <number> Semantic neighbors per function for cohesion (default: 20)
|
|
3545
3578
|
--threshold <number|range> Show similarities at/above a value or within a range
|
|
3546
|
-
--format <json|summary|clusters> Output format (
|
|
3579
|
+
--format <json|summary|clusters> Output format (default: summary; cross-search: clusters)
|
|
3547
3580
|
--include-source Include function source in cohesion JSON
|
|
3548
3581
|
--include-symmetric-duplicates Show both directions of same-index matches
|
|
3549
3582
|
--cross-file-only Exclude matches from the source file
|
|
3550
3583
|
--min-lines <number> Minimum callable length for cross-search (default: 2)
|
|
3551
3584
|
-e, --regexp <regex> Filter qualified symbols (analysis: sources only)
|
|
3552
|
-
--regex <regex>
|
|
3585
|
+
--regex <regex> Alias for -e/--regexp
|
|
3553
3586
|
--changed-since <commit> Search added, modified, or moved functions
|
|
3554
3587
|
--uncommitted Search functions from uncommitted files
|
|
3555
3588
|
--source-path <path> Restrict cross-search sources to a file or directory
|
|
@@ -3577,7 +3610,7 @@ Other Examples:
|
|
|
3577
3610
|
slopdex search "validate an authenticated session" --limit 10
|
|
3578
3611
|
|
|
3579
3612
|
Enable purpose summaries, then search by their meaning:
|
|
3580
|
-
slopdex
|
|
3613
|
+
slopdex summaries enable
|
|
3581
3614
|
slopdex search-summary "maintain the repository index" --format summary
|
|
3582
3615
|
|
|
3583
3616
|
Review functions under a path against the whole codebase:
|
|
@@ -3592,10 +3625,10 @@ Other Examples:
|
|
|
3592
3625
|
Filter semantic search results by qualified symbol before applying the limit:
|
|
3593
3626
|
slopdex search "validate session" -e '^Session\\.' --limit 10
|
|
3594
3627
|
|
|
3595
|
-
-e/--regexp uses a case-sensitive JavaScript regex on qualified names. For cross-search
|
|
3628
|
+
-e/--regexp/--regex uses a case-sensitive JavaScript regex on qualified names. For cross-search
|
|
3596
3629
|
and cohesion it filters sources only; targets keep their normal eligibility rules.
|
|
3597
3630
|
With --changed-since and --uncommitted, sources must be changed since the commit and
|
|
3598
|
-
belong to an uncommitted file. --source-path and
|
|
3631
|
+
belong to an uncommitted file. --source-path and the regex filter further narrow that intersection.
|
|
3599
3632
|
`);
|
|
3600
3633
|
}
|
|
3601
3634
|
//# sourceMappingURL=cli.js.map
|