open-codebase-index 0.22.4 → 0.23.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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/dist/cli.cjs +983 -482
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +984 -483
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +888 -398
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +889 -399
- package/dist/index.js.map +1 -1
- package/dist/pi-extension.cjs +40 -98
- package/dist/pi-extension.cjs.map +1 -1
- package/dist/pi-extension.js +40 -98
- package/dist/pi-extension.js.map +1 -1
- package/native/codebase-index-native.darwin-arm64.node +0 -0
- package/native/codebase-index-native.darwin-x64.node +0 -0
- package/native/codebase-index-native.linux-arm64-gnu.node +0 -0
- package/native/codebase-index-native.linux-x64-gnu.node +0 -0
- package/native/codebase-index-native.win32-x64-msvc.node +0 -0
- package/package.json +3 -1
package/dist/cli.cjs
CHANGED
|
@@ -496,7 +496,7 @@ var require_ignore = __commonJS({
|
|
|
496
496
|
// path matching.
|
|
497
497
|
// - check `string` either `MODE_IGNORE` or `MODE_CHECK_IGNORE`
|
|
498
498
|
// @returns {TestResult} true if a file is ignored
|
|
499
|
-
test(
|
|
499
|
+
test(path33, checkUnignored, mode) {
|
|
500
500
|
let ignored = false;
|
|
501
501
|
let unignored = false;
|
|
502
502
|
let matchedRule;
|
|
@@ -505,7 +505,7 @@ var require_ignore = __commonJS({
|
|
|
505
505
|
if (unignored === negative && ignored !== unignored || negative && !ignored && !unignored && !checkUnignored) {
|
|
506
506
|
return;
|
|
507
507
|
}
|
|
508
|
-
const matched = rule[mode].test(
|
|
508
|
+
const matched = rule[mode].test(path33);
|
|
509
509
|
if (!matched) {
|
|
510
510
|
return;
|
|
511
511
|
}
|
|
@@ -526,17 +526,17 @@ var require_ignore = __commonJS({
|
|
|
526
526
|
var throwError = (message, Ctor) => {
|
|
527
527
|
throw new Ctor(message);
|
|
528
528
|
};
|
|
529
|
-
var checkPath = (
|
|
530
|
-
if (!isString(
|
|
529
|
+
var checkPath = (path33, originalPath, doThrow) => {
|
|
530
|
+
if (!isString(path33)) {
|
|
531
531
|
return doThrow(
|
|
532
532
|
`path must be a string, but got \`${originalPath}\``,
|
|
533
533
|
TypeError
|
|
534
534
|
);
|
|
535
535
|
}
|
|
536
|
-
if (!
|
|
536
|
+
if (!path33) {
|
|
537
537
|
return doThrow(`path must not be empty`, TypeError);
|
|
538
538
|
}
|
|
539
|
-
if (checkPath.isNotRelative(
|
|
539
|
+
if (checkPath.isNotRelative(path33)) {
|
|
540
540
|
const r = "`path.relative()`d";
|
|
541
541
|
return doThrow(
|
|
542
542
|
`path should be a ${r} string, but got "${originalPath}"`,
|
|
@@ -545,7 +545,7 @@ var require_ignore = __commonJS({
|
|
|
545
545
|
}
|
|
546
546
|
return true;
|
|
547
547
|
};
|
|
548
|
-
var isNotRelative = (
|
|
548
|
+
var isNotRelative = (path33) => REGEX_TEST_INVALID_PATH.test(path33);
|
|
549
549
|
checkPath.isNotRelative = isNotRelative;
|
|
550
550
|
checkPath.convert = (p) => p;
|
|
551
551
|
var Ignore2 = class {
|
|
@@ -575,19 +575,19 @@ var require_ignore = __commonJS({
|
|
|
575
575
|
}
|
|
576
576
|
// @returns {TestResult}
|
|
577
577
|
_test(originalPath, cache, checkUnignored, slices) {
|
|
578
|
-
const
|
|
578
|
+
const path33 = originalPath && checkPath.convert(originalPath);
|
|
579
579
|
checkPath(
|
|
580
|
-
|
|
580
|
+
path33,
|
|
581
581
|
originalPath,
|
|
582
582
|
this._strictPathCheck ? throwError : RETURN_FALSE
|
|
583
583
|
);
|
|
584
|
-
return this._t(
|
|
584
|
+
return this._t(path33, cache, checkUnignored, slices);
|
|
585
585
|
}
|
|
586
|
-
checkIgnore(
|
|
587
|
-
if (!REGEX_TEST_TRAILING_SLASH.test(
|
|
588
|
-
return this.test(
|
|
586
|
+
checkIgnore(path33) {
|
|
587
|
+
if (!REGEX_TEST_TRAILING_SLASH.test(path33)) {
|
|
588
|
+
return this.test(path33);
|
|
589
589
|
}
|
|
590
|
-
const slices =
|
|
590
|
+
const slices = path33.split(SLASH2).filter(Boolean);
|
|
591
591
|
slices.pop();
|
|
592
592
|
if (slices.length) {
|
|
593
593
|
const parent = this._t(
|
|
@@ -600,18 +600,18 @@ var require_ignore = __commonJS({
|
|
|
600
600
|
return parent;
|
|
601
601
|
}
|
|
602
602
|
}
|
|
603
|
-
return this._rules.test(
|
|
603
|
+
return this._rules.test(path33, false, MODE_CHECK_IGNORE);
|
|
604
604
|
}
|
|
605
|
-
_t(
|
|
606
|
-
if (
|
|
607
|
-
return cache[
|
|
605
|
+
_t(path33, cache, checkUnignored, slices) {
|
|
606
|
+
if (path33 in cache) {
|
|
607
|
+
return cache[path33];
|
|
608
608
|
}
|
|
609
609
|
if (!slices) {
|
|
610
|
-
slices =
|
|
610
|
+
slices = path33.split(SLASH2).filter(Boolean);
|
|
611
611
|
}
|
|
612
612
|
slices.pop();
|
|
613
613
|
if (!slices.length) {
|
|
614
|
-
return cache[
|
|
614
|
+
return cache[path33] = this._rules.test(path33, checkUnignored, MODE_IGNORE);
|
|
615
615
|
}
|
|
616
616
|
const parent = this._t(
|
|
617
617
|
slices.join(SLASH2) + SLASH2,
|
|
@@ -619,29 +619,29 @@ var require_ignore = __commonJS({
|
|
|
619
619
|
checkUnignored,
|
|
620
620
|
slices
|
|
621
621
|
);
|
|
622
|
-
return cache[
|
|
622
|
+
return cache[path33] = parent.ignored ? parent : this._rules.test(path33, checkUnignored, MODE_IGNORE);
|
|
623
623
|
}
|
|
624
|
-
ignores(
|
|
625
|
-
return this._test(
|
|
624
|
+
ignores(path33) {
|
|
625
|
+
return this._test(path33, this._ignoreCache, false).ignored;
|
|
626
626
|
}
|
|
627
627
|
createFilter() {
|
|
628
|
-
return (
|
|
628
|
+
return (path33) => !this.ignores(path33);
|
|
629
629
|
}
|
|
630
630
|
filter(paths) {
|
|
631
631
|
return makeArray(paths).filter(this.createFilter());
|
|
632
632
|
}
|
|
633
633
|
// @returns {TestResult}
|
|
634
|
-
test(
|
|
635
|
-
return this._test(
|
|
634
|
+
test(path33) {
|
|
635
|
+
return this._test(path33, this._testCache, true);
|
|
636
636
|
}
|
|
637
637
|
};
|
|
638
638
|
var factory = (options) => new Ignore2(options);
|
|
639
|
-
var isPathValid = (
|
|
639
|
+
var isPathValid = (path33) => checkPath(path33 && checkPath.convert(path33), path33, RETURN_FALSE);
|
|
640
640
|
var setupWindows = () => {
|
|
641
641
|
const makePosix = (str) => /^\\\\\?\\/.test(str) || /["<>|\u0000-\u001F]+/u.test(str) ? str : str.replace(/\\/g, "/");
|
|
642
642
|
checkPath.convert = makePosix;
|
|
643
643
|
const REGEX_TEST_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i;
|
|
644
|
-
checkPath.isNotRelative = (
|
|
644
|
+
checkPath.isNotRelative = (path33) => REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path33) || isNotRelative(path33);
|
|
645
645
|
};
|
|
646
646
|
if (
|
|
647
647
|
// Detect `process` so that it can run in browsers.
|
|
@@ -669,7 +669,7 @@ module.exports = __toCommonJS(cli_exports);
|
|
|
669
669
|
var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
670
670
|
var import_fs20 = require("fs");
|
|
671
671
|
var os8 = __toESM(require("os"), 1);
|
|
672
|
-
var
|
|
672
|
+
var path32 = __toESM(require("path"), 1);
|
|
673
673
|
var import_url = require("url");
|
|
674
674
|
|
|
675
675
|
// src/config/constants.ts
|
|
@@ -1179,9 +1179,9 @@ var import_fs = require("fs");
|
|
|
1179
1179
|
var path = __toESM(require("path"), 1);
|
|
1180
1180
|
|
|
1181
1181
|
// src/eval/report-formatters.ts
|
|
1182
|
-
function assertFiniteNumber(value,
|
|
1182
|
+
function assertFiniteNumber(value, path33) {
|
|
1183
1183
|
if (typeof value !== "number" || Number.isNaN(value) || !Number.isFinite(value)) {
|
|
1184
|
-
throw new Error(`${
|
|
1184
|
+
throw new Error(`${path33} must be a finite number`);
|
|
1185
1185
|
}
|
|
1186
1186
|
return value;
|
|
1187
1187
|
}
|
|
@@ -1453,7 +1453,7 @@ function pTimeout(promise, options) {
|
|
|
1453
1453
|
} = options;
|
|
1454
1454
|
let timer;
|
|
1455
1455
|
let abortHandler;
|
|
1456
|
-
const wrappedPromise = new Promise((
|
|
1456
|
+
const wrappedPromise = new Promise((resolve20, reject) => {
|
|
1457
1457
|
if (typeof milliseconds !== "number" || Math.sign(milliseconds) !== 1) {
|
|
1458
1458
|
throw new TypeError(`Expected \`milliseconds\` to be a positive number, got \`${milliseconds}\``);
|
|
1459
1459
|
}
|
|
@@ -1467,7 +1467,7 @@ function pTimeout(promise, options) {
|
|
|
1467
1467
|
};
|
|
1468
1468
|
signal.addEventListener("abort", abortHandler, { once: true });
|
|
1469
1469
|
}
|
|
1470
|
-
promise.then(
|
|
1470
|
+
promise.then(resolve20, reject);
|
|
1471
1471
|
if (milliseconds === Number.POSITIVE_INFINITY) {
|
|
1472
1472
|
return;
|
|
1473
1473
|
}
|
|
@@ -1475,7 +1475,7 @@ function pTimeout(promise, options) {
|
|
|
1475
1475
|
timer = customTimers.setTimeout.call(void 0, () => {
|
|
1476
1476
|
if (fallback) {
|
|
1477
1477
|
try {
|
|
1478
|
-
|
|
1478
|
+
resolve20(fallback());
|
|
1479
1479
|
} catch (error) {
|
|
1480
1480
|
reject(error);
|
|
1481
1481
|
}
|
|
@@ -1485,7 +1485,7 @@ function pTimeout(promise, options) {
|
|
|
1485
1485
|
promise.cancel();
|
|
1486
1486
|
}
|
|
1487
1487
|
if (message === false) {
|
|
1488
|
-
|
|
1488
|
+
resolve20();
|
|
1489
1489
|
} else if (message instanceof Error) {
|
|
1490
1490
|
reject(message);
|
|
1491
1491
|
} else {
|
|
@@ -1887,7 +1887,7 @@ var PQueue = class extends import_index.default {
|
|
|
1887
1887
|
// Assign unique ID if not provided
|
|
1888
1888
|
id: options.id ?? (this.#idAssigner++).toString()
|
|
1889
1889
|
};
|
|
1890
|
-
return new Promise((
|
|
1890
|
+
return new Promise((resolve20, reject) => {
|
|
1891
1891
|
const taskSymbol = /* @__PURE__ */ Symbol(`task-${options.id}`);
|
|
1892
1892
|
let cleanupQueueAbortHandler = () => void 0;
|
|
1893
1893
|
const run = async () => {
|
|
@@ -1927,7 +1927,7 @@ var PQueue = class extends import_index.default {
|
|
|
1927
1927
|
})]);
|
|
1928
1928
|
}
|
|
1929
1929
|
const result = await operation;
|
|
1930
|
-
|
|
1930
|
+
resolve20(result);
|
|
1931
1931
|
this.emit("completed", result);
|
|
1932
1932
|
} catch (error) {
|
|
1933
1933
|
reject(error);
|
|
@@ -2115,13 +2115,13 @@ var PQueue = class extends import_index.default {
|
|
|
2115
2115
|
});
|
|
2116
2116
|
}
|
|
2117
2117
|
async #onEvent(event, filter) {
|
|
2118
|
-
return new Promise((
|
|
2118
|
+
return new Promise((resolve20) => {
|
|
2119
2119
|
const listener = () => {
|
|
2120
2120
|
if (filter && !filter()) {
|
|
2121
2121
|
return;
|
|
2122
2122
|
}
|
|
2123
2123
|
this.off(event, listener);
|
|
2124
|
-
|
|
2124
|
+
resolve20();
|
|
2125
2125
|
};
|
|
2126
2126
|
this.on(event, listener);
|
|
2127
2127
|
});
|
|
@@ -2407,7 +2407,7 @@ async function onAttemptFailure({ error, attemptNumber, retriesConsumed, startTi
|
|
|
2407
2407
|
const finalDelay = Math.min(delayTime, remainingTime);
|
|
2408
2408
|
options.signal?.throwIfAborted();
|
|
2409
2409
|
if (finalDelay > 0) {
|
|
2410
|
-
await new Promise((
|
|
2410
|
+
await new Promise((resolve20, reject) => {
|
|
2411
2411
|
const onAbort = () => {
|
|
2412
2412
|
clearTimeout(timeoutToken);
|
|
2413
2413
|
options.signal?.removeEventListener("abort", onAbort);
|
|
@@ -2415,7 +2415,7 @@ async function onAttemptFailure({ error, attemptNumber, retriesConsumed, startTi
|
|
|
2415
2415
|
};
|
|
2416
2416
|
const timeoutToken = setTimeout(() => {
|
|
2417
2417
|
options.signal?.removeEventListener("abort", onAbort);
|
|
2418
|
-
|
|
2418
|
+
resolve20();
|
|
2419
2419
|
}, finalDelay);
|
|
2420
2420
|
if (options.unref) {
|
|
2421
2421
|
timeoutToken.unref?.();
|
|
@@ -3221,85 +3221,6 @@ function createEmbeddingProvider(configuredProviderInfo) {
|
|
|
3221
3221
|
}
|
|
3222
3222
|
}
|
|
3223
3223
|
|
|
3224
|
-
// src/rerank/index.ts
|
|
3225
|
-
function createReranker(config) {
|
|
3226
|
-
if (!config.enabled) {
|
|
3227
|
-
return new NoOpReranker();
|
|
3228
|
-
}
|
|
3229
|
-
return new SiliconFlowReranker(config);
|
|
3230
|
-
}
|
|
3231
|
-
var NoOpReranker = class {
|
|
3232
|
-
isAvailable() {
|
|
3233
|
-
return false;
|
|
3234
|
-
}
|
|
3235
|
-
async rerank(_query, documents, _topN) {
|
|
3236
|
-
return {
|
|
3237
|
-
results: documents.map((_, index) => ({ index, relevanceScore: 0 }))
|
|
3238
|
-
};
|
|
3239
|
-
}
|
|
3240
|
-
};
|
|
3241
|
-
var SiliconFlowReranker = class {
|
|
3242
|
-
config;
|
|
3243
|
-
constructor(config) {
|
|
3244
|
-
this.config = config;
|
|
3245
|
-
}
|
|
3246
|
-
isAvailable() {
|
|
3247
|
-
return this.config.enabled && !!this.config.baseUrl && !!this.config.model;
|
|
3248
|
-
}
|
|
3249
|
-
async rerank(query, documents, topN) {
|
|
3250
|
-
if (documents.length === 0) {
|
|
3251
|
-
return { results: [] };
|
|
3252
|
-
}
|
|
3253
|
-
const headers = {
|
|
3254
|
-
"Content-Type": "application/json"
|
|
3255
|
-
};
|
|
3256
|
-
if (this.config.apiKey) {
|
|
3257
|
-
headers["Authorization"] = `Bearer ${this.config.apiKey}`;
|
|
3258
|
-
}
|
|
3259
|
-
const baseUrl = this.config.baseUrl;
|
|
3260
|
-
if (!baseUrl) {
|
|
3261
|
-
throw new Error("Reranker baseUrl is required. Configure reranker.baseUrl in your codebase-index.json.");
|
|
3262
|
-
}
|
|
3263
|
-
const timeoutMs = this.config.timeoutMs ?? 3e4;
|
|
3264
|
-
const controller = new AbortController();
|
|
3265
|
-
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
3266
|
-
try {
|
|
3267
|
-
const response = await fetch(`${baseUrl}/rerank`, {
|
|
3268
|
-
method: "POST",
|
|
3269
|
-
headers,
|
|
3270
|
-
body: JSON.stringify({
|
|
3271
|
-
model: this.config.model,
|
|
3272
|
-
query,
|
|
3273
|
-
documents,
|
|
3274
|
-
top_n: topN ?? this.config.topN ?? 20,
|
|
3275
|
-
return_documents: false
|
|
3276
|
-
}),
|
|
3277
|
-
signal: controller.signal
|
|
3278
|
-
});
|
|
3279
|
-
clearTimeout(timeout);
|
|
3280
|
-
if (!response.ok) {
|
|
3281
|
-
const errorText = await response.text();
|
|
3282
|
-
throw new Error(`Rerank API error: ${response.status} - ${errorText}`);
|
|
3283
|
-
}
|
|
3284
|
-
const data = await response.json();
|
|
3285
|
-
return {
|
|
3286
|
-
results: data.results.map((r) => ({
|
|
3287
|
-
index: r.index,
|
|
3288
|
-
relevanceScore: r.relevance_score,
|
|
3289
|
-
document: r.document?.text
|
|
3290
|
-
})),
|
|
3291
|
-
tokensUsed: data.meta?.tokens?.input_tokens
|
|
3292
|
-
};
|
|
3293
|
-
} catch (error) {
|
|
3294
|
-
clearTimeout(timeout);
|
|
3295
|
-
if (error instanceof Error && error.name === "AbortError") {
|
|
3296
|
-
throw new Error(`Rerank API request timed out after ${timeoutMs}ms`);
|
|
3297
|
-
}
|
|
3298
|
-
throw error;
|
|
3299
|
-
}
|
|
3300
|
-
}
|
|
3301
|
-
};
|
|
3302
|
-
|
|
3303
3224
|
// src/utils/files.ts
|
|
3304
3225
|
var import_ignore = __toESM(require_ignore(), 1);
|
|
3305
3226
|
var import_fs3 = require("fs");
|
|
@@ -3461,8 +3382,8 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
|
|
|
3461
3382
|
if (entry.isDirectory()) {
|
|
3462
3383
|
subdirs.push({ fullPath, relativePath });
|
|
3463
3384
|
} else if (entry.isFile()) {
|
|
3464
|
-
const
|
|
3465
|
-
if (
|
|
3385
|
+
const stat5 = await import_fs3.promises.stat(fullPath);
|
|
3386
|
+
if (stat5.size > maxFileSize) {
|
|
3466
3387
|
skipped.push({ path: relativePath, reason: "too_large" });
|
|
3467
3388
|
continue;
|
|
3468
3389
|
}
|
|
@@ -3480,7 +3401,7 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
|
|
|
3480
3401
|
}
|
|
3481
3402
|
}
|
|
3482
3403
|
if (matched) {
|
|
3483
|
-
filesInDir.push({ path: fullPath, size:
|
|
3404
|
+
filesInDir.push({ path: fullPath, size: stat5.size });
|
|
3484
3405
|
}
|
|
3485
3406
|
}
|
|
3486
3407
|
}
|
|
@@ -3537,8 +3458,8 @@ async function collectFiles(projectRoot, includePatterns, excludePatterns, maxFi
|
|
|
3537
3458
|
}
|
|
3538
3459
|
for (const resolvedKbRoot of normalizedRoots) {
|
|
3539
3460
|
try {
|
|
3540
|
-
const
|
|
3541
|
-
if (!
|
|
3461
|
+
const stat5 = await import_fs3.promises.stat(resolvedKbRoot);
|
|
3462
|
+
if (!stat5.isDirectory()) {
|
|
3542
3463
|
skipped.push({ path: resolvedKbRoot, reason: "excluded" });
|
|
3543
3464
|
continue;
|
|
3544
3465
|
}
|
|
@@ -4865,11 +4786,11 @@ function resolveGitDir(repoRoot) {
|
|
|
4865
4786
|
return null;
|
|
4866
4787
|
}
|
|
4867
4788
|
try {
|
|
4868
|
-
const
|
|
4869
|
-
if (
|
|
4789
|
+
const stat5 = (0, import_fs5.statSync)(gitPath);
|
|
4790
|
+
if (stat5.isDirectory()) {
|
|
4870
4791
|
return gitPath;
|
|
4871
4792
|
}
|
|
4872
|
-
if (
|
|
4793
|
+
if (stat5.isFile()) {
|
|
4873
4794
|
const content = (0, import_fs5.readFileSync)(gitPath, "utf-8").trim();
|
|
4874
4795
|
const match = content.match(/^gitdir:\s*(.+)$/);
|
|
4875
4796
|
if (match) {
|
|
@@ -5374,8 +5295,8 @@ async function isWorktreeRegistered(projectRoot, worktreePath) {
|
|
|
5374
5295
|
return false;
|
|
5375
5296
|
}
|
|
5376
5297
|
function isPathWithinRoot(filePath, rootPath) {
|
|
5377
|
-
const
|
|
5378
|
-
return
|
|
5298
|
+
const relative14 = path9.relative(path9.resolve(rootPath), path9.resolve(filePath));
|
|
5299
|
+
return relative14 === "" || !relative14.startsWith(`..${path9.sep}`) && relative14 !== ".." && !path9.isAbsolute(relative14);
|
|
5379
5300
|
}
|
|
5380
5301
|
async function pruneExactMissingWorktreeRegistration(projectRoot, worktreePath) {
|
|
5381
5302
|
if (await pathExists(worktreePath)) return false;
|
|
@@ -5933,11 +5854,11 @@ function normalizeFiles(rawFiles, projectRoot) {
|
|
|
5933
5854
|
for (const raw of rawFiles) {
|
|
5934
5855
|
if (raw.length === 0) continue;
|
|
5935
5856
|
const absolute = path11.resolve(root, raw);
|
|
5936
|
-
const
|
|
5937
|
-
if (path11.isAbsolute(raw) ||
|
|
5857
|
+
const relative14 = path11.relative(root, absolute);
|
|
5858
|
+
if (path11.isAbsolute(raw) || relative14 === ".." || relative14.startsWith(`..${path11.sep}`) || path11.isAbsolute(relative14)) {
|
|
5938
5859
|
throw new Error(`Changed file escapes the project root: ${JSON.stringify(raw)}`);
|
|
5939
5860
|
}
|
|
5940
|
-
const cleaned =
|
|
5861
|
+
const cleaned = relative14.startsWith(`.${path11.sep}`) ? relative14.slice(2) : relative14;
|
|
5941
5862
|
if (!seen.has(cleaned)) {
|
|
5942
5863
|
seen.add(cleaned);
|
|
5943
5864
|
result.push(cleaned);
|
|
@@ -6274,7 +6195,7 @@ function analyzeQueryIntent(query) {
|
|
|
6274
6195
|
}
|
|
6275
6196
|
function isTestPath(filePath) {
|
|
6276
6197
|
const normalized = normalizePath(filePath);
|
|
6277
|
-
return /(?:^|\/)(?:test|tests|__tests__|spec|specs)(?:\/|$)/u.test(normalized) ||
|
|
6198
|
+
return /(?:^|\/)(?:test|tests|__tests__|spec|specs)(?:\/|$)/u.test(normalized) || /(?:\.(?:test|spec)|_(?:test|spec))\.[^/]+$/u.test(normalized) || /(?:^|\/)(?:test|spec)_[^/]+\.[^/]+$/u.test(normalized);
|
|
6278
6199
|
}
|
|
6279
6200
|
function isFixturePath(filePath) {
|
|
6280
6201
|
const normalized = normalizePath(filePath);
|
|
@@ -6681,7 +6602,8 @@ function rankHybridResults(query, semanticResults, keywordResults, options) {
|
|
|
6681
6602
|
return cached;
|
|
6682
6603
|
}
|
|
6683
6604
|
}
|
|
6684
|
-
const
|
|
6605
|
+
const overfetchFactor = prioritizeSourcePaths ? 12 : 4;
|
|
6606
|
+
const overfetchLimit = Math.max(options.limit * overfetchFactor, options.limit);
|
|
6685
6607
|
const fused = options.fusionStrategy === "rrf" ? fuseResultsRrf(semanticResults, keywordResults, options.rrfK, overfetchLimit) : fuseResultsWeighted(semanticResults, keywordResults, options.hybridWeight, overfetchLimit);
|
|
6686
6608
|
const rerankPoolLimit = Math.max(overfetchLimit, options.rerankTopN * 3, options.limit * 6);
|
|
6687
6609
|
const rerankPool = fused.slice(0, rerankPoolLimit);
|
|
@@ -7067,6 +6989,29 @@ function extractPrimaryIdentifierQueryHint(query) {
|
|
|
7067
6989
|
const best = codeTerms.find((term) => term.length >= 6);
|
|
7068
6990
|
return best ?? null;
|
|
7069
6991
|
}
|
|
6992
|
+
function pathSegmentsForAffinityMatch(filePath) {
|
|
6993
|
+
const normalizedPath3 = normalizeRankingText(filePath).replace(/\\/g, "/");
|
|
6994
|
+
const segments = normalizedPath3.split("/").filter((segment) => segment.length > 0);
|
|
6995
|
+
if (segments.length === 0) {
|
|
6996
|
+
return [];
|
|
6997
|
+
}
|
|
6998
|
+
const basename8 = segments[segments.length - 1] ?? "";
|
|
6999
|
+
const basenameWithoutExt = basename8.replace(/\.[^/.]+$/u, "");
|
|
7000
|
+
const normalizedSegments = segments.map((segment) => segment.toLowerCase());
|
|
7001
|
+
return Array.from(/* @__PURE__ */ new Set([
|
|
7002
|
+
...normalizedSegments,
|
|
7003
|
+
basenameWithoutExt.toLowerCase()
|
|
7004
|
+
]));
|
|
7005
|
+
}
|
|
7006
|
+
function hasModuleAffinity(filePath, exactIdentifierVariants) {
|
|
7007
|
+
const haystack = pathSegmentsForAffinityMatch(filePath);
|
|
7008
|
+
return exactIdentifierVariants.some((variant) => {
|
|
7009
|
+
if (!variant || variant.length < 2) {
|
|
7010
|
+
return false;
|
|
7011
|
+
}
|
|
7012
|
+
return haystack.includes(variant);
|
|
7013
|
+
});
|
|
7014
|
+
}
|
|
7070
7015
|
var FILE_PATH_HINT_EXTENSIONS = [
|
|
7071
7016
|
"ts",
|
|
7072
7017
|
"tsx",
|
|
@@ -7142,10 +7087,13 @@ function buildDeterministicIdentifierPass(query, candidates, limit, prioritizeSo
|
|
|
7142
7087
|
).map((candidate) => {
|
|
7143
7088
|
const nameLower = (candidate.metadata.name ?? "").toLowerCase();
|
|
7144
7089
|
const pathLower = candidate.metadata.filePath.toLowerCase();
|
|
7145
|
-
|
|
7146
|
-
const
|
|
7090
|
+
const exactIdentifierVariants = primaryVariants.filter((value) => value.length >= 2);
|
|
7091
|
+
const exactMatch = exactIdentifierVariants.some(
|
|
7147
7092
|
(variant) => nameLower === variant || nameLower.replace(/[^a-z0-9]/g, "") === variant.replace(/[^a-z0-9]/g, "")
|
|
7148
7093
|
);
|
|
7094
|
+
let maxMatch = 0;
|
|
7095
|
+
const nameMatchesPrimary = exactMatch;
|
|
7096
|
+
const pathAffinity = exactMatch ? hasModuleAffinity(candidate.metadata.filePath, exactIdentifierVariants) : false;
|
|
7149
7097
|
const pathMatchesFileHint = filePathHint ? pathMatchesHint(candidate.metadata.filePath, filePathHint) : false;
|
|
7150
7098
|
for (const hint of hints) {
|
|
7151
7099
|
const variants = normalizeIdentifierVariants(hint);
|
|
@@ -7166,12 +7114,17 @@ function buildDeterministicIdentifierPass(query, candidates, limit, prioritizeSo
|
|
|
7166
7114
|
candidate,
|
|
7167
7115
|
maxMatch,
|
|
7168
7116
|
pathMatchesFileHint,
|
|
7169
|
-
nameMatchesPrimary
|
|
7117
|
+
nameMatchesPrimary,
|
|
7118
|
+
pathAffinity
|
|
7170
7119
|
};
|
|
7171
7120
|
}).filter((entry) => entry.maxMatch >= 0.7).sort((a, b) => {
|
|
7172
7121
|
const aAnchored = a.pathMatchesFileHint && a.nameMatchesPrimary ? 1 : 0;
|
|
7173
7122
|
const bAnchored = b.pathMatchesFileHint && b.nameMatchesPrimary ? 1 : 0;
|
|
7174
7123
|
if (aAnchored !== bAnchored) return bAnchored - aAnchored;
|
|
7124
|
+
if (a.nameMatchesPrimary !== b.nameMatchesPrimary) {
|
|
7125
|
+
return b.nameMatchesPrimary ? 1 : -1;
|
|
7126
|
+
}
|
|
7127
|
+
if (a.pathAffinity !== b.pathAffinity) return b.pathAffinity ? 1 : -1;
|
|
7175
7128
|
if (b.maxMatch !== a.maxMatch) return b.maxMatch - a.maxMatch;
|
|
7176
7129
|
if (b.candidate.score !== a.candidate.score) return b.candidate.score - a.candidate.score;
|
|
7177
7130
|
return a.candidate.id.localeCompare(b.candidate.id);
|
|
@@ -8552,7 +8505,6 @@ var Indexer = class _Indexer {
|
|
|
8552
8505
|
database = null;
|
|
8553
8506
|
provider = null;
|
|
8554
8507
|
configuredProviderInfo = null;
|
|
8555
|
-
reranker = null;
|
|
8556
8508
|
fileHashCache = /* @__PURE__ */ new Map();
|
|
8557
8509
|
fileHashCachePath = "";
|
|
8558
8510
|
failedBatchesPath = "";
|
|
@@ -8712,7 +8664,6 @@ var Indexer = class _Indexer {
|
|
|
8712
8664
|
this.database = null;
|
|
8713
8665
|
this.provider = null;
|
|
8714
8666
|
this.configuredProviderInfo = null;
|
|
8715
|
-
this.reranker = null;
|
|
8716
8667
|
this.indexCompatibility = null;
|
|
8717
8668
|
this.initializationMode = "none";
|
|
8718
8669
|
this.readIssues = [];
|
|
@@ -9442,7 +9393,7 @@ var Indexer = class _Indexer {
|
|
|
9442
9393
|
await options.queue.onSizeLessThan(Math.max(1, options.providerRateLimits.concurrency));
|
|
9443
9394
|
const task = options.queue.add(async () => {
|
|
9444
9395
|
if (options.rateLimitState.backoffMs > 0) {
|
|
9445
|
-
await new Promise((
|
|
9396
|
+
await new Promise((resolve20) => setTimeout(resolve20, options.rateLimitState.backoffMs));
|
|
9446
9397
|
}
|
|
9447
9398
|
try {
|
|
9448
9399
|
const embeddingResult = await pRetry(
|
|
@@ -10009,15 +9960,6 @@ var Indexer = class _Indexer {
|
|
|
10009
9960
|
rerankerEnabled: this.config.reranker?.enabled ?? false
|
|
10010
9961
|
});
|
|
10011
9962
|
this.provider = createEmbeddingProvider(this.configuredProviderInfo);
|
|
10012
|
-
if (this.config.reranker?.enabled) {
|
|
10013
|
-
this.reranker = createReranker(this.config.reranker);
|
|
10014
|
-
if (this.reranker.isAvailable()) {
|
|
10015
|
-
this.logger.info("Reranker initialized", {
|
|
10016
|
-
model: this.config.reranker.model,
|
|
10017
|
-
baseUrl: this.config.reranker.baseUrl
|
|
10018
|
-
});
|
|
10019
|
-
}
|
|
10020
|
-
}
|
|
10021
9963
|
const dimensions = this.configuredProviderInfo.modelInfo.dimensions;
|
|
10022
9964
|
const storePath = path15.join(this.indexPath, "vectors");
|
|
10023
9965
|
const vectorMetadataPath = `${storePath}.meta.json`;
|
|
@@ -11422,6 +11364,7 @@ var Indexer = class _Indexer {
|
|
|
11422
11364
|
const filterByBranch = options?.filterByBranch ?? true;
|
|
11423
11365
|
const sourceIntent = options?.definitionIntent === true || classifyQueryIntentRaw(query) === "source";
|
|
11424
11366
|
const identifierHints = extractIdentifierHints(query);
|
|
11367
|
+
const candidateLimit = maxResults * (sourceIntent ? 12 : 4);
|
|
11425
11368
|
this.logger.search("debug", "Starting search", {
|
|
11426
11369
|
query,
|
|
11427
11370
|
maxResults,
|
|
@@ -11458,7 +11401,7 @@ var Indexer = class _Indexer {
|
|
|
11458
11401
|
const semanticCandidates = embedding ? this.searchSemanticCandidates(
|
|
11459
11402
|
store,
|
|
11460
11403
|
embedding,
|
|
11461
|
-
|
|
11404
|
+
candidateLimit,
|
|
11462
11405
|
branchChunkIds,
|
|
11463
11406
|
shouldPrefilterByBranch
|
|
11464
11407
|
) : [];
|
|
@@ -11466,7 +11409,7 @@ var Indexer = class _Indexer {
|
|
|
11466
11409
|
const keywordStartTime = import_perf_hooks.performance.now();
|
|
11467
11410
|
const keywordCandidates = await this.keywordSearch(
|
|
11468
11411
|
query,
|
|
11469
|
-
|
|
11412
|
+
candidateLimit,
|
|
11470
11413
|
store,
|
|
11471
11414
|
invertedIndex,
|
|
11472
11415
|
branchChunkIds,
|
|
@@ -12224,9 +12167,9 @@ var Indexer = class _Indexer {
|
|
|
12224
12167
|
this.requireReadableComponents(readIssues, "database");
|
|
12225
12168
|
let shortest = [];
|
|
12226
12169
|
for (const branchKey of this.getBranchCatalogKeys()) {
|
|
12227
|
-
const
|
|
12228
|
-
if (
|
|
12229
|
-
shortest =
|
|
12170
|
+
const path33 = database.findShortestPath(fromName, toName, branchKey, maxDepth);
|
|
12171
|
+
if (path33.length > 0 && (shortest.length === 0 || path33.length < shortest.length)) {
|
|
12172
|
+
shortest = path33;
|
|
12230
12173
|
}
|
|
12231
12174
|
}
|
|
12232
12175
|
return shortest.map((hop) => this.resolveFilePathRecord(hop));
|
|
@@ -12274,13 +12217,13 @@ var Indexer = class _Indexer {
|
|
|
12274
12217
|
}
|
|
12275
12218
|
}
|
|
12276
12219
|
if (!found) continue;
|
|
12277
|
-
const
|
|
12220
|
+
const path33 = [];
|
|
12278
12221
|
let currentSymbolId = toSymbolId;
|
|
12279
12222
|
while (true) {
|
|
12280
12223
|
const symbol = symbolsById.get(currentSymbolId);
|
|
12281
12224
|
if (!symbol) break;
|
|
12282
12225
|
const parent = parentBySymbolId.get(currentSymbolId);
|
|
12283
|
-
|
|
12226
|
+
path33.push({
|
|
12284
12227
|
symbolId: symbol.id,
|
|
12285
12228
|
symbolName: symbol.name,
|
|
12286
12229
|
filePath: symbol.filePath,
|
|
@@ -12290,9 +12233,9 @@ var Indexer = class _Indexer {
|
|
|
12290
12233
|
if (!parent) break;
|
|
12291
12234
|
currentSymbolId = parent.parentId;
|
|
12292
12235
|
}
|
|
12293
|
-
|
|
12294
|
-
if (
|
|
12295
|
-
shortest =
|
|
12236
|
+
path33.reverse();
|
|
12237
|
+
if (path33.length > 0 && (shortest.length === 0 || path33.length < shortest.length)) {
|
|
12238
|
+
shortest = path33;
|
|
12296
12239
|
}
|
|
12297
12240
|
}
|
|
12298
12241
|
return shortest.map((hop) => this.resolveFilePathRecord(hop));
|
|
@@ -12628,7 +12571,6 @@ var Indexer = class _Indexer {
|
|
|
12628
12571
|
this.store = null;
|
|
12629
12572
|
this.invertedIndex = null;
|
|
12630
12573
|
this.provider = null;
|
|
12631
|
-
this.reranker = null;
|
|
12632
12574
|
this.configuredProviderInfo = null;
|
|
12633
12575
|
this.indexCompatibility = null;
|
|
12634
12576
|
this.initializationMode = "none";
|
|
@@ -12942,8 +12884,8 @@ function formatExactSearchHandoff(results) {
|
|
|
12942
12884
|
}
|
|
12943
12885
|
function formatContextEvidence(result, index) {
|
|
12944
12886
|
const symbol = result.name ? ` ${JSON.stringify(compactEvidenceValue(result.name, 80))}` : "";
|
|
12945
|
-
const
|
|
12946
|
-
return `[${index}] ${result.chunkType}${symbol} in ${
|
|
12887
|
+
const path33 = compactEvidenceValue(result.filePath, 120);
|
|
12888
|
+
return `[${index}] ${result.chunkType}${symbol} in ${path33}:${result.startLine}-${result.endLine} (score ${result.score.toFixed(2)})`;
|
|
12947
12889
|
}
|
|
12948
12890
|
function formatContextPack(heading, selected, candidateCount, duplicateCount, limitOmittedCount, budgetOmittedCount, includeExactSearchHandoff) {
|
|
12949
12891
|
const lines = selected.map((result, index) => formatContextEvidence(result, index + 1));
|
|
@@ -13597,7 +13539,7 @@ function getErrorMessage4(error) {
|
|
|
13597
13539
|
return error instanceof Error ? error.message : String(error);
|
|
13598
13540
|
}
|
|
13599
13541
|
function runCommand(file, args, options) {
|
|
13600
|
-
return new Promise((
|
|
13542
|
+
return new Promise((resolve20, reject) => {
|
|
13601
13543
|
childProcess.execFile(
|
|
13602
13544
|
file,
|
|
13603
13545
|
args,
|
|
@@ -13607,7 +13549,7 @@ function runCommand(file, args, options) {
|
|
|
13607
13549
|
reject(error);
|
|
13608
13550
|
return;
|
|
13609
13551
|
}
|
|
13610
|
-
|
|
13552
|
+
resolve20(stdout);
|
|
13611
13553
|
}
|
|
13612
13554
|
);
|
|
13613
13555
|
});
|
|
@@ -13752,10 +13694,10 @@ function safeFailureMessage(error) {
|
|
|
13752
13694
|
}
|
|
13753
13695
|
function cancellableDelay(delayMs, signal) {
|
|
13754
13696
|
if (signal.aborted) return Promise.reject(new AutoIndexCancelledError());
|
|
13755
|
-
return new Promise((
|
|
13697
|
+
return new Promise((resolve20, reject) => {
|
|
13756
13698
|
const timer = setTimeout(() => {
|
|
13757
13699
|
signal.removeEventListener("abort", onAbort);
|
|
13758
|
-
|
|
13700
|
+
resolve20();
|
|
13759
13701
|
}, delayMs);
|
|
13760
13702
|
timer.unref?.();
|
|
13761
13703
|
const onAbort = () => {
|
|
@@ -13767,15 +13709,15 @@ function cancellableDelay(delayMs, signal) {
|
|
|
13767
13709
|
}
|
|
13768
13710
|
function withTimeout(promise, timeoutMs) {
|
|
13769
13711
|
if (timeoutMs <= 0) return Promise.resolve(void 0);
|
|
13770
|
-
return new Promise((
|
|
13771
|
-
const timer = setTimeout(() =>
|
|
13712
|
+
return new Promise((resolve20) => {
|
|
13713
|
+
const timer = setTimeout(() => resolve20(void 0), timeoutMs);
|
|
13772
13714
|
timer.unref?.();
|
|
13773
13715
|
void promise.then((value) => {
|
|
13774
13716
|
clearTimeout(timer);
|
|
13775
|
-
|
|
13717
|
+
resolve20(value);
|
|
13776
13718
|
}, () => {
|
|
13777
13719
|
clearTimeout(timer);
|
|
13778
|
-
|
|
13720
|
+
resolve20(void 0);
|
|
13779
13721
|
});
|
|
13780
13722
|
});
|
|
13781
13723
|
}
|
|
@@ -14157,17 +14099,17 @@ var AutoIndexCoordinator = class {
|
|
|
14157
14099
|
}
|
|
14158
14100
|
}
|
|
14159
14101
|
waitForBatteryRetry(delayMs) {
|
|
14160
|
-
return new Promise((
|
|
14102
|
+
return new Promise((resolve20) => {
|
|
14161
14103
|
const timer = setTimeout(() => {
|
|
14162
14104
|
if (this.batteryRetryTimer === timer) {
|
|
14163
14105
|
this.batteryRetryTimer = null;
|
|
14164
14106
|
this.resolveBatteryRetry = null;
|
|
14165
14107
|
}
|
|
14166
|
-
|
|
14108
|
+
resolve20();
|
|
14167
14109
|
}, delayMs);
|
|
14168
14110
|
timer.unref?.();
|
|
14169
14111
|
this.batteryRetryTimer = timer;
|
|
14170
|
-
this.resolveBatteryRetry =
|
|
14112
|
+
this.resolveBatteryRetry = resolve20;
|
|
14171
14113
|
});
|
|
14172
14114
|
}
|
|
14173
14115
|
cancelBatteryRetry() {
|
|
@@ -14175,9 +14117,9 @@ var AutoIndexCoordinator = class {
|
|
|
14175
14117
|
clearTimeout(this.batteryRetryTimer);
|
|
14176
14118
|
this.batteryRetryTimer = null;
|
|
14177
14119
|
}
|
|
14178
|
-
const
|
|
14120
|
+
const resolve20 = this.resolveBatteryRetry;
|
|
14179
14121
|
this.resolveBatteryRetry = null;
|
|
14180
|
-
|
|
14122
|
+
resolve20?.();
|
|
14181
14123
|
}
|
|
14182
14124
|
finishBatteryCheck(batteryCheck) {
|
|
14183
14125
|
if (this.batteryCheck !== batteryCheck) return;
|
|
@@ -14852,12 +14794,12 @@ async function getCallGraphPath(projectRoot, host, from, to, maxDepth, fromFileP
|
|
|
14852
14794
|
if (fromResolution.status !== "resolved" || toResolution.status !== "resolved") {
|
|
14853
14795
|
return { from: fromResolution, to: toResolution, path: [] };
|
|
14854
14796
|
}
|
|
14855
|
-
const
|
|
14797
|
+
const path33 = await indexer.findCallPathBySymbolIds(
|
|
14856
14798
|
fromResolution.symbolId,
|
|
14857
14799
|
toResolution.symbolId,
|
|
14858
14800
|
maxDepth
|
|
14859
14801
|
);
|
|
14860
|
-
return { from: fromResolution, to: toResolution, path:
|
|
14802
|
+
return { from: fromResolution, to: toResolution, path: path33 };
|
|
14861
14803
|
}
|
|
14862
14804
|
async function runIndexCodebase(projectRoot, host, args, onProgress) {
|
|
14863
14805
|
const root = getProjectRoot(projectRoot, host);
|
|
@@ -15482,7 +15424,7 @@ async function resolveCodebaseContextUnmeasured(projectRoot, host, input) {
|
|
|
15482
15424
|
const directory = input.directory ?? void 0;
|
|
15483
15425
|
const tokenBudget = input.tokenBudget ?? void 0;
|
|
15484
15426
|
if (from && to) {
|
|
15485
|
-
const
|
|
15427
|
+
const path33 = await getCallGraphPath(
|
|
15486
15428
|
projectRoot,
|
|
15487
15429
|
host,
|
|
15488
15430
|
from,
|
|
@@ -15491,25 +15433,25 @@ async function resolveCodebaseContextUnmeasured(projectRoot, host, input) {
|
|
|
15491
15433
|
fromFilePath,
|
|
15492
15434
|
toFilePath
|
|
15493
15435
|
);
|
|
15494
|
-
const pathText = formatCallGraphPathResult(
|
|
15495
|
-
if (
|
|
15436
|
+
const pathText = formatCallGraphPathResult(path33);
|
|
15437
|
+
if (path33.path.length > 0) {
|
|
15496
15438
|
const fitted2 = fitTextToContextBudget(
|
|
15497
15439
|
pathText,
|
|
15498
15440
|
tokenBudget
|
|
15499
15441
|
);
|
|
15500
15442
|
return {
|
|
15501
15443
|
text: fitted2.text,
|
|
15502
|
-
details: fittedDetails("path", fitted2,
|
|
15444
|
+
details: fittedDetails("path", fitted2, path33.path.length)
|
|
15503
15445
|
};
|
|
15504
15446
|
}
|
|
15505
|
-
if (
|
|
15447
|
+
if (path33.from.status !== "resolved" || path33.to.status !== "resolved") {
|
|
15506
15448
|
const fitted2 = fitTextToContextBudget(pathText, tokenBudget);
|
|
15507
15449
|
return {
|
|
15508
15450
|
text: fitted2.text,
|
|
15509
15451
|
details: fittedDetails("path", fitted2, 0)
|
|
15510
15452
|
};
|
|
15511
15453
|
}
|
|
15512
|
-
const resolvedFrom =
|
|
15454
|
+
const resolvedFrom = path33.from;
|
|
15513
15455
|
const { callers } = await getCallGraphData(projectRoot, host, {
|
|
15514
15456
|
name: to,
|
|
15515
15457
|
direction: "callers",
|
|
@@ -15986,9 +15928,9 @@ function getRelevantEvidence(query) {
|
|
|
15986
15928
|
});
|
|
15987
15929
|
}
|
|
15988
15930
|
if (query.expected.acceptableFiles) {
|
|
15989
|
-
for (const
|
|
15931
|
+
for (const path33 of query.expected.acceptableFiles) {
|
|
15990
15932
|
legacyEvidence.push({
|
|
15991
|
-
path:
|
|
15933
|
+
path: path33,
|
|
15992
15934
|
...query.expected.symbol !== void 0 ? { symbol: query.expected.symbol } : {},
|
|
15993
15935
|
relevance: 1
|
|
15994
15936
|
});
|
|
@@ -16485,68 +16427,68 @@ function isStringArray4(value) {
|
|
|
16485
16427
|
function isNonEmptyString(value) {
|
|
16486
16428
|
return typeof value === "string" && value.trim().length > 0;
|
|
16487
16429
|
}
|
|
16488
|
-
function asPositiveNumber(value,
|
|
16430
|
+
function asPositiveNumber(value, path33) {
|
|
16489
16431
|
if (typeof value !== "number" || Number.isNaN(value) || value < 0) {
|
|
16490
|
-
throw new Error(`${
|
|
16432
|
+
throw new Error(`${path33} must be a non-negative number`);
|
|
16491
16433
|
}
|
|
16492
16434
|
return value;
|
|
16493
16435
|
}
|
|
16494
|
-
function parseQueryType(value,
|
|
16436
|
+
function parseQueryType(value, path33) {
|
|
16495
16437
|
if (value === "definition" || value === "implementation-intent" || value === "similarity" || value === "keyword-heavy" || value === "conceptual") {
|
|
16496
16438
|
return value;
|
|
16497
16439
|
}
|
|
16498
16440
|
throw new Error(
|
|
16499
|
-
`${
|
|
16441
|
+
`${path33} must be one of: definition, implementation-intent, similarity, keyword-heavy, conceptual`
|
|
16500
16442
|
);
|
|
16501
16443
|
}
|
|
16502
|
-
function parseExpectedRoute(value,
|
|
16444
|
+
function parseExpectedRoute(value, path33) {
|
|
16503
16445
|
if (value === void 0) return void 0;
|
|
16504
16446
|
if (value === "search" || value === "definition") return value;
|
|
16505
|
-
throw new Error(`${
|
|
16447
|
+
throw new Error(`${path33} must be one of: search, definition`);
|
|
16506
16448
|
}
|
|
16507
|
-
function parseExpectedOutcome(value,
|
|
16449
|
+
function parseExpectedOutcome(value, path33) {
|
|
16508
16450
|
if (value === void 0) return void 0;
|
|
16509
16451
|
if (value === "results" || value === "no-results") {
|
|
16510
16452
|
return value;
|
|
16511
16453
|
}
|
|
16512
|
-
throw new Error(`${
|
|
16454
|
+
throw new Error(`${path33} must be one of: results, no-results`);
|
|
16513
16455
|
}
|
|
16514
|
-
function parseRecoveryExpectation(value,
|
|
16456
|
+
function parseRecoveryExpectation(value, path33) {
|
|
16515
16457
|
if (value === void 0) return void 0;
|
|
16516
16458
|
if (value === "none" || value === "filter-relaxed") {
|
|
16517
16459
|
return value;
|
|
16518
16460
|
}
|
|
16519
|
-
throw new Error(`${
|
|
16461
|
+
throw new Error(`${path33} must be one of: none, filter-relaxed`);
|
|
16520
16462
|
}
|
|
16521
|
-
function parseQueryDifficulty(value,
|
|
16463
|
+
function parseQueryDifficulty(value, path33) {
|
|
16522
16464
|
if (value === void 0) return void 0;
|
|
16523
16465
|
if (value === "easy" || value === "medium" || value === "hard") {
|
|
16524
16466
|
return value;
|
|
16525
16467
|
}
|
|
16526
|
-
throw new Error(`${
|
|
16468
|
+
throw new Error(`${path33} must be one of: easy, medium, hard`);
|
|
16527
16469
|
}
|
|
16528
|
-
function parseQueryTags(value,
|
|
16470
|
+
function parseQueryTags(value, path33) {
|
|
16529
16471
|
if (value === void 0) return void 0;
|
|
16530
16472
|
if (!isStringArray4(value) || value.some((tag) => tag.trim().length === 0)) {
|
|
16531
|
-
throw new Error(`${
|
|
16473
|
+
throw new Error(`${path33} must be an array of non-empty strings`);
|
|
16532
16474
|
}
|
|
16533
16475
|
if (value.length > 16) {
|
|
16534
|
-
throw new Error(`${
|
|
16476
|
+
throw new Error(`${path33} must contain at most 16 tags`);
|
|
16535
16477
|
}
|
|
16536
16478
|
return value;
|
|
16537
16479
|
}
|
|
16538
|
-
function parseQueryArgs(value,
|
|
16480
|
+
function parseQueryArgs(value, path33) {
|
|
16539
16481
|
if (value === void 0) return void 0;
|
|
16540
16482
|
if (!isRecord3(value)) {
|
|
16541
|
-
throw new Error(`${
|
|
16542
|
-
}
|
|
16543
|
-
const symbol = parseStringOrUndefined(value.symbol, `${
|
|
16544
|
-
const filePath = parseStringOrUndefined(value.filePath, `${
|
|
16545
|
-
const fileType = parseStringOrUndefined(value.fileType, `${
|
|
16546
|
-
const directory = parseStringOrUndefined(value.directory, `${
|
|
16547
|
-
const callerLimit = parsePositiveIntegerOrUndefined(value.callerLimit, `${
|
|
16548
|
-
const calleeLimit = parsePositiveIntegerOrUndefined(value.calleeLimit, `${
|
|
16549
|
-
const tokenBudget = parsePositiveIntegerOrUndefined(value.tokenBudget, `${
|
|
16483
|
+
throw new Error(`${path33} must be an object`);
|
|
16484
|
+
}
|
|
16485
|
+
const symbol = parseStringOrUndefined(value.symbol, `${path33}.symbol`);
|
|
16486
|
+
const filePath = parseStringOrUndefined(value.filePath, `${path33}.filePath`);
|
|
16487
|
+
const fileType = parseStringOrUndefined(value.fileType, `${path33}.fileType`);
|
|
16488
|
+
const directory = parseStringOrUndefined(value.directory, `${path33}.directory`);
|
|
16489
|
+
const callerLimit = parsePositiveIntegerOrUndefined(value.callerLimit, `${path33}.callerLimit`);
|
|
16490
|
+
const calleeLimit = parsePositiveIntegerOrUndefined(value.calleeLimit, `${path33}.calleeLimit`);
|
|
16491
|
+
const tokenBudget = parsePositiveIntegerOrUndefined(value.tokenBudget, `${path33}.tokenBudget`);
|
|
16550
16492
|
return {
|
|
16551
16493
|
...symbol !== void 0 ? { symbol } : {},
|
|
16552
16494
|
...filePath !== void 0 ? { filePath } : {},
|
|
@@ -16557,50 +16499,50 @@ function parseQueryArgs(value, path31) {
|
|
|
16557
16499
|
...tokenBudget !== void 0 ? { tokenBudget } : {}
|
|
16558
16500
|
};
|
|
16559
16501
|
}
|
|
16560
|
-
function parsePositiveIntegerOrUndefined(value,
|
|
16502
|
+
function parsePositiveIntegerOrUndefined(value, path33) {
|
|
16561
16503
|
if (value === void 0 || value === null) return void 0;
|
|
16562
16504
|
if (typeof value !== "number" || !Number.isInteger(value) || value <= 0) {
|
|
16563
|
-
throw new Error(`${
|
|
16505
|
+
throw new Error(`${path33} must be a positive integer`);
|
|
16564
16506
|
}
|
|
16565
16507
|
return value;
|
|
16566
16508
|
}
|
|
16567
16509
|
var SEMVER_VERSION_PATTERN = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
|
|
16568
|
-
function parseSemanticVersion(value,
|
|
16510
|
+
function parseSemanticVersion(value, path33) {
|
|
16569
16511
|
if (!isNonEmptyString(value)) {
|
|
16570
|
-
throw new Error(`${
|
|
16512
|
+
throw new Error(`${path33} must be a non-empty string`);
|
|
16571
16513
|
}
|
|
16572
16514
|
if (!SEMVER_VERSION_PATTERN.test(value)) {
|
|
16573
|
-
throw new Error(`${
|
|
16515
|
+
throw new Error(`${path33} must be a valid semantic version (MAJOR.MINOR.PATCH)`);
|
|
16574
16516
|
}
|
|
16575
16517
|
return value;
|
|
16576
16518
|
}
|
|
16577
|
-
function parseRetrievalMode(value,
|
|
16519
|
+
function parseRetrievalMode(value, path33) {
|
|
16578
16520
|
if (value === void 0 || value === "search") return "search";
|
|
16579
16521
|
if (value === "context" || value === "edit-context") return value;
|
|
16580
|
-
throw new Error(`${
|
|
16522
|
+
throw new Error(`${path33} must be one of: search, context, edit-context`);
|
|
16581
16523
|
}
|
|
16582
|
-
function parseStringOrUndefined(value,
|
|
16524
|
+
function parseStringOrUndefined(value, path33) {
|
|
16583
16525
|
if (value === void 0 || value === null) return void 0;
|
|
16584
16526
|
if (!isNonEmptyString(value)) {
|
|
16585
|
-
throw new Error(`${
|
|
16527
|
+
throw new Error(`${path33} must be a non-empty string`);
|
|
16586
16528
|
}
|
|
16587
16529
|
return value;
|
|
16588
16530
|
}
|
|
16589
|
-
function parseGradedEvidence(value,
|
|
16531
|
+
function parseGradedEvidence(value, path33) {
|
|
16590
16532
|
if (value === void 0) return [];
|
|
16591
16533
|
if (!Array.isArray(value)) {
|
|
16592
|
-
throw new Error(`${
|
|
16534
|
+
throw new Error(`${path33} must be an array`);
|
|
16593
16535
|
}
|
|
16594
16536
|
return value.map((entry, index) => {
|
|
16595
16537
|
if (!isRecord3(entry)) {
|
|
16596
|
-
throw new Error(`${
|
|
16538
|
+
throw new Error(`${path33}[${index}] must be an object`);
|
|
16597
16539
|
}
|
|
16598
|
-
const evidencePath = parseStringOrUndefined(entry.path, `${
|
|
16540
|
+
const evidencePath = parseStringOrUndefined(entry.path, `${path33}[${index}].path`);
|
|
16599
16541
|
if (evidencePath === void 0) {
|
|
16600
|
-
throw new Error(`${
|
|
16542
|
+
throw new Error(`${path33}[${index}].path is required`);
|
|
16601
16543
|
}
|
|
16602
|
-
const symbol = parseStringOrUndefined(entry.symbol, `${
|
|
16603
|
-
const relevance = parseEvidenceRelevance(entry.relevance, `${
|
|
16544
|
+
const symbol = parseStringOrUndefined(entry.symbol, `${path33}[${index}].symbol`);
|
|
16545
|
+
const relevance = parseEvidenceRelevance(entry.relevance, `${path33}[${index}].relevance`);
|
|
16604
16546
|
return {
|
|
16605
16547
|
path: evidencePath,
|
|
16606
16548
|
...symbol !== void 0 ? { symbol } : {},
|
|
@@ -16608,27 +16550,27 @@ function parseGradedEvidence(value, path31) {
|
|
|
16608
16550
|
};
|
|
16609
16551
|
});
|
|
16610
16552
|
}
|
|
16611
|
-
function parseEvidenceRelevance(value,
|
|
16553
|
+
function parseEvidenceRelevance(value, path33) {
|
|
16612
16554
|
if (value === void 0) {
|
|
16613
|
-
throw new Error(`${
|
|
16555
|
+
throw new Error(`${path33} is required`);
|
|
16614
16556
|
}
|
|
16615
16557
|
if (value !== 1 && value !== 2 && value !== 3) {
|
|
16616
|
-
throw new Error(`${
|
|
16558
|
+
throw new Error(`${path33} must be 1, 2, or 3`);
|
|
16617
16559
|
}
|
|
16618
16560
|
return value;
|
|
16619
16561
|
}
|
|
16620
|
-
function parseExpectedGraphNeighbor(value,
|
|
16562
|
+
function parseExpectedGraphNeighbor(value, path33) {
|
|
16621
16563
|
if (value === void 0) return void 0;
|
|
16622
16564
|
if (!isRecord3(value)) {
|
|
16623
|
-
throw new Error(`${
|
|
16565
|
+
throw new Error(`${path33} must be an object`);
|
|
16624
16566
|
}
|
|
16625
16567
|
if (value.direction !== "caller" && value.direction !== "callee") {
|
|
16626
|
-
throw new Error(`${
|
|
16568
|
+
throw new Error(`${path33}.direction must be one of: caller, callee`);
|
|
16627
16569
|
}
|
|
16628
|
-
const filePath = parseStringOrUndefined(value.filePath, `${
|
|
16629
|
-
const symbol = parseStringOrUndefined(value.symbol, `${
|
|
16570
|
+
const filePath = parseStringOrUndefined(value.filePath, `${path33}.filePath`);
|
|
16571
|
+
const symbol = parseStringOrUndefined(value.symbol, `${path33}.symbol`);
|
|
16630
16572
|
if (filePath === void 0 && symbol === void 0) {
|
|
16631
|
-
throw new Error(`${
|
|
16573
|
+
throw new Error(`${path33} must include filePath or symbol`);
|
|
16632
16574
|
}
|
|
16633
16575
|
return {
|
|
16634
16576
|
direction: value.direction,
|
|
@@ -16636,9 +16578,9 @@ function parseExpectedGraphNeighbor(value, path31) {
|
|
|
16636
16578
|
...symbol !== void 0 ? { symbol } : {}
|
|
16637
16579
|
};
|
|
16638
16580
|
}
|
|
16639
|
-
function parseExpected(input,
|
|
16581
|
+
function parseExpected(input, path33) {
|
|
16640
16582
|
if (!isRecord3(input)) {
|
|
16641
|
-
throw new Error(`${
|
|
16583
|
+
throw new Error(`${path33} must be an object`);
|
|
16642
16584
|
}
|
|
16643
16585
|
const filePathRaw = input.filePath;
|
|
16644
16586
|
const acceptableFilesRaw = input.acceptableFiles;
|
|
@@ -16649,29 +16591,29 @@ function parseExpected(input, path31) {
|
|
|
16649
16591
|
const recoveryExpectationRaw = input.recoveryExpectation;
|
|
16650
16592
|
const gradedEvidenceRaw = input.gradedEvidence;
|
|
16651
16593
|
const graphNeighborRaw = input.graphNeighbor;
|
|
16652
|
-
const filePath = parseStringOrUndefined(filePathRaw, `${
|
|
16594
|
+
const filePath = parseStringOrUndefined(filePathRaw, `${path33}.filePath`);
|
|
16653
16595
|
const acceptableFiles = isStringArray4(acceptableFilesRaw) ? acceptableFilesRaw : void 0;
|
|
16654
|
-
const gradedEvidence = parseGradedEvidence(gradedEvidenceRaw, `${
|
|
16655
|
-
const graphNeighbor = parseExpectedGraphNeighbor(graphNeighborRaw, `${
|
|
16656
|
-
const expectedOutcome = parseExpectedOutcome(expectedOutcomeRaw, `${
|
|
16596
|
+
const gradedEvidence = parseGradedEvidence(gradedEvidenceRaw, `${path33}.gradedEvidence`);
|
|
16597
|
+
const graphNeighbor = parseExpectedGraphNeighbor(graphNeighborRaw, `${path33}.graphNeighbor`);
|
|
16598
|
+
const expectedOutcome = parseExpectedOutcome(expectedOutcomeRaw, `${path33}.expectedOutcome`);
|
|
16657
16599
|
if (expectedOutcome !== "no-results" && !filePath && (!acceptableFiles || acceptableFiles.length === 0) && gradedEvidence.length === 0) {
|
|
16658
16600
|
throw new Error(
|
|
16659
|
-
`${
|
|
16601
|
+
`${path33} must include expected.filePath, expected.acceptableFiles, or expected.gradedEvidence`
|
|
16660
16602
|
);
|
|
16661
16603
|
}
|
|
16662
16604
|
if (acceptableFilesRaw !== void 0 && !isStringArray4(acceptableFilesRaw)) {
|
|
16663
|
-
throw new Error(`${
|
|
16605
|
+
throw new Error(`${path33}.acceptableFiles must be an array of strings`);
|
|
16664
16606
|
}
|
|
16665
16607
|
if (symbolRaw !== void 0 && typeof symbolRaw !== "string") {
|
|
16666
|
-
throw new Error(`${
|
|
16608
|
+
throw new Error(`${path33}.symbol must be a string when provided`);
|
|
16667
16609
|
}
|
|
16668
16610
|
if (branchRaw !== void 0 && typeof branchRaw !== "string") {
|
|
16669
|
-
throw new Error(`${
|
|
16611
|
+
throw new Error(`${path33}.branch must be a string when provided`);
|
|
16670
16612
|
}
|
|
16671
|
-
const expectedRoute = parseExpectedRoute(expectedRouteRaw, `${
|
|
16613
|
+
const expectedRoute = parseExpectedRoute(expectedRouteRaw, `${path33}.expectedRoute`);
|
|
16672
16614
|
const recoveryExpectation = parseRecoveryExpectation(
|
|
16673
16615
|
recoveryExpectationRaw,
|
|
16674
|
-
`${
|
|
16616
|
+
`${path33}.recoveryExpectation`
|
|
16675
16617
|
);
|
|
16676
16618
|
return {
|
|
16677
16619
|
filePath,
|
|
@@ -16685,13 +16627,13 @@ function parseExpected(input, path31) {
|
|
|
16685
16627
|
...graphNeighbor !== void 0 ? { graphNeighbor } : {}
|
|
16686
16628
|
};
|
|
16687
16629
|
}
|
|
16688
|
-
function parseQueryLanguage(value,
|
|
16689
|
-
return parseStringOrUndefined(value,
|
|
16630
|
+
function parseQueryLanguage(value, path33) {
|
|
16631
|
+
return parseStringOrUndefined(value, path33);
|
|
16690
16632
|
}
|
|
16691
16633
|
function parseQuery(input, index) {
|
|
16692
|
-
const
|
|
16634
|
+
const path33 = `queries[${index}]`;
|
|
16693
16635
|
if (!isRecord3(input)) {
|
|
16694
|
-
throw new Error(`${
|
|
16636
|
+
throw new Error(`${path33} must be an object`);
|
|
16695
16637
|
}
|
|
16696
16638
|
const id = input.id;
|
|
16697
16639
|
const query = input.query;
|
|
@@ -16703,21 +16645,21 @@ function parseQuery(input, index) {
|
|
|
16703
16645
|
const tags = input.tags;
|
|
16704
16646
|
const args = input.args;
|
|
16705
16647
|
if (typeof id !== "string" || id.trim().length === 0) {
|
|
16706
|
-
throw new Error(`${
|
|
16648
|
+
throw new Error(`${path33}.id must be a non-empty string`);
|
|
16707
16649
|
}
|
|
16708
16650
|
if (typeof query !== "string" || query.trim().length === 0) {
|
|
16709
|
-
throw new Error(`${
|
|
16651
|
+
throw new Error(`${path33}.query must be a non-empty string`);
|
|
16710
16652
|
}
|
|
16711
16653
|
return {
|
|
16712
16654
|
id,
|
|
16713
16655
|
query,
|
|
16714
|
-
queryType: parseQueryType(queryType, `${
|
|
16715
|
-
retrievalMode: parseRetrievalMode(retrievalMode, `${
|
|
16716
|
-
language: parseQueryLanguage(language, `${
|
|
16717
|
-
difficulty: parseQueryDifficulty(difficulty, `${
|
|
16718
|
-
args: parseQueryArgs(args, `${
|
|
16719
|
-
tags: parseQueryTags(tags, `${
|
|
16720
|
-
expected: parseExpected(expected, `${
|
|
16656
|
+
queryType: parseQueryType(queryType, `${path33}.queryType`),
|
|
16657
|
+
retrievalMode: parseRetrievalMode(retrievalMode, `${path33}.retrievalMode`),
|
|
16658
|
+
language: parseQueryLanguage(language, `${path33}.language`),
|
|
16659
|
+
difficulty: parseQueryDifficulty(difficulty, `${path33}.difficulty`),
|
|
16660
|
+
args: parseQueryArgs(args, `${path33}.args`),
|
|
16661
|
+
tags: parseQueryTags(tags, `${path33}.tags`),
|
|
16662
|
+
expected: parseExpected(expected, `${path33}.expected`)
|
|
16721
16663
|
};
|
|
16722
16664
|
}
|
|
16723
16665
|
function parseGoldenDataset(raw, sourceLabel) {
|
|
@@ -17684,7 +17626,7 @@ async function executeCallGraph(projectRoot, host, args) {
|
|
|
17684
17626
|
return { text: formatCallGraphResult(await getCallGraphData(projectRoot, host, args)) };
|
|
17685
17627
|
}
|
|
17686
17628
|
async function executeCallGraphPath(projectRoot, host, args) {
|
|
17687
|
-
const
|
|
17629
|
+
const path33 = await getCallGraphPath(
|
|
17688
17630
|
projectRoot,
|
|
17689
17631
|
host,
|
|
17690
17632
|
args.from,
|
|
@@ -17693,7 +17635,7 @@ async function executeCallGraphPath(projectRoot, host, args) {
|
|
|
17693
17635
|
args.fromFilePath,
|
|
17694
17636
|
args.toFilePath
|
|
17695
17637
|
);
|
|
17696
|
-
return { text: formatCallGraphPathResult(
|
|
17638
|
+
return { text: formatCallGraphPathResult(path33) };
|
|
17697
17639
|
}
|
|
17698
17640
|
async function executeCodeCommunities(projectRoot, host, args) {
|
|
17699
17641
|
const result = await getCodeCommunities(projectRoot, host, args);
|
|
@@ -18272,7 +18214,7 @@ var ReaddirpStream = class extends import_node_stream.Readable {
|
|
|
18272
18214
|
this._directoryFilter = normalizeFilter(opts.directoryFilter);
|
|
18273
18215
|
const statMethod = opts.lstat ? import_promises.lstat : import_promises.stat;
|
|
18274
18216
|
if (wantBigintFsStats) {
|
|
18275
|
-
this._stat = (
|
|
18217
|
+
this._stat = (path33) => statMethod(path33, { bigint: true });
|
|
18276
18218
|
} else {
|
|
18277
18219
|
this._stat = statMethod;
|
|
18278
18220
|
}
|
|
@@ -18297,8 +18239,8 @@ var ReaddirpStream = class extends import_node_stream.Readable {
|
|
|
18297
18239
|
const par = this.parent;
|
|
18298
18240
|
const fil = par && par.files;
|
|
18299
18241
|
if (fil && fil.length > 0) {
|
|
18300
|
-
const { path:
|
|
18301
|
-
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent,
|
|
18242
|
+
const { path: path33, depth } = par;
|
|
18243
|
+
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path33));
|
|
18302
18244
|
const awaited = await Promise.all(slice);
|
|
18303
18245
|
for (const entry of awaited) {
|
|
18304
18246
|
if (!entry)
|
|
@@ -18338,20 +18280,20 @@ var ReaddirpStream = class extends import_node_stream.Readable {
|
|
|
18338
18280
|
this.reading = false;
|
|
18339
18281
|
}
|
|
18340
18282
|
}
|
|
18341
|
-
async _exploreDir(
|
|
18283
|
+
async _exploreDir(path33, depth) {
|
|
18342
18284
|
let files;
|
|
18343
18285
|
try {
|
|
18344
|
-
files = await (0, import_promises.readdir)(
|
|
18286
|
+
files = await (0, import_promises.readdir)(path33, this._rdOptions);
|
|
18345
18287
|
} catch (error) {
|
|
18346
18288
|
this._onError(error);
|
|
18347
18289
|
}
|
|
18348
|
-
return { files, depth, path:
|
|
18290
|
+
return { files, depth, path: path33 };
|
|
18349
18291
|
}
|
|
18350
|
-
async _formatEntry(dirent,
|
|
18292
|
+
async _formatEntry(dirent, path33) {
|
|
18351
18293
|
let entry;
|
|
18352
18294
|
const basename8 = this._isDirent ? dirent.name : dirent;
|
|
18353
18295
|
try {
|
|
18354
|
-
const fullPath = (0, import_node_path.resolve)((0, import_node_path.join)(
|
|
18296
|
+
const fullPath = (0, import_node_path.resolve)((0, import_node_path.join)(path33, basename8));
|
|
18355
18297
|
entry = { path: (0, import_node_path.relative)(this._root, fullPath), fullPath, basename: basename8 };
|
|
18356
18298
|
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
18357
18299
|
} catch (err) {
|
|
@@ -18751,16 +18693,16 @@ var delFromSet = (main, prop, item) => {
|
|
|
18751
18693
|
};
|
|
18752
18694
|
var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
|
|
18753
18695
|
var FsWatchInstances = /* @__PURE__ */ new Map();
|
|
18754
|
-
function createFsWatchInstance(
|
|
18696
|
+
function createFsWatchInstance(path33, options, listener, errHandler, emitRaw) {
|
|
18755
18697
|
const handleEvent = (rawEvent, evPath) => {
|
|
18756
|
-
listener(
|
|
18757
|
-
emitRaw(rawEvent, evPath, { watchedPath:
|
|
18758
|
-
if (evPath &&
|
|
18759
|
-
fsWatchBroadcast(sp.resolve(
|
|
18698
|
+
listener(path33);
|
|
18699
|
+
emitRaw(rawEvent, evPath, { watchedPath: path33 });
|
|
18700
|
+
if (evPath && path33 !== evPath) {
|
|
18701
|
+
fsWatchBroadcast(sp.resolve(path33, evPath), KEY_LISTENERS, sp.join(path33, evPath));
|
|
18760
18702
|
}
|
|
18761
18703
|
};
|
|
18762
18704
|
try {
|
|
18763
|
-
return (0, import_node_fs.watch)(
|
|
18705
|
+
return (0, import_node_fs.watch)(path33, {
|
|
18764
18706
|
persistent: options.persistent
|
|
18765
18707
|
}, handleEvent);
|
|
18766
18708
|
} catch (error) {
|
|
@@ -18776,12 +18718,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
|
|
|
18776
18718
|
listener(val1, val2, val3);
|
|
18777
18719
|
});
|
|
18778
18720
|
};
|
|
18779
|
-
var setFsWatchListener = (
|
|
18721
|
+
var setFsWatchListener = (path33, fullPath, options, handlers) => {
|
|
18780
18722
|
const { listener, errHandler, rawEmitter } = handlers;
|
|
18781
18723
|
let cont = FsWatchInstances.get(fullPath);
|
|
18782
18724
|
let watcher;
|
|
18783
18725
|
if (!options.persistent) {
|
|
18784
|
-
watcher = createFsWatchInstance(
|
|
18726
|
+
watcher = createFsWatchInstance(path33, options, listener, errHandler, rawEmitter);
|
|
18785
18727
|
if (!watcher)
|
|
18786
18728
|
return;
|
|
18787
18729
|
return watcher.close.bind(watcher);
|
|
@@ -18792,7 +18734,7 @@ var setFsWatchListener = (path31, fullPath, options, handlers) => {
|
|
|
18792
18734
|
addAndConvert(cont, KEY_RAW, rawEmitter);
|
|
18793
18735
|
} else {
|
|
18794
18736
|
watcher = createFsWatchInstance(
|
|
18795
|
-
|
|
18737
|
+
path33,
|
|
18796
18738
|
options,
|
|
18797
18739
|
fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
|
|
18798
18740
|
errHandler,
|
|
@@ -18807,7 +18749,7 @@ var setFsWatchListener = (path31, fullPath, options, handlers) => {
|
|
|
18807
18749
|
cont.watcherUnusable = true;
|
|
18808
18750
|
if (isWindows && error.code === "EPERM") {
|
|
18809
18751
|
try {
|
|
18810
|
-
const fd = await (0, import_promises2.open)(
|
|
18752
|
+
const fd = await (0, import_promises2.open)(path33, "r");
|
|
18811
18753
|
await fd.close();
|
|
18812
18754
|
broadcastErr(error);
|
|
18813
18755
|
} catch (err) {
|
|
@@ -18838,7 +18780,7 @@ var setFsWatchListener = (path31, fullPath, options, handlers) => {
|
|
|
18838
18780
|
};
|
|
18839
18781
|
};
|
|
18840
18782
|
var FsWatchFileInstances = /* @__PURE__ */ new Map();
|
|
18841
|
-
var setFsWatchFileListener = (
|
|
18783
|
+
var setFsWatchFileListener = (path33, fullPath, options, handlers) => {
|
|
18842
18784
|
const { listener, rawEmitter } = handlers;
|
|
18843
18785
|
let cont = FsWatchFileInstances.get(fullPath);
|
|
18844
18786
|
const copts = cont && cont.options;
|
|
@@ -18860,7 +18802,7 @@ var setFsWatchFileListener = (path31, fullPath, options, handlers) => {
|
|
|
18860
18802
|
});
|
|
18861
18803
|
const currmtime = curr.mtimeMs;
|
|
18862
18804
|
if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
|
|
18863
|
-
foreach(cont.listeners, (listener2) => listener2(
|
|
18805
|
+
foreach(cont.listeners, (listener2) => listener2(path33, curr));
|
|
18864
18806
|
}
|
|
18865
18807
|
})
|
|
18866
18808
|
};
|
|
@@ -18890,13 +18832,13 @@ var NodeFsHandler = class {
|
|
|
18890
18832
|
* @param listener on fs change
|
|
18891
18833
|
* @returns closer for the watcher instance
|
|
18892
18834
|
*/
|
|
18893
|
-
_watchWithNodeFs(
|
|
18835
|
+
_watchWithNodeFs(path33, listener) {
|
|
18894
18836
|
const opts = this.fsw.options;
|
|
18895
|
-
const directory = sp.dirname(
|
|
18896
|
-
const basename8 = sp.basename(
|
|
18837
|
+
const directory = sp.dirname(path33);
|
|
18838
|
+
const basename8 = sp.basename(path33);
|
|
18897
18839
|
const parent = this.fsw._getWatchedDir(directory);
|
|
18898
18840
|
parent.add(basename8);
|
|
18899
|
-
const absolutePath = sp.resolve(
|
|
18841
|
+
const absolutePath = sp.resolve(path33);
|
|
18900
18842
|
const options = {
|
|
18901
18843
|
persistent: opts.persistent
|
|
18902
18844
|
};
|
|
@@ -18906,12 +18848,12 @@ var NodeFsHandler = class {
|
|
|
18906
18848
|
if (opts.usePolling) {
|
|
18907
18849
|
const enableBin = opts.interval !== opts.binaryInterval;
|
|
18908
18850
|
options.interval = enableBin && isBinaryPath(basename8) ? opts.binaryInterval : opts.interval;
|
|
18909
|
-
closer = setFsWatchFileListener(
|
|
18851
|
+
closer = setFsWatchFileListener(path33, absolutePath, options, {
|
|
18910
18852
|
listener,
|
|
18911
18853
|
rawEmitter: this.fsw._emitRaw
|
|
18912
18854
|
});
|
|
18913
18855
|
} else {
|
|
18914
|
-
closer = setFsWatchListener(
|
|
18856
|
+
closer = setFsWatchListener(path33, absolutePath, options, {
|
|
18915
18857
|
listener,
|
|
18916
18858
|
errHandler: this._boundHandleError,
|
|
18917
18859
|
rawEmitter: this.fsw._emitRaw
|
|
@@ -18933,7 +18875,7 @@ var NodeFsHandler = class {
|
|
|
18933
18875
|
let prevStats = stats;
|
|
18934
18876
|
if (parent.has(basename8))
|
|
18935
18877
|
return;
|
|
18936
|
-
const listener = async (
|
|
18878
|
+
const listener = async (path33, newStats) => {
|
|
18937
18879
|
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
|
|
18938
18880
|
return;
|
|
18939
18881
|
if (!newStats || newStats.mtimeMs === 0) {
|
|
@@ -18947,11 +18889,11 @@ var NodeFsHandler = class {
|
|
|
18947
18889
|
this.fsw._emit(EV.CHANGE, file, newStats2);
|
|
18948
18890
|
}
|
|
18949
18891
|
if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
|
|
18950
|
-
this.fsw._closeFile(
|
|
18892
|
+
this.fsw._closeFile(path33);
|
|
18951
18893
|
prevStats = newStats2;
|
|
18952
18894
|
const closer2 = this._watchWithNodeFs(file, listener);
|
|
18953
18895
|
if (closer2)
|
|
18954
|
-
this.fsw._addPathCloser(
|
|
18896
|
+
this.fsw._addPathCloser(path33, closer2);
|
|
18955
18897
|
} else {
|
|
18956
18898
|
prevStats = newStats2;
|
|
18957
18899
|
}
|
|
@@ -18983,7 +18925,7 @@ var NodeFsHandler = class {
|
|
|
18983
18925
|
* @param item basename of this item
|
|
18984
18926
|
* @returns true if no more processing is needed for this entry.
|
|
18985
18927
|
*/
|
|
18986
|
-
async _handleSymlink(entry, directory,
|
|
18928
|
+
async _handleSymlink(entry, directory, path33, item) {
|
|
18987
18929
|
if (this.fsw.closed) {
|
|
18988
18930
|
return;
|
|
18989
18931
|
}
|
|
@@ -18993,7 +18935,7 @@ var NodeFsHandler = class {
|
|
|
18993
18935
|
this.fsw._incrReadyCount();
|
|
18994
18936
|
let linkPath;
|
|
18995
18937
|
try {
|
|
18996
|
-
linkPath = await (0, import_promises2.realpath)(
|
|
18938
|
+
linkPath = await (0, import_promises2.realpath)(path33);
|
|
18997
18939
|
} catch (e) {
|
|
18998
18940
|
this.fsw._emitReady();
|
|
18999
18941
|
return true;
|
|
@@ -19003,12 +18945,12 @@ var NodeFsHandler = class {
|
|
|
19003
18945
|
if (dir.has(item)) {
|
|
19004
18946
|
if (this.fsw._symlinkPaths.get(full) !== linkPath) {
|
|
19005
18947
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
19006
|
-
this.fsw._emit(EV.CHANGE,
|
|
18948
|
+
this.fsw._emit(EV.CHANGE, path33, entry.stats);
|
|
19007
18949
|
}
|
|
19008
18950
|
} else {
|
|
19009
18951
|
dir.add(item);
|
|
19010
18952
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
19011
|
-
this.fsw._emit(EV.ADD,
|
|
18953
|
+
this.fsw._emit(EV.ADD, path33, entry.stats);
|
|
19012
18954
|
}
|
|
19013
18955
|
this.fsw._emitReady();
|
|
19014
18956
|
return true;
|
|
@@ -19038,9 +18980,9 @@ var NodeFsHandler = class {
|
|
|
19038
18980
|
return;
|
|
19039
18981
|
}
|
|
19040
18982
|
const item = entry.path;
|
|
19041
|
-
let
|
|
18983
|
+
let path33 = sp.join(directory, item);
|
|
19042
18984
|
current.add(item);
|
|
19043
|
-
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory,
|
|
18985
|
+
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path33, item)) {
|
|
19044
18986
|
return;
|
|
19045
18987
|
}
|
|
19046
18988
|
if (this.fsw.closed) {
|
|
@@ -19049,11 +18991,11 @@ var NodeFsHandler = class {
|
|
|
19049
18991
|
}
|
|
19050
18992
|
if (item === target || !target && !previous.has(item)) {
|
|
19051
18993
|
this.fsw._incrReadyCount();
|
|
19052
|
-
|
|
19053
|
-
this._addToNodeFs(
|
|
18994
|
+
path33 = sp.join(dir, sp.relative(dir, path33));
|
|
18995
|
+
this._addToNodeFs(path33, initialAdd, wh, depth + 1);
|
|
19054
18996
|
}
|
|
19055
18997
|
}).on(EV.ERROR, this._boundHandleError);
|
|
19056
|
-
return new Promise((
|
|
18998
|
+
return new Promise((resolve20, reject) => {
|
|
19057
18999
|
if (!stream)
|
|
19058
19000
|
return reject();
|
|
19059
19001
|
stream.once(STR_END, () => {
|
|
@@ -19062,7 +19004,7 @@ var NodeFsHandler = class {
|
|
|
19062
19004
|
return;
|
|
19063
19005
|
}
|
|
19064
19006
|
const wasThrottled = throttler ? throttler.clear() : false;
|
|
19065
|
-
|
|
19007
|
+
resolve20(void 0);
|
|
19066
19008
|
previous.getChildren().filter((item) => {
|
|
19067
19009
|
return item !== directory && !current.has(item);
|
|
19068
19010
|
}).forEach((item) => {
|
|
@@ -19119,13 +19061,13 @@ var NodeFsHandler = class {
|
|
|
19119
19061
|
* @param depth Child path actually targeted for watch
|
|
19120
19062
|
* @param target Child path actually targeted for watch
|
|
19121
19063
|
*/
|
|
19122
|
-
async _addToNodeFs(
|
|
19064
|
+
async _addToNodeFs(path33, initialAdd, priorWh, depth, target) {
|
|
19123
19065
|
const ready = this.fsw._emitReady;
|
|
19124
|
-
if (this.fsw._isIgnored(
|
|
19066
|
+
if (this.fsw._isIgnored(path33) || this.fsw.closed) {
|
|
19125
19067
|
ready();
|
|
19126
19068
|
return false;
|
|
19127
19069
|
}
|
|
19128
|
-
const wh = this.fsw._getWatchHelpers(
|
|
19070
|
+
const wh = this.fsw._getWatchHelpers(path33);
|
|
19129
19071
|
if (priorWh) {
|
|
19130
19072
|
wh.filterPath = (entry) => priorWh.filterPath(entry);
|
|
19131
19073
|
wh.filterDir = (entry) => priorWh.filterDir(entry);
|
|
@@ -19141,8 +19083,8 @@ var NodeFsHandler = class {
|
|
|
19141
19083
|
const follow = this.fsw.options.followSymlinks;
|
|
19142
19084
|
let closer;
|
|
19143
19085
|
if (stats.isDirectory()) {
|
|
19144
|
-
const absPath = sp.resolve(
|
|
19145
|
-
const targetPath = follow ? await (0, import_promises2.realpath)(
|
|
19086
|
+
const absPath = sp.resolve(path33);
|
|
19087
|
+
const targetPath = follow ? await (0, import_promises2.realpath)(path33) : path33;
|
|
19146
19088
|
if (this.fsw.closed)
|
|
19147
19089
|
return;
|
|
19148
19090
|
closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
|
|
@@ -19152,29 +19094,29 @@ var NodeFsHandler = class {
|
|
|
19152
19094
|
this.fsw._symlinkPaths.set(absPath, targetPath);
|
|
19153
19095
|
}
|
|
19154
19096
|
} else if (stats.isSymbolicLink()) {
|
|
19155
|
-
const targetPath = follow ? await (0, import_promises2.realpath)(
|
|
19097
|
+
const targetPath = follow ? await (0, import_promises2.realpath)(path33) : path33;
|
|
19156
19098
|
if (this.fsw.closed)
|
|
19157
19099
|
return;
|
|
19158
19100
|
const parent = sp.dirname(wh.watchPath);
|
|
19159
19101
|
this.fsw._getWatchedDir(parent).add(wh.watchPath);
|
|
19160
19102
|
this.fsw._emit(EV.ADD, wh.watchPath, stats);
|
|
19161
|
-
closer = await this._handleDir(parent, stats, initialAdd, depth,
|
|
19103
|
+
closer = await this._handleDir(parent, stats, initialAdd, depth, path33, wh, targetPath);
|
|
19162
19104
|
if (this.fsw.closed)
|
|
19163
19105
|
return;
|
|
19164
19106
|
if (targetPath !== void 0) {
|
|
19165
|
-
this.fsw._symlinkPaths.set(sp.resolve(
|
|
19107
|
+
this.fsw._symlinkPaths.set(sp.resolve(path33), targetPath);
|
|
19166
19108
|
}
|
|
19167
19109
|
} else {
|
|
19168
19110
|
closer = this._handleFile(wh.watchPath, stats, initialAdd);
|
|
19169
19111
|
}
|
|
19170
19112
|
ready();
|
|
19171
19113
|
if (closer)
|
|
19172
|
-
this.fsw._addPathCloser(
|
|
19114
|
+
this.fsw._addPathCloser(path33, closer);
|
|
19173
19115
|
return false;
|
|
19174
19116
|
} catch (error) {
|
|
19175
19117
|
if (this.fsw._handleError(error)) {
|
|
19176
19118
|
ready();
|
|
19177
|
-
return
|
|
19119
|
+
return path33;
|
|
19178
19120
|
}
|
|
19179
19121
|
}
|
|
19180
19122
|
}
|
|
@@ -19206,35 +19148,35 @@ function createPattern(matcher) {
|
|
|
19206
19148
|
if (matcher.path === string)
|
|
19207
19149
|
return true;
|
|
19208
19150
|
if (matcher.recursive) {
|
|
19209
|
-
const
|
|
19210
|
-
if (!
|
|
19151
|
+
const relative14 = sp2.relative(matcher.path, string);
|
|
19152
|
+
if (!relative14) {
|
|
19211
19153
|
return false;
|
|
19212
19154
|
}
|
|
19213
|
-
return !
|
|
19155
|
+
return !relative14.startsWith("..") && !sp2.isAbsolute(relative14);
|
|
19214
19156
|
}
|
|
19215
19157
|
return false;
|
|
19216
19158
|
};
|
|
19217
19159
|
}
|
|
19218
19160
|
return () => false;
|
|
19219
19161
|
}
|
|
19220
|
-
function normalizePath3(
|
|
19221
|
-
if (typeof
|
|
19162
|
+
function normalizePath3(path33) {
|
|
19163
|
+
if (typeof path33 !== "string")
|
|
19222
19164
|
throw new Error("string expected");
|
|
19223
|
-
|
|
19224
|
-
|
|
19165
|
+
path33 = sp2.normalize(path33);
|
|
19166
|
+
path33 = path33.replace(/\\/g, "/");
|
|
19225
19167
|
let prepend = false;
|
|
19226
|
-
if (
|
|
19168
|
+
if (path33.startsWith("//"))
|
|
19227
19169
|
prepend = true;
|
|
19228
|
-
|
|
19170
|
+
path33 = path33.replace(DOUBLE_SLASH_RE, "/");
|
|
19229
19171
|
if (prepend)
|
|
19230
|
-
|
|
19231
|
-
return
|
|
19172
|
+
path33 = "/" + path33;
|
|
19173
|
+
return path33;
|
|
19232
19174
|
}
|
|
19233
19175
|
function matchPatterns(patterns, testString, stats) {
|
|
19234
|
-
const
|
|
19176
|
+
const path33 = normalizePath3(testString);
|
|
19235
19177
|
for (let index = 0; index < patterns.length; index++) {
|
|
19236
19178
|
const pattern = patterns[index];
|
|
19237
|
-
if (pattern(
|
|
19179
|
+
if (pattern(path33, stats)) {
|
|
19238
19180
|
return true;
|
|
19239
19181
|
}
|
|
19240
19182
|
}
|
|
@@ -19272,19 +19214,19 @@ var toUnix = (string) => {
|
|
|
19272
19214
|
}
|
|
19273
19215
|
return str;
|
|
19274
19216
|
};
|
|
19275
|
-
var normalizePathToUnix = (
|
|
19276
|
-
var normalizeIgnored = (cwd = "") => (
|
|
19277
|
-
if (typeof
|
|
19278
|
-
return normalizePathToUnix(sp2.isAbsolute(
|
|
19217
|
+
var normalizePathToUnix = (path33) => toUnix(sp2.normalize(toUnix(path33)));
|
|
19218
|
+
var normalizeIgnored = (cwd = "") => (path33) => {
|
|
19219
|
+
if (typeof path33 === "string") {
|
|
19220
|
+
return normalizePathToUnix(sp2.isAbsolute(path33) ? path33 : sp2.join(cwd, path33));
|
|
19279
19221
|
} else {
|
|
19280
|
-
return
|
|
19222
|
+
return path33;
|
|
19281
19223
|
}
|
|
19282
19224
|
};
|
|
19283
|
-
var getAbsolutePath = (
|
|
19284
|
-
if (sp2.isAbsolute(
|
|
19285
|
-
return
|
|
19225
|
+
var getAbsolutePath = (path33, cwd) => {
|
|
19226
|
+
if (sp2.isAbsolute(path33)) {
|
|
19227
|
+
return path33;
|
|
19286
19228
|
}
|
|
19287
|
-
return sp2.join(cwd,
|
|
19229
|
+
return sp2.join(cwd, path33);
|
|
19288
19230
|
};
|
|
19289
19231
|
var EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
|
|
19290
19232
|
var DirEntry = class {
|
|
@@ -19349,10 +19291,10 @@ var WatchHelper = class {
|
|
|
19349
19291
|
dirParts;
|
|
19350
19292
|
followSymlinks;
|
|
19351
19293
|
statMethod;
|
|
19352
|
-
constructor(
|
|
19294
|
+
constructor(path33, follow, fsw) {
|
|
19353
19295
|
this.fsw = fsw;
|
|
19354
|
-
const watchPath =
|
|
19355
|
-
this.path =
|
|
19296
|
+
const watchPath = path33;
|
|
19297
|
+
this.path = path33 = path33.replace(REPLACER_RE, "");
|
|
19356
19298
|
this.watchPath = watchPath;
|
|
19357
19299
|
this.fullWatchPath = sp2.resolve(watchPath);
|
|
19358
19300
|
this.dirParts = [];
|
|
@@ -19492,20 +19434,20 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
19492
19434
|
this._closePromise = void 0;
|
|
19493
19435
|
let paths = unifyPaths(paths_);
|
|
19494
19436
|
if (cwd) {
|
|
19495
|
-
paths = paths.map((
|
|
19496
|
-
const absPath = getAbsolutePath(
|
|
19437
|
+
paths = paths.map((path33) => {
|
|
19438
|
+
const absPath = getAbsolutePath(path33, cwd);
|
|
19497
19439
|
return absPath;
|
|
19498
19440
|
});
|
|
19499
19441
|
}
|
|
19500
|
-
paths.forEach((
|
|
19501
|
-
this._removeIgnoredPath(
|
|
19442
|
+
paths.forEach((path33) => {
|
|
19443
|
+
this._removeIgnoredPath(path33);
|
|
19502
19444
|
});
|
|
19503
19445
|
this._userIgnored = void 0;
|
|
19504
19446
|
if (!this._readyCount)
|
|
19505
19447
|
this._readyCount = 0;
|
|
19506
19448
|
this._readyCount += paths.length;
|
|
19507
|
-
Promise.all(paths.map(async (
|
|
19508
|
-
const res = await this._nodeFsHandler._addToNodeFs(
|
|
19449
|
+
Promise.all(paths.map(async (path33) => {
|
|
19450
|
+
const res = await this._nodeFsHandler._addToNodeFs(path33, !_internal, void 0, 0, _origAdd);
|
|
19509
19451
|
if (res)
|
|
19510
19452
|
this._emitReady();
|
|
19511
19453
|
return res;
|
|
@@ -19527,17 +19469,17 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
19527
19469
|
return this;
|
|
19528
19470
|
const paths = unifyPaths(paths_);
|
|
19529
19471
|
const { cwd } = this.options;
|
|
19530
|
-
paths.forEach((
|
|
19531
|
-
if (!sp2.isAbsolute(
|
|
19472
|
+
paths.forEach((path33) => {
|
|
19473
|
+
if (!sp2.isAbsolute(path33) && !this._closers.has(path33)) {
|
|
19532
19474
|
if (cwd)
|
|
19533
|
-
|
|
19534
|
-
|
|
19475
|
+
path33 = sp2.join(cwd, path33);
|
|
19476
|
+
path33 = sp2.resolve(path33);
|
|
19535
19477
|
}
|
|
19536
|
-
this._closePath(
|
|
19537
|
-
this._addIgnoredPath(
|
|
19538
|
-
if (this._watched.has(
|
|
19478
|
+
this._closePath(path33);
|
|
19479
|
+
this._addIgnoredPath(path33);
|
|
19480
|
+
if (this._watched.has(path33)) {
|
|
19539
19481
|
this._addIgnoredPath({
|
|
19540
|
-
path:
|
|
19482
|
+
path: path33,
|
|
19541
19483
|
recursive: true
|
|
19542
19484
|
});
|
|
19543
19485
|
}
|
|
@@ -19601,38 +19543,38 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
19601
19543
|
* @param stats arguments to be passed with event
|
|
19602
19544
|
* @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
|
|
19603
19545
|
*/
|
|
19604
|
-
async _emit(event,
|
|
19546
|
+
async _emit(event, path33, stats) {
|
|
19605
19547
|
if (this.closed)
|
|
19606
19548
|
return;
|
|
19607
19549
|
const opts = this.options;
|
|
19608
19550
|
if (isWindows)
|
|
19609
|
-
|
|
19551
|
+
path33 = sp2.normalize(path33);
|
|
19610
19552
|
if (opts.cwd)
|
|
19611
|
-
|
|
19612
|
-
const args = [
|
|
19553
|
+
path33 = sp2.relative(opts.cwd, path33);
|
|
19554
|
+
const args = [path33];
|
|
19613
19555
|
if (stats != null)
|
|
19614
19556
|
args.push(stats);
|
|
19615
19557
|
const awf = opts.awaitWriteFinish;
|
|
19616
19558
|
let pw;
|
|
19617
|
-
if (awf && (pw = this._pendingWrites.get(
|
|
19559
|
+
if (awf && (pw = this._pendingWrites.get(path33))) {
|
|
19618
19560
|
pw.lastChange = /* @__PURE__ */ new Date();
|
|
19619
19561
|
return this;
|
|
19620
19562
|
}
|
|
19621
19563
|
if (opts.atomic) {
|
|
19622
19564
|
if (event === EVENTS.UNLINK) {
|
|
19623
|
-
this._pendingUnlinks.set(
|
|
19565
|
+
this._pendingUnlinks.set(path33, [event, ...args]);
|
|
19624
19566
|
setTimeout(() => {
|
|
19625
|
-
this._pendingUnlinks.forEach((entry,
|
|
19567
|
+
this._pendingUnlinks.forEach((entry, path34) => {
|
|
19626
19568
|
this.emit(...entry);
|
|
19627
19569
|
this.emit(EVENTS.ALL, ...entry);
|
|
19628
|
-
this._pendingUnlinks.delete(
|
|
19570
|
+
this._pendingUnlinks.delete(path34);
|
|
19629
19571
|
});
|
|
19630
19572
|
}, typeof opts.atomic === "number" ? opts.atomic : 100);
|
|
19631
19573
|
return this;
|
|
19632
19574
|
}
|
|
19633
|
-
if (event === EVENTS.ADD && this._pendingUnlinks.has(
|
|
19575
|
+
if (event === EVENTS.ADD && this._pendingUnlinks.has(path33)) {
|
|
19634
19576
|
event = EVENTS.CHANGE;
|
|
19635
|
-
this._pendingUnlinks.delete(
|
|
19577
|
+
this._pendingUnlinks.delete(path33);
|
|
19636
19578
|
}
|
|
19637
19579
|
}
|
|
19638
19580
|
if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
|
|
@@ -19650,16 +19592,16 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
19650
19592
|
this.emitWithAll(event, args);
|
|
19651
19593
|
}
|
|
19652
19594
|
};
|
|
19653
|
-
this._awaitWriteFinish(
|
|
19595
|
+
this._awaitWriteFinish(path33, awf.stabilityThreshold, event, awfEmit);
|
|
19654
19596
|
return this;
|
|
19655
19597
|
}
|
|
19656
19598
|
if (event === EVENTS.CHANGE) {
|
|
19657
|
-
const isThrottled = !this._throttle(EVENTS.CHANGE,
|
|
19599
|
+
const isThrottled = !this._throttle(EVENTS.CHANGE, path33, 50);
|
|
19658
19600
|
if (isThrottled)
|
|
19659
19601
|
return this;
|
|
19660
19602
|
}
|
|
19661
19603
|
if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
|
|
19662
|
-
const fullPath = opts.cwd ? sp2.join(opts.cwd,
|
|
19604
|
+
const fullPath = opts.cwd ? sp2.join(opts.cwd, path33) : path33;
|
|
19663
19605
|
let stats2;
|
|
19664
19606
|
try {
|
|
19665
19607
|
stats2 = await (0, import_promises3.stat)(fullPath);
|
|
@@ -19690,23 +19632,23 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
19690
19632
|
* @param timeout duration of time to suppress duplicate actions
|
|
19691
19633
|
* @returns tracking object or false if action should be suppressed
|
|
19692
19634
|
*/
|
|
19693
|
-
_throttle(actionType,
|
|
19635
|
+
_throttle(actionType, path33, timeout) {
|
|
19694
19636
|
if (!this._throttled.has(actionType)) {
|
|
19695
19637
|
this._throttled.set(actionType, /* @__PURE__ */ new Map());
|
|
19696
19638
|
}
|
|
19697
19639
|
const action = this._throttled.get(actionType);
|
|
19698
19640
|
if (!action)
|
|
19699
19641
|
throw new Error("invalid throttle");
|
|
19700
|
-
const actionPath = action.get(
|
|
19642
|
+
const actionPath = action.get(path33);
|
|
19701
19643
|
if (actionPath) {
|
|
19702
19644
|
actionPath.count++;
|
|
19703
19645
|
return false;
|
|
19704
19646
|
}
|
|
19705
19647
|
let timeoutObject;
|
|
19706
19648
|
const clear = () => {
|
|
19707
|
-
const item = action.get(
|
|
19649
|
+
const item = action.get(path33);
|
|
19708
19650
|
const count = item ? item.count : 0;
|
|
19709
|
-
action.delete(
|
|
19651
|
+
action.delete(path33);
|
|
19710
19652
|
clearTimeout(timeoutObject);
|
|
19711
19653
|
if (item)
|
|
19712
19654
|
clearTimeout(item.timeoutObject);
|
|
@@ -19714,7 +19656,7 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
19714
19656
|
};
|
|
19715
19657
|
timeoutObject = setTimeout(clear, timeout);
|
|
19716
19658
|
const thr = { timeoutObject, clear, count: 0 };
|
|
19717
|
-
action.set(
|
|
19659
|
+
action.set(path33, thr);
|
|
19718
19660
|
return thr;
|
|
19719
19661
|
}
|
|
19720
19662
|
_incrReadyCount() {
|
|
@@ -19728,44 +19670,44 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
19728
19670
|
* @param event
|
|
19729
19671
|
* @param awfEmit Callback to be called when ready for event to be emitted.
|
|
19730
19672
|
*/
|
|
19731
|
-
_awaitWriteFinish(
|
|
19673
|
+
_awaitWriteFinish(path33, threshold, event, awfEmit) {
|
|
19732
19674
|
const awf = this.options.awaitWriteFinish;
|
|
19733
19675
|
if (typeof awf !== "object")
|
|
19734
19676
|
return;
|
|
19735
19677
|
const pollInterval = awf.pollInterval;
|
|
19736
19678
|
let timeoutHandler;
|
|
19737
|
-
let fullPath =
|
|
19738
|
-
if (this.options.cwd && !sp2.isAbsolute(
|
|
19739
|
-
fullPath = sp2.join(this.options.cwd,
|
|
19679
|
+
let fullPath = path33;
|
|
19680
|
+
if (this.options.cwd && !sp2.isAbsolute(path33)) {
|
|
19681
|
+
fullPath = sp2.join(this.options.cwd, path33);
|
|
19740
19682
|
}
|
|
19741
19683
|
const now2 = /* @__PURE__ */ new Date();
|
|
19742
19684
|
const writes = this._pendingWrites;
|
|
19743
19685
|
function awaitWriteFinishFn(prevStat) {
|
|
19744
19686
|
(0, import_node_fs2.stat)(fullPath, (err, curStat) => {
|
|
19745
|
-
if (err || !writes.has(
|
|
19687
|
+
if (err || !writes.has(path33)) {
|
|
19746
19688
|
if (err && err.code !== "ENOENT")
|
|
19747
19689
|
awfEmit(err);
|
|
19748
19690
|
return;
|
|
19749
19691
|
}
|
|
19750
19692
|
const now3 = Number(/* @__PURE__ */ new Date());
|
|
19751
19693
|
if (prevStat && curStat.size !== prevStat.size) {
|
|
19752
|
-
writes.get(
|
|
19694
|
+
writes.get(path33).lastChange = now3;
|
|
19753
19695
|
}
|
|
19754
|
-
const pw = writes.get(
|
|
19696
|
+
const pw = writes.get(path33);
|
|
19755
19697
|
const df = now3 - pw.lastChange;
|
|
19756
19698
|
if (df >= threshold) {
|
|
19757
|
-
writes.delete(
|
|
19699
|
+
writes.delete(path33);
|
|
19758
19700
|
awfEmit(void 0, curStat);
|
|
19759
19701
|
} else {
|
|
19760
19702
|
timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
|
|
19761
19703
|
}
|
|
19762
19704
|
});
|
|
19763
19705
|
}
|
|
19764
|
-
if (!writes.has(
|
|
19765
|
-
writes.set(
|
|
19706
|
+
if (!writes.has(path33)) {
|
|
19707
|
+
writes.set(path33, {
|
|
19766
19708
|
lastChange: now2,
|
|
19767
19709
|
cancelWait: () => {
|
|
19768
|
-
writes.delete(
|
|
19710
|
+
writes.delete(path33);
|
|
19769
19711
|
clearTimeout(timeoutHandler);
|
|
19770
19712
|
return event;
|
|
19771
19713
|
}
|
|
@@ -19776,8 +19718,8 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
19776
19718
|
/**
|
|
19777
19719
|
* Determines whether user has asked to ignore this path.
|
|
19778
19720
|
*/
|
|
19779
|
-
_isIgnored(
|
|
19780
|
-
if (this.options.atomic && DOT_RE.test(
|
|
19721
|
+
_isIgnored(path33, stats) {
|
|
19722
|
+
if (this.options.atomic && DOT_RE.test(path33))
|
|
19781
19723
|
return true;
|
|
19782
19724
|
if (!this._userIgnored) {
|
|
19783
19725
|
const { cwd } = this.options;
|
|
@@ -19787,17 +19729,17 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
19787
19729
|
const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
|
|
19788
19730
|
this._userIgnored = anymatch(list, void 0);
|
|
19789
19731
|
}
|
|
19790
|
-
return this._userIgnored(
|
|
19732
|
+
return this._userIgnored(path33, stats);
|
|
19791
19733
|
}
|
|
19792
|
-
_isntIgnored(
|
|
19793
|
-
return !this._isIgnored(
|
|
19734
|
+
_isntIgnored(path33, stat5) {
|
|
19735
|
+
return !this._isIgnored(path33, stat5);
|
|
19794
19736
|
}
|
|
19795
19737
|
/**
|
|
19796
19738
|
* Provides a set of common helpers and properties relating to symlink handling.
|
|
19797
19739
|
* @param path file or directory pattern being watched
|
|
19798
19740
|
*/
|
|
19799
|
-
_getWatchHelpers(
|
|
19800
|
-
return new WatchHelper(
|
|
19741
|
+
_getWatchHelpers(path33) {
|
|
19742
|
+
return new WatchHelper(path33, this.options.followSymlinks, this);
|
|
19801
19743
|
}
|
|
19802
19744
|
// Directory helpers
|
|
19803
19745
|
// -----------------
|
|
@@ -19829,63 +19771,63 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
19829
19771
|
* @param item base path of item/directory
|
|
19830
19772
|
*/
|
|
19831
19773
|
_remove(directory, item, isDirectory) {
|
|
19832
|
-
const
|
|
19833
|
-
const fullPath = sp2.resolve(
|
|
19834
|
-
isDirectory = isDirectory != null ? isDirectory : this._watched.has(
|
|
19835
|
-
if (!this._throttle("remove",
|
|
19774
|
+
const path33 = sp2.join(directory, item);
|
|
19775
|
+
const fullPath = sp2.resolve(path33);
|
|
19776
|
+
isDirectory = isDirectory != null ? isDirectory : this._watched.has(path33) || this._watched.has(fullPath);
|
|
19777
|
+
if (!this._throttle("remove", path33, 100))
|
|
19836
19778
|
return;
|
|
19837
19779
|
if (!isDirectory && this._watched.size === 1) {
|
|
19838
19780
|
this.add(directory, item, true);
|
|
19839
19781
|
}
|
|
19840
|
-
const wp = this._getWatchedDir(
|
|
19782
|
+
const wp = this._getWatchedDir(path33);
|
|
19841
19783
|
const nestedDirectoryChildren = wp.getChildren();
|
|
19842
|
-
nestedDirectoryChildren.forEach((nested) => this._remove(
|
|
19784
|
+
nestedDirectoryChildren.forEach((nested) => this._remove(path33, nested));
|
|
19843
19785
|
const parent = this._getWatchedDir(directory);
|
|
19844
19786
|
const wasTracked = parent.has(item);
|
|
19845
19787
|
parent.remove(item);
|
|
19846
19788
|
if (this._symlinkPaths.has(fullPath)) {
|
|
19847
19789
|
this._symlinkPaths.delete(fullPath);
|
|
19848
19790
|
}
|
|
19849
|
-
let relPath =
|
|
19791
|
+
let relPath = path33;
|
|
19850
19792
|
if (this.options.cwd)
|
|
19851
|
-
relPath = sp2.relative(this.options.cwd,
|
|
19793
|
+
relPath = sp2.relative(this.options.cwd, path33);
|
|
19852
19794
|
if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
|
|
19853
19795
|
const event = this._pendingWrites.get(relPath).cancelWait();
|
|
19854
19796
|
if (event === EVENTS.ADD)
|
|
19855
19797
|
return;
|
|
19856
19798
|
}
|
|
19857
|
-
this._watched.delete(
|
|
19799
|
+
this._watched.delete(path33);
|
|
19858
19800
|
this._watched.delete(fullPath);
|
|
19859
19801
|
const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
|
|
19860
|
-
if (wasTracked && !this._isIgnored(
|
|
19861
|
-
this._emit(eventName,
|
|
19862
|
-
this._closePath(
|
|
19802
|
+
if (wasTracked && !this._isIgnored(path33))
|
|
19803
|
+
this._emit(eventName, path33);
|
|
19804
|
+
this._closePath(path33);
|
|
19863
19805
|
}
|
|
19864
19806
|
/**
|
|
19865
19807
|
* Closes all watchers for a path
|
|
19866
19808
|
*/
|
|
19867
|
-
_closePath(
|
|
19868
|
-
this._closeFile(
|
|
19869
|
-
const dir = sp2.dirname(
|
|
19870
|
-
this._getWatchedDir(dir).remove(sp2.basename(
|
|
19809
|
+
_closePath(path33) {
|
|
19810
|
+
this._closeFile(path33);
|
|
19811
|
+
const dir = sp2.dirname(path33);
|
|
19812
|
+
this._getWatchedDir(dir).remove(sp2.basename(path33));
|
|
19871
19813
|
}
|
|
19872
19814
|
/**
|
|
19873
19815
|
* Closes only file-specific watchers
|
|
19874
19816
|
*/
|
|
19875
|
-
_closeFile(
|
|
19876
|
-
const closers = this._closers.get(
|
|
19817
|
+
_closeFile(path33) {
|
|
19818
|
+
const closers = this._closers.get(path33);
|
|
19877
19819
|
if (!closers)
|
|
19878
19820
|
return;
|
|
19879
19821
|
closers.forEach((closer) => closer());
|
|
19880
|
-
this._closers.delete(
|
|
19822
|
+
this._closers.delete(path33);
|
|
19881
19823
|
}
|
|
19882
|
-
_addPathCloser(
|
|
19824
|
+
_addPathCloser(path33, closer) {
|
|
19883
19825
|
if (!closer)
|
|
19884
19826
|
return;
|
|
19885
|
-
let list = this._closers.get(
|
|
19827
|
+
let list = this._closers.get(path33);
|
|
19886
19828
|
if (!list) {
|
|
19887
19829
|
list = [];
|
|
19888
|
-
this._closers.set(
|
|
19830
|
+
this._closers.set(path33, list);
|
|
19889
19831
|
}
|
|
19890
19832
|
list.push(closer);
|
|
19891
19833
|
}
|
|
@@ -19915,12 +19857,291 @@ function watch(paths, options = {}) {
|
|
|
19915
19857
|
var chokidar_default = { watch, FSWatcher };
|
|
19916
19858
|
|
|
19917
19859
|
// src/watcher/file-watcher.ts
|
|
19860
|
+
var path28 = __toESM(require("path"), 1);
|
|
19861
|
+
|
|
19862
|
+
// src/watcher/native-recursive-watcher.ts
|
|
19863
|
+
var import_node_fs3 = require("fs");
|
|
19918
19864
|
var path26 = __toESM(require("path"), 1);
|
|
19865
|
+
var NativeRecursiveWatcher = class {
|
|
19866
|
+
constructor(root, onChange, options = {}) {
|
|
19867
|
+
this.root = root;
|
|
19868
|
+
this.onChange = onChange;
|
|
19869
|
+
this.watchFactory = options.watchFactory ?? this.defaultWatchFactory;
|
|
19870
|
+
this.onError = options.onError;
|
|
19871
|
+
}
|
|
19872
|
+
root;
|
|
19873
|
+
onChange;
|
|
19874
|
+
watcher = null;
|
|
19875
|
+
listenerToken = 0;
|
|
19876
|
+
watchFactory;
|
|
19877
|
+
onError;
|
|
19878
|
+
start() {
|
|
19879
|
+
if (this.watcher) return;
|
|
19880
|
+
const token = ++this.listenerToken;
|
|
19881
|
+
const listener = (_eventType, filename) => {
|
|
19882
|
+
if (this.watcher === null || this.listenerToken !== token) return;
|
|
19883
|
+
const absolutePath = this.toAbsolutePath(filename);
|
|
19884
|
+
const nextResult = this.onChange(absolutePath);
|
|
19885
|
+
if (nextResult instanceof Promise) {
|
|
19886
|
+
void nextResult.catch((error) => {
|
|
19887
|
+
console.error("[codebase-index] Error handling native watcher event:", error);
|
|
19888
|
+
});
|
|
19889
|
+
}
|
|
19890
|
+
};
|
|
19891
|
+
const watcher = this.watchFactory(this.root, listener, {
|
|
19892
|
+
persistent: true,
|
|
19893
|
+
recursive: true
|
|
19894
|
+
});
|
|
19895
|
+
watcher.on?.("error", (error) => {
|
|
19896
|
+
if (this.watcher === watcher && this.listenerToken === token) {
|
|
19897
|
+
this.onError?.(error);
|
|
19898
|
+
}
|
|
19899
|
+
});
|
|
19900
|
+
this.watcher = watcher;
|
|
19901
|
+
}
|
|
19902
|
+
async stop() {
|
|
19903
|
+
const watcher = this.watcher;
|
|
19904
|
+
this.watcher = null;
|
|
19905
|
+
this.listenerToken += 1;
|
|
19906
|
+
if (!watcher) return;
|
|
19907
|
+
await watcher.close();
|
|
19908
|
+
}
|
|
19909
|
+
toAbsolutePath(filename) {
|
|
19910
|
+
if (filename == null) return null;
|
|
19911
|
+
const normalizedFilename = typeof filename === "string" ? filename : filename.toString();
|
|
19912
|
+
const absolutePath = path26.resolve(this.root, normalizedFilename);
|
|
19913
|
+
const relativePath = path26.relative(this.root, absolutePath);
|
|
19914
|
+
const outsideRoot = relativePath === ".." || relativePath.startsWith(`..${path26.sep}`) || path26.isAbsolute(relativePath);
|
|
19915
|
+
return outsideRoot ? null : absolutePath;
|
|
19916
|
+
}
|
|
19917
|
+
defaultWatchFactory = (root, listener, options) => (0, import_node_fs3.watch)(root, options, listener);
|
|
19918
|
+
};
|
|
19919
|
+
|
|
19920
|
+
// src/watcher/snapshot.ts
|
|
19921
|
+
var fsPromises4 = __toESM(require("fs/promises"), 1);
|
|
19922
|
+
var path27 = __toESM(require("path"), 1);
|
|
19923
|
+
async function buildFileSnapshotScan(projectRoot, config, configPaths = []) {
|
|
19924
|
+
const normalizedProjectRoot = path27.resolve(projectRoot);
|
|
19925
|
+
const ignoreFilter = createIgnoreFilter(normalizedProjectRoot);
|
|
19926
|
+
const includePatterns = [...config.include, ...config.additionalInclude ?? []];
|
|
19927
|
+
const maxDepth = config.indexing?.maxDepth ?? -1;
|
|
19928
|
+
const snapshot = /* @__PURE__ */ new Map();
|
|
19929
|
+
const unreadablePrefixes = /* @__PURE__ */ new Set();
|
|
19930
|
+
const includeFile = async (filePath) => {
|
|
19931
|
+
const normalizedPath3 = path27.resolve(filePath);
|
|
19932
|
+
if (!shouldIncludeFile(normalizedPath3, normalizedProjectRoot, includePatterns, config.exclude, ignoreFilter)) return;
|
|
19933
|
+
const stat5 = await readStatIfFile(normalizedPath3, unreadablePrefixes);
|
|
19934
|
+
if (stat5) snapshot.set(normalizedPath3, { size: stat5.size, mtimeMs: stat5.mtimeMs });
|
|
19935
|
+
};
|
|
19936
|
+
const walk = async (directoryPath, depth) => {
|
|
19937
|
+
let entries;
|
|
19938
|
+
try {
|
|
19939
|
+
entries = await fsPromises4.readdir(directoryPath, { withFileTypes: true });
|
|
19940
|
+
} catch (error) {
|
|
19941
|
+
if (isMissingFsError(error)) return;
|
|
19942
|
+
if (isPermissionFsError(error)) {
|
|
19943
|
+
unreadablePrefixes.add(path27.resolve(directoryPath));
|
|
19944
|
+
return;
|
|
19945
|
+
}
|
|
19946
|
+
throw error;
|
|
19947
|
+
}
|
|
19948
|
+
for (const entry of entries) {
|
|
19949
|
+
const fullPath = path27.join(directoryPath, entry.name);
|
|
19950
|
+
const relativePath = path27.relative(normalizedProjectRoot, fullPath);
|
|
19951
|
+
if (entry.isDirectory()) {
|
|
19952
|
+
if (hasFilteredPathSegment(relativePath, path27.sep) || isRestrictedDirectory(relativePath, path27.sep)) continue;
|
|
19953
|
+
if (ignoreFilter.ignores(relativePath)) continue;
|
|
19954
|
+
if (maxDepth === -1 || depth < maxDepth) await walk(fullPath, depth + 1);
|
|
19955
|
+
} else if (entry.isFile()) {
|
|
19956
|
+
await includeFile(fullPath);
|
|
19957
|
+
}
|
|
19958
|
+
}
|
|
19959
|
+
};
|
|
19960
|
+
await walk(normalizedProjectRoot, 0);
|
|
19961
|
+
await includeExplicitConfigPaths(snapshot, unreadablePrefixes, configPaths);
|
|
19962
|
+
return { entries: snapshot, unreadablePrefixes };
|
|
19963
|
+
}
|
|
19964
|
+
async function buildFileSnapshotForPathScan(projectRoot, config, configPaths, targetPath) {
|
|
19965
|
+
const normalizedProjectRoot = path27.resolve(projectRoot);
|
|
19966
|
+
const normalizedTargetPath = path27.resolve(targetPath);
|
|
19967
|
+
if (!isWithinPath(normalizedProjectRoot, normalizedTargetPath)) {
|
|
19968
|
+
return { entries: /* @__PURE__ */ new Map(), unreadablePrefixes: /* @__PURE__ */ new Set() };
|
|
19969
|
+
}
|
|
19970
|
+
const ignoreFilter = createIgnoreFilter(normalizedProjectRoot);
|
|
19971
|
+
const includePatterns = [...config.include, ...config.additionalInclude ?? []];
|
|
19972
|
+
const maxDepth = config.indexing?.maxDepth ?? -1;
|
|
19973
|
+
const explicitConfigPaths = new Set(configPaths.map((configPath) => path27.resolve(configPath)));
|
|
19974
|
+
const snapshot = /* @__PURE__ */ new Map();
|
|
19975
|
+
const unreadablePrefixes = /* @__PURE__ */ new Set();
|
|
19976
|
+
const includeFile = async (filePath) => {
|
|
19977
|
+
const normalizedPath3 = path27.resolve(filePath);
|
|
19978
|
+
if (!explicitConfigPaths.has(normalizedPath3) && !shouldIncludeFile(
|
|
19979
|
+
normalizedPath3,
|
|
19980
|
+
normalizedProjectRoot,
|
|
19981
|
+
includePatterns,
|
|
19982
|
+
config.exclude,
|
|
19983
|
+
ignoreFilter
|
|
19984
|
+
)) return;
|
|
19985
|
+
const stat5 = await readStatIfFile(normalizedPath3, unreadablePrefixes);
|
|
19986
|
+
if (stat5) snapshot.set(normalizedPath3, { size: stat5.size, mtimeMs: stat5.mtimeMs });
|
|
19987
|
+
};
|
|
19988
|
+
const walk = async (directoryPath, depth) => {
|
|
19989
|
+
let entries;
|
|
19990
|
+
try {
|
|
19991
|
+
entries = await fsPromises4.readdir(directoryPath, { withFileTypes: true });
|
|
19992
|
+
} catch (error) {
|
|
19993
|
+
if (isMissingFsError(error)) return;
|
|
19994
|
+
if (isPermissionFsError(error)) {
|
|
19995
|
+
unreadablePrefixes.add(path27.resolve(directoryPath));
|
|
19996
|
+
return;
|
|
19997
|
+
}
|
|
19998
|
+
throw error;
|
|
19999
|
+
}
|
|
20000
|
+
for (const entry of entries) {
|
|
20001
|
+
const fullPath = path27.join(directoryPath, entry.name);
|
|
20002
|
+
const relativePath = path27.relative(normalizedProjectRoot, fullPath);
|
|
20003
|
+
if (entry.isDirectory()) {
|
|
20004
|
+
if (hasFilteredPathSegment(relativePath, path27.sep) || isRestrictedDirectory(relativePath, path27.sep)) continue;
|
|
20005
|
+
if (ignoreFilter.ignores(relativePath)) continue;
|
|
20006
|
+
if (maxDepth === -1 || depth < maxDepth) await walk(fullPath, depth + 1);
|
|
20007
|
+
} else if (entry.isFile()) {
|
|
20008
|
+
await includeFile(fullPath);
|
|
20009
|
+
}
|
|
20010
|
+
}
|
|
20011
|
+
};
|
|
20012
|
+
const targetStat = await readStatIfFile(normalizedTargetPath, unreadablePrefixes);
|
|
20013
|
+
if (targetStat) await includeFile(normalizedTargetPath);
|
|
20014
|
+
else await walk(normalizedTargetPath, 0);
|
|
20015
|
+
await includeExplicitConfigPathsInPath(snapshot, unreadablePrefixes, configPaths, normalizedTargetPath);
|
|
20016
|
+
return { entries: snapshot, unreadablePrefixes };
|
|
20017
|
+
}
|
|
20018
|
+
function completeFileSnapshot(previous, scan) {
|
|
20019
|
+
const completed = new Map(scan.entries);
|
|
20020
|
+
for (const unreadablePrefix of scan.unreadablePrefixes) {
|
|
20021
|
+
for (const [entryPath, entry] of previous) {
|
|
20022
|
+
if (isWithinPath(unreadablePrefix, entryPath) && !completed.has(entryPath)) completed.set(entryPath, entry);
|
|
20023
|
+
}
|
|
20024
|
+
}
|
|
20025
|
+
return completed;
|
|
20026
|
+
}
|
|
20027
|
+
async function includeExplicitConfigPaths(snapshot, unreadablePrefixes, configPaths) {
|
|
20028
|
+
for (const configPath of [...new Set(configPaths.map((value) => path27.resolve(value)))]) {
|
|
20029
|
+
if (snapshot.has(configPath)) continue;
|
|
20030
|
+
const stat5 = await readStatIfFile(configPath, unreadablePrefixes);
|
|
20031
|
+
if (stat5) snapshot.set(configPath, { size: stat5.size, mtimeMs: stat5.mtimeMs });
|
|
20032
|
+
}
|
|
20033
|
+
}
|
|
20034
|
+
async function includeExplicitConfigPathsInPath(snapshot, unreadablePrefixes, configPaths, targetPath) {
|
|
20035
|
+
await includeExplicitConfigPaths(
|
|
20036
|
+
snapshot,
|
|
20037
|
+
unreadablePrefixes,
|
|
20038
|
+
configPaths.filter((configPath) => isWithinPath(targetPath, path27.resolve(configPath)))
|
|
20039
|
+
);
|
|
20040
|
+
}
|
|
20041
|
+
function isWithinPath(parentPath, childPath) {
|
|
20042
|
+
const relativePath = path27.relative(parentPath, childPath);
|
|
20043
|
+
return relativePath === "" || !relativePath.startsWith(`..${path27.sep}`) && relativePath !== ".." && !path27.isAbsolute(relativePath);
|
|
20044
|
+
}
|
|
20045
|
+
async function readStatIfFile(filePath, unreadablePrefixes) {
|
|
20046
|
+
try {
|
|
20047
|
+
const stat5 = await fsPromises4.stat(filePath);
|
|
20048
|
+
return stat5.isFile() ? stat5 : null;
|
|
20049
|
+
} catch (error) {
|
|
20050
|
+
if (isMissingFsError(error)) return null;
|
|
20051
|
+
if (isPermissionFsError(error)) {
|
|
20052
|
+
unreadablePrefixes.add(path27.resolve(filePath));
|
|
20053
|
+
return null;
|
|
20054
|
+
}
|
|
20055
|
+
throw error;
|
|
20056
|
+
}
|
|
20057
|
+
}
|
|
20058
|
+
function isMissingFsError(error) {
|
|
20059
|
+
return error instanceof Error && ["ENOENT", "ENOTDIR"].includes(error.code ?? "");
|
|
20060
|
+
}
|
|
20061
|
+
function isPermissionFsError(error) {
|
|
20062
|
+
return error instanceof Error && ["EACCES", "EPERM"].includes(error.code ?? "");
|
|
20063
|
+
}
|
|
20064
|
+
var diffTypeOrder = { add: 0, change: 1, unlink: 2 };
|
|
20065
|
+
function diffFileSnapshots(previous, current, forcedChanges = /* @__PURE__ */ new Set()) {
|
|
20066
|
+
const changes = [];
|
|
20067
|
+
for (const [filePath, previousEntry] of previous) {
|
|
20068
|
+
const currentEntry = current.get(filePath);
|
|
20069
|
+
if (!currentEntry) changes.push({ type: "unlink", path: filePath });
|
|
20070
|
+
else if (forcedChanges.has(filePath) || currentEntry.size !== previousEntry.size || currentEntry.mtimeMs !== previousEntry.mtimeMs) {
|
|
20071
|
+
changes.push({ type: "change", path: filePath });
|
|
20072
|
+
}
|
|
20073
|
+
}
|
|
20074
|
+
for (const [filePath] of current) {
|
|
20075
|
+
if (!previous.has(filePath)) changes.push({ type: "add", path: filePath });
|
|
20076
|
+
}
|
|
20077
|
+
return changes.sort((left, right) => left.path.localeCompare(right.path) || diffTypeOrder[left.type] - diffTypeOrder[right.type]);
|
|
20078
|
+
}
|
|
20079
|
+
|
|
20080
|
+
// src/watcher/snapshot-reconciler.ts
|
|
20081
|
+
var FileSnapshotReconciler = class {
|
|
20082
|
+
constructor(projectRoot, config, configPaths) {
|
|
20083
|
+
this.projectRoot = projectRoot;
|
|
20084
|
+
this.config = config;
|
|
20085
|
+
this.configPaths = configPaths;
|
|
20086
|
+
}
|
|
20087
|
+
projectRoot;
|
|
20088
|
+
config;
|
|
20089
|
+
configPaths;
|
|
20090
|
+
snapshot = null;
|
|
20091
|
+
reconciliationTail = Promise.resolve();
|
|
20092
|
+
async initialize() {
|
|
20093
|
+
this.snapshot = (await buildFileSnapshotScan(this.projectRoot, this.config, this.configPaths)).entries;
|
|
20094
|
+
}
|
|
20095
|
+
async reconcile(invalidations = []) {
|
|
20096
|
+
if (this.snapshot === null) {
|
|
20097
|
+
throw new Error("FileSnapshotReconciler is not initialized. Call initialize() before reconcile().");
|
|
20098
|
+
}
|
|
20099
|
+
const reconciliation = this.reconciliationTail.then(async () => {
|
|
20100
|
+
const previousSnapshot = this.snapshot;
|
|
20101
|
+
if (previousSnapshot === null) {
|
|
20102
|
+
throw new Error("FileSnapshotReconciler is not initialized. Call initialize() before reconcile().");
|
|
20103
|
+
}
|
|
20104
|
+
const normalizedInvalidations = invalidations.map((invalidation) => typeof invalidation === "string" || invalidation === null ? { path: invalidation, forceChange: false } : { path: invalidation.path, forceChange: invalidation.forceChange === true });
|
|
20105
|
+
const scopedPaths = normalizedInvalidations.map((invalidation) => invalidation.path).filter((filePath) => filePath !== null);
|
|
20106
|
+
const scan = scopedPaths.length === 0 || scopedPaths.length !== normalizedInvalidations.length ? await buildFileSnapshotScan(this.projectRoot, this.config, this.configPaths) : await this.reconcilePaths(previousSnapshot, scopedPaths);
|
|
20107
|
+
const nextSnapshot = completeFileSnapshot(previousSnapshot, scan);
|
|
20108
|
+
const forcedChanges = new Set(normalizedInvalidations.filter((invalidation) => invalidation.path !== null && invalidation.forceChange).map((invalidation) => invalidation.path));
|
|
20109
|
+
const changes = diffFileSnapshots(previousSnapshot, nextSnapshot, forcedChanges);
|
|
20110
|
+
this.snapshot = nextSnapshot;
|
|
20111
|
+
return changes;
|
|
20112
|
+
});
|
|
20113
|
+
this.reconciliationTail = reconciliation.then(() => void 0, () => void 0);
|
|
20114
|
+
return reconciliation;
|
|
20115
|
+
}
|
|
20116
|
+
async reconcilePaths(previousSnapshot, invalidatedPaths) {
|
|
20117
|
+
const scopes = this.getScopes(invalidatedPaths);
|
|
20118
|
+
const entries = new Map(previousSnapshot);
|
|
20119
|
+
const unreadablePrefixes = /* @__PURE__ */ new Set();
|
|
20120
|
+
for (const scope of scopes) {
|
|
20121
|
+
for (const previousPath of entries.keys()) {
|
|
20122
|
+
if (isWithinPath(scope, previousPath)) entries.delete(previousPath);
|
|
20123
|
+
}
|
|
20124
|
+
const scopedScan = await buildFileSnapshotForPathScan(this.projectRoot, this.config, this.configPaths, scope);
|
|
20125
|
+
for (const [filePath, entry] of scopedScan.entries) entries.set(filePath, entry);
|
|
20126
|
+
for (const unreadablePrefix of scopedScan.unreadablePrefixes) unreadablePrefixes.add(unreadablePrefix);
|
|
20127
|
+
}
|
|
20128
|
+
return { entries, unreadablePrefixes };
|
|
20129
|
+
}
|
|
20130
|
+
getScopes(invalidatedPaths) {
|
|
20131
|
+
const uniquePaths = [...new Set(invalidatedPaths)].sort((left, right) => left.length - right.length);
|
|
20132
|
+
return uniquePaths.filter((candidate, index) => !uniquePaths.slice(0, index).some(
|
|
20133
|
+
(ancestor) => isWithinPath(ancestor, candidate)
|
|
20134
|
+
));
|
|
20135
|
+
}
|
|
20136
|
+
};
|
|
20137
|
+
|
|
20138
|
+
// src/watcher/file-watcher.ts
|
|
19919
20139
|
var FileWatcher = class {
|
|
19920
20140
|
watcher = null;
|
|
19921
20141
|
projectRoot;
|
|
19922
20142
|
config;
|
|
19923
20143
|
configPath;
|
|
20144
|
+
backend;
|
|
19924
20145
|
projectConfigPaths;
|
|
19925
20146
|
pendingChanges = /* @__PURE__ */ new Map();
|
|
19926
20147
|
debounceTimer = null;
|
|
@@ -19930,44 +20151,74 @@ var FileWatcher = class {
|
|
|
19930
20151
|
resolveReady = null;
|
|
19931
20152
|
pollingFallbackAttempted = false;
|
|
19932
20153
|
pendingClose = null;
|
|
20154
|
+
startupReadySignals = 1;
|
|
20155
|
+
nativeWatcher = null;
|
|
20156
|
+
nativeReconciler = null;
|
|
20157
|
+
nativeSetupGeneration = 0;
|
|
20158
|
+
nativeStarting = false;
|
|
20159
|
+
nativeInitializing = false;
|
|
20160
|
+
nativeReconcileTimer = null;
|
|
20161
|
+
nativeInvalidatedPaths = /* @__PURE__ */ new Map();
|
|
20162
|
+
configPathStates = /* @__PURE__ */ new Map();
|
|
19933
20163
|
constructor(projectRoot, config, host, options = {}) {
|
|
19934
20164
|
this.projectRoot = projectRoot;
|
|
19935
20165
|
this.config = config;
|
|
20166
|
+
this.backend = options.backend ?? "auto";
|
|
19936
20167
|
this.configPath = options.configPath;
|
|
19937
20168
|
this.projectConfigPaths = options.configPath ? [options.configPath] : getProjectConfigCandidatePaths(projectRoot, host);
|
|
19938
20169
|
}
|
|
19939
20170
|
start(handler) {
|
|
19940
|
-
if (this.watcher) {
|
|
20171
|
+
if (this.watcher || this.nativeWatcher || this.nativeStarting) {
|
|
19941
20172
|
return;
|
|
19942
20173
|
}
|
|
19943
20174
|
this.onChanges = handler;
|
|
19944
20175
|
this.pollingFallbackAttempted = false;
|
|
19945
20176
|
this.resetReady();
|
|
20177
|
+
if (this.shouldUseNativeWatcher()) {
|
|
20178
|
+
if (this.hasExternalConfigWatchTarget()) {
|
|
20179
|
+
this.setStartupReadySignals(2);
|
|
20180
|
+
this.startExternalConfigWatcher();
|
|
20181
|
+
}
|
|
20182
|
+
this.nativeStarting = true;
|
|
20183
|
+
void this.createNativeWatcher();
|
|
20184
|
+
return;
|
|
20185
|
+
}
|
|
19946
20186
|
this.createWatcher();
|
|
19947
20187
|
}
|
|
19948
20188
|
resetReady() {
|
|
19949
|
-
this.readyPromise = new Promise((
|
|
19950
|
-
this.resolveReady =
|
|
20189
|
+
this.readyPromise = new Promise((resolve20) => {
|
|
20190
|
+
this.resolveReady = resolve20;
|
|
19951
20191
|
});
|
|
20192
|
+
this.startupReadySignals = 1;
|
|
19952
20193
|
}
|
|
19953
|
-
|
|
19954
|
-
|
|
19955
|
-
|
|
19956
|
-
if (this.configPath) {
|
|
19957
|
-
watchTargets = [this.projectRoot, this.configPath];
|
|
19958
|
-
} else {
|
|
19959
|
-
const externalConfigTargets = this.projectConfigPaths.filter((projectConfigPath) => {
|
|
19960
|
-
const relativeConfigPath = path26.relative(this.projectRoot, projectConfigPath);
|
|
19961
|
-
return this.isOutsideProjectPath(relativeConfigPath);
|
|
19962
|
-
}).map((projectConfigPath) => (0, import_fs19.existsSync)(projectConfigPath) ? projectConfigPath : this.getNearestExistingDirectory(path26.dirname(projectConfigPath)));
|
|
19963
|
-
const uniqueExternalConfigTargets = [...new Set(externalConfigTargets)];
|
|
19964
|
-
if (uniqueExternalConfigTargets.length > 0) {
|
|
19965
|
-
watchTargets = [this.projectRoot, ...uniqueExternalConfigTargets];
|
|
19966
|
-
}
|
|
20194
|
+
setStartupReadySignals(expectedSignals) {
|
|
20195
|
+
if (!this.readyPromise) {
|
|
20196
|
+
return;
|
|
19967
20197
|
}
|
|
20198
|
+
this.startupReadySignals = Math.max(0, expectedSignals);
|
|
20199
|
+
}
|
|
20200
|
+
reportStartupReadySignal() {
|
|
20201
|
+
if (!this.readyPromise || !this.resolveReady) {
|
|
20202
|
+
return;
|
|
20203
|
+
}
|
|
20204
|
+
if (this.startupReadySignals <= 0) {
|
|
20205
|
+
return;
|
|
20206
|
+
}
|
|
20207
|
+
this.startupReadySignals -= 1;
|
|
20208
|
+
if (this.startupReadySignals !== 0) {
|
|
20209
|
+
return;
|
|
20210
|
+
}
|
|
20211
|
+
this.resolveReady();
|
|
20212
|
+
this.resolveReady = null;
|
|
20213
|
+
}
|
|
20214
|
+
createWatcher(watchTargets, usePolling = false, reportsStartupReady = true) {
|
|
20215
|
+
let reportedStartupReady = false;
|
|
20216
|
+
this.configPathStates = this.getConfigPathStates();
|
|
20217
|
+
const ignoreFilter = createIgnoreFilter(this.projectRoot);
|
|
20218
|
+
const resolvedWatchTargets = watchTargets ?? this.getFullChokidarWatchTargets();
|
|
19968
20219
|
const watcherOptions = {
|
|
19969
20220
|
ignored: (filePath) => {
|
|
19970
|
-
const relativePath =
|
|
20221
|
+
const relativePath = path28.relative(this.projectRoot, filePath);
|
|
19971
20222
|
if (!relativePath) return false;
|
|
19972
20223
|
if (this.isProjectConfigPathOrAncestor(relativePath)) {
|
|
19973
20224
|
return false;
|
|
@@ -19975,10 +20226,10 @@ var FileWatcher = class {
|
|
|
19975
20226
|
if (this.isOutsideProjectPath(relativePath)) {
|
|
19976
20227
|
return true;
|
|
19977
20228
|
}
|
|
19978
|
-
if (hasFilteredPathSegment(relativePath,
|
|
20229
|
+
if (hasFilteredPathSegment(relativePath, path28.sep)) {
|
|
19979
20230
|
return true;
|
|
19980
20231
|
}
|
|
19981
|
-
if (isRestrictedDirectory(relativePath,
|
|
20232
|
+
if (isRestrictedDirectory(relativePath, path28.sep)) {
|
|
19982
20233
|
return true;
|
|
19983
20234
|
}
|
|
19984
20235
|
if (ignoreFilter.ignores(relativePath)) {
|
|
@@ -20011,10 +20262,13 @@ var FileWatcher = class {
|
|
|
20011
20262
|
watcher = new FSWatcher(watcherOptions);
|
|
20012
20263
|
}
|
|
20013
20264
|
this.watcher = watcher;
|
|
20014
|
-
watcher.
|
|
20265
|
+
watcher.on("ready", () => {
|
|
20015
20266
|
if (this.watcher !== watcher) return;
|
|
20016
|
-
this.
|
|
20017
|
-
|
|
20267
|
+
this.reconcileConfigPathStates();
|
|
20268
|
+
if (reportsStartupReady) {
|
|
20269
|
+
this.reportStartupReadySignal();
|
|
20270
|
+
reportedStartupReady = true;
|
|
20271
|
+
}
|
|
20018
20272
|
});
|
|
20019
20273
|
watcher.on("error", (error) => {
|
|
20020
20274
|
const err = error instanceof Error ? error : null;
|
|
@@ -20028,10 +20282,13 @@ var FileWatcher = class {
|
|
|
20028
20282
|
console.error("[codebase-index] Failed to close exhausted file watcher:", closeError);
|
|
20029
20283
|
});
|
|
20030
20284
|
if (this.onChanges) {
|
|
20285
|
+
const replacementReportsStartupReady = reportsStartupReady || reportedStartupReady;
|
|
20031
20286
|
if (!this.resolveReady) {
|
|
20032
20287
|
this.resetReady();
|
|
20288
|
+
} else if (reportedStartupReady) {
|
|
20289
|
+
this.startupReadySignals += 1;
|
|
20033
20290
|
}
|
|
20034
|
-
this.createWatcher(true);
|
|
20291
|
+
this.createWatcher(resolvedWatchTargets, true, replacementReportsStartupReady);
|
|
20035
20292
|
} else {
|
|
20036
20293
|
this.watcher = null;
|
|
20037
20294
|
}
|
|
@@ -20042,13 +20299,166 @@ var FileWatcher = class {
|
|
|
20042
20299
|
watcher.on("add", (filePath) => this.handleChange(watcher, "add", filePath));
|
|
20043
20300
|
watcher.on("change", (filePath) => this.handleChange(watcher, "change", filePath));
|
|
20044
20301
|
watcher.on("unlink", (filePath) => this.handleChange(watcher, "unlink", filePath));
|
|
20045
|
-
watcher.add(
|
|
20302
|
+
watcher.add(resolvedWatchTargets);
|
|
20303
|
+
}
|
|
20304
|
+
shouldUseNativeWatcher() {
|
|
20305
|
+
if (this.backend === "chokidar") {
|
|
20306
|
+
return false;
|
|
20307
|
+
}
|
|
20308
|
+
return true;
|
|
20309
|
+
}
|
|
20310
|
+
getFullChokidarWatchTargets() {
|
|
20311
|
+
if (this.configPath) {
|
|
20312
|
+
return [this.projectRoot, this.configPath];
|
|
20313
|
+
}
|
|
20314
|
+
const externalConfigTargets = this.getExternalConfigWatchTargets();
|
|
20315
|
+
if (externalConfigTargets.length === 0) {
|
|
20316
|
+
return this.projectRoot;
|
|
20317
|
+
}
|
|
20318
|
+
return [this.projectRoot, ...externalConfigTargets];
|
|
20319
|
+
}
|
|
20320
|
+
getExternalConfigWatchTargets() {
|
|
20321
|
+
return [...new Set(
|
|
20322
|
+
this.projectConfigPaths.filter((projectConfigPath) => {
|
|
20323
|
+
const relativeConfigPath = path28.relative(this.projectRoot, projectConfigPath);
|
|
20324
|
+
return this.isOutsideProjectPath(relativeConfigPath);
|
|
20325
|
+
}).map((projectConfigPath) => {
|
|
20326
|
+
if ((0, import_fs19.existsSync)(projectConfigPath)) {
|
|
20327
|
+
return projectConfigPath;
|
|
20328
|
+
}
|
|
20329
|
+
return this.getNearestExistingDirectory(path28.dirname(projectConfigPath));
|
|
20330
|
+
})
|
|
20331
|
+
)];
|
|
20332
|
+
}
|
|
20333
|
+
hasExternalConfigWatchTarget() {
|
|
20334
|
+
return this.getExternalConfigWatchTargets().length > 0;
|
|
20335
|
+
}
|
|
20336
|
+
startExternalConfigWatcher(usePolling = false) {
|
|
20337
|
+
const externalTargets = this.getExternalConfigWatchTargets();
|
|
20338
|
+
if (externalTargets.length === 0) {
|
|
20339
|
+
return;
|
|
20340
|
+
}
|
|
20341
|
+
this.createWatcher(externalTargets, usePolling);
|
|
20342
|
+
}
|
|
20343
|
+
async createNativeWatcher() {
|
|
20344
|
+
const generation = ++this.nativeSetupGeneration;
|
|
20345
|
+
const reconciler = new FileSnapshotReconciler(this.projectRoot, this.config, this.projectConfigPaths);
|
|
20346
|
+
const watcher = new NativeRecursiveWatcher(
|
|
20347
|
+
this.projectRoot,
|
|
20348
|
+
(filePath) => this.scheduleNativeReconciliation(generation, filePath),
|
|
20349
|
+
{ onError: (error) => void this.fallbackFromNativeWatcher(generation, error) }
|
|
20350
|
+
);
|
|
20351
|
+
this.nativeReconciler = reconciler;
|
|
20352
|
+
this.nativeWatcher = watcher;
|
|
20353
|
+
this.nativeInitializing = true;
|
|
20354
|
+
try {
|
|
20355
|
+
watcher.start();
|
|
20356
|
+
if (!this.isCurrentNativeSetup(generation)) {
|
|
20357
|
+
await watcher.stop();
|
|
20358
|
+
return;
|
|
20359
|
+
}
|
|
20360
|
+
await reconciler.initialize();
|
|
20361
|
+
if (!this.isCurrentNativeSetup(generation) || this.nativeWatcher !== watcher) {
|
|
20362
|
+
await watcher.stop();
|
|
20363
|
+
return;
|
|
20364
|
+
}
|
|
20365
|
+
this.nativeStarting = false;
|
|
20366
|
+
this.nativeInitializing = false;
|
|
20367
|
+
await this.reconcileNativeWatcherWithPendingInvalidations(generation);
|
|
20368
|
+
this.reportStartupReadySignal();
|
|
20369
|
+
} catch (error) {
|
|
20370
|
+
if (!this.isCurrentNativeSetup(generation)) return;
|
|
20371
|
+
this.nativeInitializing = false;
|
|
20372
|
+
if (this.nativeWatcher) {
|
|
20373
|
+
await this.fallbackFromNativeWatcher(generation, error);
|
|
20374
|
+
return;
|
|
20375
|
+
}
|
|
20376
|
+
this.nativeStarting = false;
|
|
20377
|
+
const externalWatcher = this.watcher;
|
|
20378
|
+
this.watcher = null;
|
|
20379
|
+
this.nativeReconciler = null;
|
|
20380
|
+
await externalWatcher?.close();
|
|
20381
|
+
console.warn("[codebase-index] Native recursive watcher unavailable; using Chokidar fallback.", error);
|
|
20382
|
+
this.setStartupReadySignals(1);
|
|
20383
|
+
this.createWatcher();
|
|
20384
|
+
}
|
|
20385
|
+
}
|
|
20386
|
+
isCurrentNativeSetup(generation) {
|
|
20387
|
+
return this.nativeSetupGeneration === generation && this.onChanges !== null;
|
|
20388
|
+
}
|
|
20389
|
+
scheduleNativeReconciliation(generation, filePath) {
|
|
20390
|
+
if (!this.isCurrentNativeSetup(generation)) return;
|
|
20391
|
+
const requiresFullReconciliation = filePath === path28.join(this.projectRoot, ".gitignore");
|
|
20392
|
+
const invalidatedPath = requiresFullReconciliation ? null : filePath;
|
|
20393
|
+
this.nativeInvalidatedPaths.set(invalidatedPath, invalidatedPath !== null);
|
|
20394
|
+
if (this.nativeReconcileTimer) {
|
|
20395
|
+
clearTimeout(this.nativeReconcileTimer);
|
|
20396
|
+
}
|
|
20397
|
+
this.nativeReconcileTimer = setTimeout(() => {
|
|
20398
|
+
this.nativeReconcileTimer = null;
|
|
20399
|
+
void this.reconcileNativeWatcherFromQueue(generation);
|
|
20400
|
+
}, 100);
|
|
20401
|
+
}
|
|
20402
|
+
reconcileNativeWatcherFromQueue(generation) {
|
|
20403
|
+
if (!this.isCurrentNativeSetup(generation) || this.nativeInitializing) return;
|
|
20404
|
+
const invalidatedPaths = this.popNativeInvalidations();
|
|
20405
|
+
if (invalidatedPaths.length === 0) return;
|
|
20406
|
+
void this.reconcileNativeWatcher(generation, invalidatedPaths);
|
|
20407
|
+
}
|
|
20408
|
+
async reconcileNativeWatcher(generation, invalidatedPaths) {
|
|
20409
|
+
if (!this.isCurrentNativeSetup(generation) || !this.nativeReconciler) return;
|
|
20410
|
+
try {
|
|
20411
|
+
const reconciler = this.nativeReconciler;
|
|
20412
|
+
const changes = await reconciler.reconcile(invalidatedPaths);
|
|
20413
|
+
if (!this.isCurrentNativeSetup(generation) || this.nativeReconciler !== reconciler) return;
|
|
20414
|
+
this.recordChanges(changes);
|
|
20415
|
+
} catch (error) {
|
|
20416
|
+
await this.fallbackFromNativeWatcher(generation, error);
|
|
20417
|
+
}
|
|
20418
|
+
}
|
|
20419
|
+
async reconcileNativeWatcherWithPendingInvalidations(generation) {
|
|
20420
|
+
const invalidatedPaths = this.popNativeInvalidations();
|
|
20421
|
+
if (invalidatedPaths.length === 0) return;
|
|
20422
|
+
await this.reconcileNativeWatcher(generation, invalidatedPaths);
|
|
20423
|
+
}
|
|
20424
|
+
popNativeInvalidations() {
|
|
20425
|
+
if (this.nativeInvalidatedPaths.size === 0) return [];
|
|
20426
|
+
const invalidations = [...this.nativeInvalidatedPaths].map(([invalidatedPath, forceChange]) => ({
|
|
20427
|
+
path: invalidatedPath,
|
|
20428
|
+
forceChange
|
|
20429
|
+
}));
|
|
20430
|
+
this.nativeInvalidatedPaths.clear();
|
|
20431
|
+
return invalidations;
|
|
20432
|
+
}
|
|
20433
|
+
async fallbackFromNativeWatcher(generation, error) {
|
|
20434
|
+
if (!this.isCurrentNativeSetup(generation)) return;
|
|
20435
|
+
const watcher = this.nativeWatcher;
|
|
20436
|
+
const externalWatcher = this.watcher;
|
|
20437
|
+
this.nativeWatcher = null;
|
|
20438
|
+
this.watcher = null;
|
|
20439
|
+
this.nativeReconciler = null;
|
|
20440
|
+
this.nativeStarting = false;
|
|
20441
|
+
this.nativeInitializing = false;
|
|
20442
|
+
this.nativeSetupGeneration += 1;
|
|
20443
|
+
if (this.nativeReconcileTimer) {
|
|
20444
|
+
clearTimeout(this.nativeReconcileTimer);
|
|
20445
|
+
this.nativeReconcileTimer = null;
|
|
20446
|
+
}
|
|
20447
|
+
this.nativeInvalidatedPaths.clear();
|
|
20448
|
+
this.setStartupReadySignals(1);
|
|
20449
|
+
console.warn("[codebase-index] Native recursive watcher failed; using Chokidar fallback.", error);
|
|
20450
|
+
await watcher?.stop();
|
|
20451
|
+
await externalWatcher?.close();
|
|
20452
|
+
if (this.onChanges) {
|
|
20453
|
+
this.createWatcher();
|
|
20454
|
+
}
|
|
20046
20455
|
}
|
|
20047
20456
|
handleChange(watcher, type, filePath) {
|
|
20048
20457
|
if (this.watcher !== watcher) {
|
|
20049
20458
|
return;
|
|
20050
20459
|
}
|
|
20051
20460
|
if (this.isProjectConfigPath(filePath)) {
|
|
20461
|
+
this.updateConfigPathState(filePath);
|
|
20052
20462
|
this.pendingChanges.set(filePath, type);
|
|
20053
20463
|
this.scheduleFlush();
|
|
20054
20464
|
return;
|
|
@@ -20063,27 +20473,33 @@ var FileWatcher = class {
|
|
|
20063
20473
|
)) {
|
|
20064
20474
|
return;
|
|
20065
20475
|
}
|
|
20066
|
-
this.
|
|
20476
|
+
this.recordChanges([{ path: filePath, type }]);
|
|
20477
|
+
}
|
|
20478
|
+
recordChanges(changes) {
|
|
20479
|
+
if (changes.length === 0) return;
|
|
20480
|
+
for (const change of changes) {
|
|
20481
|
+
this.pendingChanges.set(change.path, change.type);
|
|
20482
|
+
}
|
|
20067
20483
|
this.scheduleFlush();
|
|
20068
20484
|
}
|
|
20069
20485
|
isProjectConfigPath(filePath) {
|
|
20070
|
-
const relativePath =
|
|
20071
|
-
const normalizedRelativePath =
|
|
20486
|
+
const relativePath = path28.relative(this.projectRoot, filePath);
|
|
20487
|
+
const normalizedRelativePath = path28.normalize(relativePath);
|
|
20072
20488
|
return this.getProjectConfigRelativePaths().some((configPath) => configPath === normalizedRelativePath);
|
|
20073
20489
|
}
|
|
20074
20490
|
isProjectConfigPathOrAncestor(relativePath) {
|
|
20075
|
-
const normalizedRelativePath =
|
|
20491
|
+
const normalizedRelativePath = path28.normalize(relativePath);
|
|
20076
20492
|
return this.getProjectConfigRelativePaths().some(
|
|
20077
|
-
(configPath) => configPath === normalizedRelativePath || configPath.startsWith(`${normalizedRelativePath}${
|
|
20493
|
+
(configPath) => configPath === normalizedRelativePath || configPath.startsWith(`${normalizedRelativePath}${path28.sep}`)
|
|
20078
20494
|
);
|
|
20079
20495
|
}
|
|
20080
20496
|
isOutsideProjectPath(relativePath) {
|
|
20081
|
-
return relativePath === ".." || relativePath.startsWith(`..${
|
|
20497
|
+
return relativePath === ".." || relativePath.startsWith(`..${path28.sep}`) || path28.isAbsolute(relativePath);
|
|
20082
20498
|
}
|
|
20083
20499
|
getNearestExistingDirectory(directoryPath) {
|
|
20084
20500
|
let candidate = directoryPath;
|
|
20085
20501
|
while (!(0, import_fs19.existsSync)(candidate)) {
|
|
20086
|
-
const parent =
|
|
20502
|
+
const parent = path28.dirname(candidate);
|
|
20087
20503
|
if (parent === candidate) break;
|
|
20088
20504
|
candidate = parent;
|
|
20089
20505
|
}
|
|
@@ -20091,9 +20507,51 @@ var FileWatcher = class {
|
|
|
20091
20507
|
}
|
|
20092
20508
|
getProjectConfigRelativePaths() {
|
|
20093
20509
|
return this.projectConfigPaths.map(
|
|
20094
|
-
(configPath) =>
|
|
20510
|
+
(configPath) => path28.normalize(path28.relative(this.projectRoot, configPath))
|
|
20095
20511
|
);
|
|
20096
20512
|
}
|
|
20513
|
+
getConfigPathStates() {
|
|
20514
|
+
const states = /* @__PURE__ */ new Map();
|
|
20515
|
+
for (const configPath of this.projectConfigPaths) {
|
|
20516
|
+
const state = this.getConfigPathState(configPath);
|
|
20517
|
+
if (state) states.set(configPath, state);
|
|
20518
|
+
}
|
|
20519
|
+
return states;
|
|
20520
|
+
}
|
|
20521
|
+
getConfigPathState(configPath) {
|
|
20522
|
+
try {
|
|
20523
|
+
const stats = (0, import_fs19.statSync)(configPath);
|
|
20524
|
+
return stats.isFile() ? { mtimeMs: stats.mtimeMs, size: stats.size } : void 0;
|
|
20525
|
+
} catch (error) {
|
|
20526
|
+
void error;
|
|
20527
|
+
return void 0;
|
|
20528
|
+
}
|
|
20529
|
+
}
|
|
20530
|
+
updateConfigPathState(configPath) {
|
|
20531
|
+
const state = this.getConfigPathState(configPath);
|
|
20532
|
+
if (state) {
|
|
20533
|
+
this.configPathStates.set(configPath, state);
|
|
20534
|
+
} else {
|
|
20535
|
+
this.configPathStates.delete(configPath);
|
|
20536
|
+
}
|
|
20537
|
+
}
|
|
20538
|
+
reconcileConfigPathStates() {
|
|
20539
|
+
const nextStates = this.getConfigPathStates();
|
|
20540
|
+
const changes = [];
|
|
20541
|
+
for (const configPath of this.projectConfigPaths) {
|
|
20542
|
+
const previous = this.configPathStates.get(configPath);
|
|
20543
|
+
const next = nextStates.get(configPath);
|
|
20544
|
+
if (!previous && next) {
|
|
20545
|
+
changes.push({ path: configPath, type: "add" });
|
|
20546
|
+
} else if (previous && !next) {
|
|
20547
|
+
changes.push({ path: configPath, type: "unlink" });
|
|
20548
|
+
} else if (previous && next && (previous.size !== next.size || previous.mtimeMs !== next.mtimeMs)) {
|
|
20549
|
+
changes.push({ path: configPath, type: "change" });
|
|
20550
|
+
}
|
|
20551
|
+
}
|
|
20552
|
+
this.configPathStates = nextStates;
|
|
20553
|
+
this.recordChanges(changes);
|
|
20554
|
+
}
|
|
20097
20555
|
scheduleFlush() {
|
|
20098
20556
|
if (this.debounceTimer) {
|
|
20099
20557
|
clearTimeout(this.debounceTimer);
|
|
@@ -20107,7 +20565,7 @@ var FileWatcher = class {
|
|
|
20107
20565
|
return;
|
|
20108
20566
|
}
|
|
20109
20567
|
const changes = Array.from(this.pendingChanges.entries()).map(
|
|
20110
|
-
([
|
|
20568
|
+
([path33, type]) => ({ path: path33, type })
|
|
20111
20569
|
);
|
|
20112
20570
|
this.pendingChanges.clear();
|
|
20113
20571
|
try {
|
|
@@ -20121,20 +20579,31 @@ var FileWatcher = class {
|
|
|
20121
20579
|
clearTimeout(this.debounceTimer);
|
|
20122
20580
|
this.debounceTimer = null;
|
|
20123
20581
|
}
|
|
20582
|
+
if (this.nativeReconcileTimer) {
|
|
20583
|
+
clearTimeout(this.nativeReconcileTimer);
|
|
20584
|
+
this.nativeReconcileTimer = null;
|
|
20585
|
+
}
|
|
20586
|
+
this.nativeInvalidatedPaths.clear();
|
|
20124
20587
|
const watcher = this.watcher;
|
|
20588
|
+
const nativeWatcher = this.nativeWatcher;
|
|
20125
20589
|
const pendingClose = this.pendingClose;
|
|
20126
20590
|
const resolveReady = this.resolveReady;
|
|
20127
20591
|
this.watcher = null;
|
|
20592
|
+
this.nativeWatcher = null;
|
|
20593
|
+
this.nativeReconciler = null;
|
|
20594
|
+
this.nativeStarting = false;
|
|
20595
|
+
this.nativeInitializing = false;
|
|
20596
|
+
this.nativeSetupGeneration += 1;
|
|
20128
20597
|
this.pendingClose = null;
|
|
20129
20598
|
this.resolveReady = null;
|
|
20130
20599
|
this.readyPromise = null;
|
|
20131
20600
|
this.pendingChanges.clear();
|
|
20132
20601
|
this.onChanges = null;
|
|
20133
|
-
await Promise.all([watcher?.close(), pendingClose]);
|
|
20602
|
+
await Promise.all([watcher?.close(), nativeWatcher?.stop(), pendingClose]);
|
|
20134
20603
|
resolveReady?.();
|
|
20135
20604
|
}
|
|
20136
20605
|
isRunning() {
|
|
20137
|
-
return this.watcher !== null;
|
|
20606
|
+
return this.watcher !== null || this.nativeWatcher !== null || this.nativeStarting;
|
|
20138
20607
|
}
|
|
20139
20608
|
async waitUntilReady() {
|
|
20140
20609
|
await (this.readyPromise ?? Promise.resolve());
|
|
@@ -20142,7 +20611,7 @@ var FileWatcher = class {
|
|
|
20142
20611
|
};
|
|
20143
20612
|
|
|
20144
20613
|
// src/watcher/git-head-watcher.ts
|
|
20145
|
-
var
|
|
20614
|
+
var path29 = __toESM(require("path"), 1);
|
|
20146
20615
|
var GitHeadWatcher = class {
|
|
20147
20616
|
watcher = null;
|
|
20148
20617
|
projectRoot;
|
|
@@ -20164,13 +20633,13 @@ var GitHeadWatcher = class {
|
|
|
20164
20633
|
this.readyPromise = Promise.resolve();
|
|
20165
20634
|
return;
|
|
20166
20635
|
}
|
|
20167
|
-
this.readyPromise = new Promise((
|
|
20168
|
-
this.resolveReady =
|
|
20636
|
+
this.readyPromise = new Promise((resolve20) => {
|
|
20637
|
+
this.resolveReady = resolve20;
|
|
20169
20638
|
});
|
|
20170
20639
|
this.onBranchChange = handler;
|
|
20171
20640
|
this.currentBranch = getCurrentBranch(this.projectRoot);
|
|
20172
20641
|
const headPath = getHeadPath(this.projectRoot);
|
|
20173
|
-
const refsPath =
|
|
20642
|
+
const refsPath = path29.join(this.projectRoot, ".git", "refs", "heads");
|
|
20174
20643
|
this.watcher = chokidar_default.watch([headPath, refsPath], {
|
|
20175
20644
|
persistent: true,
|
|
20176
20645
|
ignoreInitial: true,
|
|
@@ -20306,7 +20775,7 @@ function getConfigPaths(projectRoot, host, options) {
|
|
|
20306
20775
|
|
|
20307
20776
|
// src/tools/visualize/activity.ts
|
|
20308
20777
|
var import_child_process5 = require("child_process");
|
|
20309
|
-
var
|
|
20778
|
+
var path30 = __toESM(require("path"), 1);
|
|
20310
20779
|
function attachRecentActivity(data, projectRoot) {
|
|
20311
20780
|
const activity = readGitActivity(projectRoot);
|
|
20312
20781
|
const changes = activity.size > 0 ? buildGitChanges(data, activity, projectRoot) : buildGraphChanges(data);
|
|
@@ -20468,7 +20937,7 @@ function normalizePath4(filePath) {
|
|
|
20468
20937
|
return filePath.replace(/\\/g, "/");
|
|
20469
20938
|
}
|
|
20470
20939
|
function toGitRelativePath(projectRoot, filePath) {
|
|
20471
|
-
const relativePath =
|
|
20940
|
+
const relativePath = path30.isAbsolute(filePath) ? path30.relative(projectRoot, filePath) : filePath;
|
|
20472
20941
|
return normalizePath4(relativePath);
|
|
20473
20942
|
}
|
|
20474
20943
|
|
|
@@ -20726,7 +21195,7 @@ render();
|
|
|
20726
21195
|
}
|
|
20727
21196
|
|
|
20728
21197
|
// src/tools/visualize/transform.ts
|
|
20729
|
-
var
|
|
21198
|
+
var path31 = __toESM(require("path"), 1);
|
|
20730
21199
|
|
|
20731
21200
|
// src/tools/visualize/modules.ts
|
|
20732
21201
|
var MAX_MODULES = 18;
|
|
@@ -20859,8 +21328,8 @@ function compactModules(prefixToNodes) {
|
|
|
20859
21328
|
function deriveModules(nodes) {
|
|
20860
21329
|
const initial = /* @__PURE__ */ new Map();
|
|
20861
21330
|
for (const node of nodes) {
|
|
20862
|
-
const
|
|
20863
|
-
const prefix = modulePrefixFromRelativePath(
|
|
21331
|
+
const relative14 = stripToProjectRelative(node.filePath);
|
|
21332
|
+
const prefix = modulePrefixFromRelativePath(relative14);
|
|
20864
21333
|
if (!initial.has(prefix)) initial.set(prefix, []);
|
|
20865
21334
|
initial.get(prefix)?.push(node);
|
|
20866
21335
|
}
|
|
@@ -20986,7 +21455,7 @@ function transformForVisualization(symbols, edges, options = {}) {
|
|
|
20986
21455
|
filePath: s.filePath,
|
|
20987
21456
|
kind: s.kind,
|
|
20988
21457
|
line: s.startLine,
|
|
20989
|
-
directory:
|
|
21458
|
+
directory: path31.dirname(s.filePath),
|
|
20990
21459
|
moduleId: "",
|
|
20991
21460
|
moduleLabel: ""
|
|
20992
21461
|
}));
|
|
@@ -21014,9 +21483,9 @@ function parseArgs(argv) {
|
|
|
21014
21483
|
let host = "opencode";
|
|
21015
21484
|
for (let i = 2; i < argv.length; i++) {
|
|
21016
21485
|
if (argv[i] === "--project" && argv[i + 1]) {
|
|
21017
|
-
project =
|
|
21486
|
+
project = path32.resolve(argv[++i]);
|
|
21018
21487
|
} else if (argv[i] === "--config" && argv[i + 1]) {
|
|
21019
|
-
config =
|
|
21488
|
+
config = path32.resolve(argv[++i]);
|
|
21020
21489
|
} else if (argv[i] === "--host" && argv[i + 1]) {
|
|
21021
21490
|
host = parseHostMode(argv[++i]);
|
|
21022
21491
|
} else if (argv[i] === "--host") {
|
|
@@ -21043,7 +21512,7 @@ function parseIndexArgs(argv, cwd) {
|
|
|
21043
21512
|
if (!arg.startsWith("--project=")) {
|
|
21044
21513
|
i += 1;
|
|
21045
21514
|
}
|
|
21046
|
-
project =
|
|
21515
|
+
project = path32.resolve(cwd, value);
|
|
21047
21516
|
continue;
|
|
21048
21517
|
}
|
|
21049
21518
|
if (arg === "--config" || arg.startsWith("--config=")) {
|
|
@@ -21054,7 +21523,7 @@ function parseIndexArgs(argv, cwd) {
|
|
|
21054
21523
|
if (!arg.startsWith("--config=")) {
|
|
21055
21524
|
i += 1;
|
|
21056
21525
|
}
|
|
21057
|
-
config =
|
|
21526
|
+
config = path32.resolve(cwd, value);
|
|
21058
21527
|
continue;
|
|
21059
21528
|
}
|
|
21060
21529
|
if (arg === "--host" || arg.startsWith("--host=")) {
|
|
@@ -21120,7 +21589,7 @@ function parseVisualizeArgs(argv, cwd) {
|
|
|
21120
21589
|
for (let i = 0; i < argv.length; i++) {
|
|
21121
21590
|
const arg = argv[i];
|
|
21122
21591
|
if (arg === "--project" && argv[i + 1]) {
|
|
21123
|
-
project =
|
|
21592
|
+
project = path32.resolve(argv[++i]);
|
|
21124
21593
|
} else if (arg === "--max" && argv[i + 1]) {
|
|
21125
21594
|
maxNodes = Number(argv[++i]);
|
|
21126
21595
|
} else if (arg.startsWith("--max=") || arg.startsWith("max=")) {
|
|
@@ -21157,7 +21626,7 @@ async function handleVisualizeCommand(argv, cwd) {
|
|
|
21157
21626
|
console.error("No connected symbols found. Retry with: npm run visualize -- orphans");
|
|
21158
21627
|
return 1;
|
|
21159
21628
|
}
|
|
21160
|
-
const outputPath =
|
|
21629
|
+
const outputPath = path32.join(os8.tmpdir(), `call-graph-${Date.now()}.html`);
|
|
21161
21630
|
(0, import_fs20.writeFileSync)(outputPath, generateVisualizationHtml(vizData), "utf-8");
|
|
21162
21631
|
console.log(`Temporal call graph visualization generated: ${outputPath}`);
|
|
21163
21632
|
console.log(`Nodes: ${vizData.nodes.length} | Edges: ${vizData.edges.length}`);
|
|
@@ -21189,8 +21658,60 @@ async function runMcpCli(argv) {
|
|
|
21189
21658
|
const config = parseConfig(rawConfig);
|
|
21190
21659
|
const server = createMcpServer(args.project, config, args.host);
|
|
21191
21660
|
const transport = new import_stdio.StdioServerTransport();
|
|
21192
|
-
await server.connect(transport);
|
|
21193
21661
|
let watcher = null;
|
|
21662
|
+
let shutdownPromise;
|
|
21663
|
+
const onServerClose = server.server.onclose;
|
|
21664
|
+
const shutdown = () => {
|
|
21665
|
+
if (shutdownPromise) return shutdownPromise;
|
|
21666
|
+
process.stdin.removeListener("end", requestShutdown);
|
|
21667
|
+
process.stdin.removeListener("close", requestShutdown);
|
|
21668
|
+
process.removeListener("SIGHUP", requestShutdown);
|
|
21669
|
+
process.removeListener("SIGINT", requestShutdown);
|
|
21670
|
+
process.removeListener("SIGTERM", requestShutdown);
|
|
21671
|
+
server.server.onclose = onServerClose;
|
|
21672
|
+
shutdownPromise = (async () => {
|
|
21673
|
+
let exitCode = 0;
|
|
21674
|
+
try {
|
|
21675
|
+
await watcher?.stop();
|
|
21676
|
+
} catch (error) {
|
|
21677
|
+
exitCode = 1;
|
|
21678
|
+
console.error("Failed to stop MCP file watcher cleanly:", error);
|
|
21679
|
+
}
|
|
21680
|
+
try {
|
|
21681
|
+
await stopAutoIndex(args.project, args.host);
|
|
21682
|
+
} catch (error) {
|
|
21683
|
+
exitCode = 1;
|
|
21684
|
+
console.error("Failed to stop automatic indexing cleanly:", error);
|
|
21685
|
+
}
|
|
21686
|
+
try {
|
|
21687
|
+
await server.close();
|
|
21688
|
+
} catch (error) {
|
|
21689
|
+
exitCode = 1;
|
|
21690
|
+
console.error("Failed to close MCP server cleanly:", error);
|
|
21691
|
+
}
|
|
21692
|
+
process.exit(exitCode);
|
|
21693
|
+
})();
|
|
21694
|
+
return shutdownPromise;
|
|
21695
|
+
};
|
|
21696
|
+
const requestShutdown = () => {
|
|
21697
|
+
void shutdown();
|
|
21698
|
+
};
|
|
21699
|
+
server.server.onclose = () => {
|
|
21700
|
+
try {
|
|
21701
|
+
onServerClose?.();
|
|
21702
|
+
} finally {
|
|
21703
|
+
requestShutdown();
|
|
21704
|
+
}
|
|
21705
|
+
};
|
|
21706
|
+
process.stdin.once("end", requestShutdown);
|
|
21707
|
+
process.stdin.once("close", requestShutdown);
|
|
21708
|
+
process.once("SIGINT", requestShutdown);
|
|
21709
|
+
if (process.platform !== "win32") {
|
|
21710
|
+
process.once("SIGHUP", requestShutdown);
|
|
21711
|
+
process.once("SIGTERM", requestShutdown);
|
|
21712
|
+
}
|
|
21713
|
+
await server.connect(transport);
|
|
21714
|
+
if (shutdownPromise) return;
|
|
21194
21715
|
const isHomeDir = isHomeDirectory(args.project);
|
|
21195
21716
|
const isValidProject = !isHomeDir && (!config.indexing.requireProjectMarker || hasProjectMarker(args.project));
|
|
21196
21717
|
if (config.indexing.watchFiles && isValidProject) {
|
|
@@ -21202,26 +21723,6 @@ async function runMcpCli(argv) {
|
|
|
21202
21723
|
args.config ? { configPath: args.config } : {}
|
|
21203
21724
|
);
|
|
21204
21725
|
}
|
|
21205
|
-
let shuttingDown = false;
|
|
21206
|
-
const shutdown = async () => {
|
|
21207
|
-
if (shuttingDown) return;
|
|
21208
|
-
shuttingDown = true;
|
|
21209
|
-
try {
|
|
21210
|
-
await watcher?.stop();
|
|
21211
|
-
await stopAutoIndex(args.project, args.host);
|
|
21212
|
-
await server.close();
|
|
21213
|
-
process.exit(0);
|
|
21214
|
-
} catch (error) {
|
|
21215
|
-
console.error("Failed to stop MCP server cleanly:", error);
|
|
21216
|
-
process.exit(1);
|
|
21217
|
-
}
|
|
21218
|
-
};
|
|
21219
|
-
process.on("SIGINT", () => {
|
|
21220
|
-
void shutdown();
|
|
21221
|
-
});
|
|
21222
|
-
process.on("SIGTERM", () => {
|
|
21223
|
-
void shutdown();
|
|
21224
|
-
});
|
|
21225
21726
|
}
|
|
21226
21727
|
function printIndexProgress(onProgress, title, metadata) {
|
|
21227
21728
|
const details = Object.entries(metadata).filter(([, value]) => value !== void 0 && value !== null).map(([key, value]) => `${key}=${isSensitiveKey(key) ? "[REDACTED]" : String(value)}`).join(" ");
|