opencode-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.js
CHANGED
|
@@ -491,7 +491,7 @@ var require_ignore = __commonJS({
|
|
|
491
491
|
// path matching.
|
|
492
492
|
// - check `string` either `MODE_IGNORE` or `MODE_CHECK_IGNORE`
|
|
493
493
|
// @returns {TestResult} true if a file is ignored
|
|
494
|
-
test(
|
|
494
|
+
test(path33, checkUnignored, mode) {
|
|
495
495
|
let ignored = false;
|
|
496
496
|
let unignored = false;
|
|
497
497
|
let matchedRule;
|
|
@@ -500,7 +500,7 @@ var require_ignore = __commonJS({
|
|
|
500
500
|
if (unignored === negative && ignored !== unignored || negative && !ignored && !unignored && !checkUnignored) {
|
|
501
501
|
return;
|
|
502
502
|
}
|
|
503
|
-
const matched = rule[mode].test(
|
|
503
|
+
const matched = rule[mode].test(path33);
|
|
504
504
|
if (!matched) {
|
|
505
505
|
return;
|
|
506
506
|
}
|
|
@@ -521,17 +521,17 @@ var require_ignore = __commonJS({
|
|
|
521
521
|
var throwError = (message, Ctor) => {
|
|
522
522
|
throw new Ctor(message);
|
|
523
523
|
};
|
|
524
|
-
var checkPath = (
|
|
525
|
-
if (!isString(
|
|
524
|
+
var checkPath = (path33, originalPath, doThrow) => {
|
|
525
|
+
if (!isString(path33)) {
|
|
526
526
|
return doThrow(
|
|
527
527
|
`path must be a string, but got \`${originalPath}\``,
|
|
528
528
|
TypeError
|
|
529
529
|
);
|
|
530
530
|
}
|
|
531
|
-
if (!
|
|
531
|
+
if (!path33) {
|
|
532
532
|
return doThrow(`path must not be empty`, TypeError);
|
|
533
533
|
}
|
|
534
|
-
if (checkPath.isNotRelative(
|
|
534
|
+
if (checkPath.isNotRelative(path33)) {
|
|
535
535
|
const r = "`path.relative()`d";
|
|
536
536
|
return doThrow(
|
|
537
537
|
`path should be a ${r} string, but got "${originalPath}"`,
|
|
@@ -540,7 +540,7 @@ var require_ignore = __commonJS({
|
|
|
540
540
|
}
|
|
541
541
|
return true;
|
|
542
542
|
};
|
|
543
|
-
var isNotRelative = (
|
|
543
|
+
var isNotRelative = (path33) => REGEX_TEST_INVALID_PATH.test(path33);
|
|
544
544
|
checkPath.isNotRelative = isNotRelative;
|
|
545
545
|
checkPath.convert = (p) => p;
|
|
546
546
|
var Ignore2 = class {
|
|
@@ -570,19 +570,19 @@ var require_ignore = __commonJS({
|
|
|
570
570
|
}
|
|
571
571
|
// @returns {TestResult}
|
|
572
572
|
_test(originalPath, cache, checkUnignored, slices) {
|
|
573
|
-
const
|
|
573
|
+
const path33 = originalPath && checkPath.convert(originalPath);
|
|
574
574
|
checkPath(
|
|
575
|
-
|
|
575
|
+
path33,
|
|
576
576
|
originalPath,
|
|
577
577
|
this._strictPathCheck ? throwError : RETURN_FALSE
|
|
578
578
|
);
|
|
579
|
-
return this._t(
|
|
579
|
+
return this._t(path33, cache, checkUnignored, slices);
|
|
580
580
|
}
|
|
581
|
-
checkIgnore(
|
|
582
|
-
if (!REGEX_TEST_TRAILING_SLASH.test(
|
|
583
|
-
return this.test(
|
|
581
|
+
checkIgnore(path33) {
|
|
582
|
+
if (!REGEX_TEST_TRAILING_SLASH.test(path33)) {
|
|
583
|
+
return this.test(path33);
|
|
584
584
|
}
|
|
585
|
-
const slices =
|
|
585
|
+
const slices = path33.split(SLASH2).filter(Boolean);
|
|
586
586
|
slices.pop();
|
|
587
587
|
if (slices.length) {
|
|
588
588
|
const parent = this._t(
|
|
@@ -595,18 +595,18 @@ var require_ignore = __commonJS({
|
|
|
595
595
|
return parent;
|
|
596
596
|
}
|
|
597
597
|
}
|
|
598
|
-
return this._rules.test(
|
|
598
|
+
return this._rules.test(path33, false, MODE_CHECK_IGNORE);
|
|
599
599
|
}
|
|
600
|
-
_t(
|
|
601
|
-
if (
|
|
602
|
-
return cache[
|
|
600
|
+
_t(path33, cache, checkUnignored, slices) {
|
|
601
|
+
if (path33 in cache) {
|
|
602
|
+
return cache[path33];
|
|
603
603
|
}
|
|
604
604
|
if (!slices) {
|
|
605
|
-
slices =
|
|
605
|
+
slices = path33.split(SLASH2).filter(Boolean);
|
|
606
606
|
}
|
|
607
607
|
slices.pop();
|
|
608
608
|
if (!slices.length) {
|
|
609
|
-
return cache[
|
|
609
|
+
return cache[path33] = this._rules.test(path33, checkUnignored, MODE_IGNORE);
|
|
610
610
|
}
|
|
611
611
|
const parent = this._t(
|
|
612
612
|
slices.join(SLASH2) + SLASH2,
|
|
@@ -614,29 +614,29 @@ var require_ignore = __commonJS({
|
|
|
614
614
|
checkUnignored,
|
|
615
615
|
slices
|
|
616
616
|
);
|
|
617
|
-
return cache[
|
|
617
|
+
return cache[path33] = parent.ignored ? parent : this._rules.test(path33, checkUnignored, MODE_IGNORE);
|
|
618
618
|
}
|
|
619
|
-
ignores(
|
|
620
|
-
return this._test(
|
|
619
|
+
ignores(path33) {
|
|
620
|
+
return this._test(path33, this._ignoreCache, false).ignored;
|
|
621
621
|
}
|
|
622
622
|
createFilter() {
|
|
623
|
-
return (
|
|
623
|
+
return (path33) => !this.ignores(path33);
|
|
624
624
|
}
|
|
625
625
|
filter(paths) {
|
|
626
626
|
return makeArray(paths).filter(this.createFilter());
|
|
627
627
|
}
|
|
628
628
|
// @returns {TestResult}
|
|
629
|
-
test(
|
|
630
|
-
return this._test(
|
|
629
|
+
test(path33) {
|
|
630
|
+
return this._test(path33, this._testCache, true);
|
|
631
631
|
}
|
|
632
632
|
};
|
|
633
633
|
var factory = (options) => new Ignore2(options);
|
|
634
|
-
var isPathValid = (
|
|
634
|
+
var isPathValid = (path33) => checkPath(path33 && checkPath.convert(path33), path33, RETURN_FALSE);
|
|
635
635
|
var setupWindows = () => {
|
|
636
636
|
const makePosix = (str) => /^\\\\\?\\/.test(str) || /["<>|\u0000-\u001F]+/u.test(str) ? str : str.replace(/\\/g, "/");
|
|
637
637
|
checkPath.convert = makePosix;
|
|
638
638
|
const REGEX_TEST_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i;
|
|
639
|
-
checkPath.isNotRelative = (
|
|
639
|
+
checkPath.isNotRelative = (path33) => REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path33) || isNotRelative(path33);
|
|
640
640
|
};
|
|
641
641
|
if (
|
|
642
642
|
// Detect `process` so that it can run in browsers.
|
|
@@ -655,7 +655,7 @@ var require_ignore = __commonJS({
|
|
|
655
655
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
656
656
|
import { realpathSync as realpathSync6, writeFileSync as writeFileSync6 } from "fs";
|
|
657
657
|
import * as os8 from "os";
|
|
658
|
-
import * as
|
|
658
|
+
import * as path32 from "path";
|
|
659
659
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
660
660
|
|
|
661
661
|
// src/config/constants.ts
|
|
@@ -1165,9 +1165,9 @@ import { mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
|
1165
1165
|
import * as path from "path";
|
|
1166
1166
|
|
|
1167
1167
|
// src/eval/report-formatters.ts
|
|
1168
|
-
function assertFiniteNumber(value,
|
|
1168
|
+
function assertFiniteNumber(value, path33) {
|
|
1169
1169
|
if (typeof value !== "number" || Number.isNaN(value) || !Number.isFinite(value)) {
|
|
1170
|
-
throw new Error(`${
|
|
1170
|
+
throw new Error(`${path33} must be a finite number`);
|
|
1171
1171
|
}
|
|
1172
1172
|
return value;
|
|
1173
1173
|
}
|
|
@@ -1439,7 +1439,7 @@ function pTimeout(promise, options) {
|
|
|
1439
1439
|
} = options;
|
|
1440
1440
|
let timer;
|
|
1441
1441
|
let abortHandler;
|
|
1442
|
-
const wrappedPromise = new Promise((
|
|
1442
|
+
const wrappedPromise = new Promise((resolve20, reject) => {
|
|
1443
1443
|
if (typeof milliseconds !== "number" || Math.sign(milliseconds) !== 1) {
|
|
1444
1444
|
throw new TypeError(`Expected \`milliseconds\` to be a positive number, got \`${milliseconds}\``);
|
|
1445
1445
|
}
|
|
@@ -1453,7 +1453,7 @@ function pTimeout(promise, options) {
|
|
|
1453
1453
|
};
|
|
1454
1454
|
signal.addEventListener("abort", abortHandler, { once: true });
|
|
1455
1455
|
}
|
|
1456
|
-
promise.then(
|
|
1456
|
+
promise.then(resolve20, reject);
|
|
1457
1457
|
if (milliseconds === Number.POSITIVE_INFINITY) {
|
|
1458
1458
|
return;
|
|
1459
1459
|
}
|
|
@@ -1461,7 +1461,7 @@ function pTimeout(promise, options) {
|
|
|
1461
1461
|
timer = customTimers.setTimeout.call(void 0, () => {
|
|
1462
1462
|
if (fallback) {
|
|
1463
1463
|
try {
|
|
1464
|
-
|
|
1464
|
+
resolve20(fallback());
|
|
1465
1465
|
} catch (error) {
|
|
1466
1466
|
reject(error);
|
|
1467
1467
|
}
|
|
@@ -1471,7 +1471,7 @@ function pTimeout(promise, options) {
|
|
|
1471
1471
|
promise.cancel();
|
|
1472
1472
|
}
|
|
1473
1473
|
if (message === false) {
|
|
1474
|
-
|
|
1474
|
+
resolve20();
|
|
1475
1475
|
} else if (message instanceof Error) {
|
|
1476
1476
|
reject(message);
|
|
1477
1477
|
} else {
|
|
@@ -1873,7 +1873,7 @@ var PQueue = class extends import_index.default {
|
|
|
1873
1873
|
// Assign unique ID if not provided
|
|
1874
1874
|
id: options.id ?? (this.#idAssigner++).toString()
|
|
1875
1875
|
};
|
|
1876
|
-
return new Promise((
|
|
1876
|
+
return new Promise((resolve20, reject) => {
|
|
1877
1877
|
const taskSymbol = /* @__PURE__ */ Symbol(`task-${options.id}`);
|
|
1878
1878
|
let cleanupQueueAbortHandler = () => void 0;
|
|
1879
1879
|
const run = async () => {
|
|
@@ -1913,7 +1913,7 @@ var PQueue = class extends import_index.default {
|
|
|
1913
1913
|
})]);
|
|
1914
1914
|
}
|
|
1915
1915
|
const result = await operation;
|
|
1916
|
-
|
|
1916
|
+
resolve20(result);
|
|
1917
1917
|
this.emit("completed", result);
|
|
1918
1918
|
} catch (error) {
|
|
1919
1919
|
reject(error);
|
|
@@ -2101,13 +2101,13 @@ var PQueue = class extends import_index.default {
|
|
|
2101
2101
|
});
|
|
2102
2102
|
}
|
|
2103
2103
|
async #onEvent(event, filter) {
|
|
2104
|
-
return new Promise((
|
|
2104
|
+
return new Promise((resolve20) => {
|
|
2105
2105
|
const listener = () => {
|
|
2106
2106
|
if (filter && !filter()) {
|
|
2107
2107
|
return;
|
|
2108
2108
|
}
|
|
2109
2109
|
this.off(event, listener);
|
|
2110
|
-
|
|
2110
|
+
resolve20();
|
|
2111
2111
|
};
|
|
2112
2112
|
this.on(event, listener);
|
|
2113
2113
|
});
|
|
@@ -2393,7 +2393,7 @@ async function onAttemptFailure({ error, attemptNumber, retriesConsumed, startTi
|
|
|
2393
2393
|
const finalDelay = Math.min(delayTime, remainingTime);
|
|
2394
2394
|
options.signal?.throwIfAborted();
|
|
2395
2395
|
if (finalDelay > 0) {
|
|
2396
|
-
await new Promise((
|
|
2396
|
+
await new Promise((resolve20, reject) => {
|
|
2397
2397
|
const onAbort = () => {
|
|
2398
2398
|
clearTimeout(timeoutToken);
|
|
2399
2399
|
options.signal?.removeEventListener("abort", onAbort);
|
|
@@ -2401,7 +2401,7 @@ async function onAttemptFailure({ error, attemptNumber, retriesConsumed, startTi
|
|
|
2401
2401
|
};
|
|
2402
2402
|
const timeoutToken = setTimeout(() => {
|
|
2403
2403
|
options.signal?.removeEventListener("abort", onAbort);
|
|
2404
|
-
|
|
2404
|
+
resolve20();
|
|
2405
2405
|
}, finalDelay);
|
|
2406
2406
|
if (options.unref) {
|
|
2407
2407
|
timeoutToken.unref?.();
|
|
@@ -3207,85 +3207,6 @@ function createEmbeddingProvider(configuredProviderInfo) {
|
|
|
3207
3207
|
}
|
|
3208
3208
|
}
|
|
3209
3209
|
|
|
3210
|
-
// src/rerank/index.ts
|
|
3211
|
-
function createReranker(config) {
|
|
3212
|
-
if (!config.enabled) {
|
|
3213
|
-
return new NoOpReranker();
|
|
3214
|
-
}
|
|
3215
|
-
return new SiliconFlowReranker(config);
|
|
3216
|
-
}
|
|
3217
|
-
var NoOpReranker = class {
|
|
3218
|
-
isAvailable() {
|
|
3219
|
-
return false;
|
|
3220
|
-
}
|
|
3221
|
-
async rerank(_query, documents, _topN) {
|
|
3222
|
-
return {
|
|
3223
|
-
results: documents.map((_, index) => ({ index, relevanceScore: 0 }))
|
|
3224
|
-
};
|
|
3225
|
-
}
|
|
3226
|
-
};
|
|
3227
|
-
var SiliconFlowReranker = class {
|
|
3228
|
-
config;
|
|
3229
|
-
constructor(config) {
|
|
3230
|
-
this.config = config;
|
|
3231
|
-
}
|
|
3232
|
-
isAvailable() {
|
|
3233
|
-
return this.config.enabled && !!this.config.baseUrl && !!this.config.model;
|
|
3234
|
-
}
|
|
3235
|
-
async rerank(query, documents, topN) {
|
|
3236
|
-
if (documents.length === 0) {
|
|
3237
|
-
return { results: [] };
|
|
3238
|
-
}
|
|
3239
|
-
const headers = {
|
|
3240
|
-
"Content-Type": "application/json"
|
|
3241
|
-
};
|
|
3242
|
-
if (this.config.apiKey) {
|
|
3243
|
-
headers["Authorization"] = `Bearer ${this.config.apiKey}`;
|
|
3244
|
-
}
|
|
3245
|
-
const baseUrl = this.config.baseUrl;
|
|
3246
|
-
if (!baseUrl) {
|
|
3247
|
-
throw new Error("Reranker baseUrl is required. Configure reranker.baseUrl in your codebase-index.json.");
|
|
3248
|
-
}
|
|
3249
|
-
const timeoutMs = this.config.timeoutMs ?? 3e4;
|
|
3250
|
-
const controller = new AbortController();
|
|
3251
|
-
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
3252
|
-
try {
|
|
3253
|
-
const response = await fetch(`${baseUrl}/rerank`, {
|
|
3254
|
-
method: "POST",
|
|
3255
|
-
headers,
|
|
3256
|
-
body: JSON.stringify({
|
|
3257
|
-
model: this.config.model,
|
|
3258
|
-
query,
|
|
3259
|
-
documents,
|
|
3260
|
-
top_n: topN ?? this.config.topN ?? 20,
|
|
3261
|
-
return_documents: false
|
|
3262
|
-
}),
|
|
3263
|
-
signal: controller.signal
|
|
3264
|
-
});
|
|
3265
|
-
clearTimeout(timeout);
|
|
3266
|
-
if (!response.ok) {
|
|
3267
|
-
const errorText = await response.text();
|
|
3268
|
-
throw new Error(`Rerank API error: ${response.status} - ${errorText}`);
|
|
3269
|
-
}
|
|
3270
|
-
const data = await response.json();
|
|
3271
|
-
return {
|
|
3272
|
-
results: data.results.map((r) => ({
|
|
3273
|
-
index: r.index,
|
|
3274
|
-
relevanceScore: r.relevance_score,
|
|
3275
|
-
document: r.document?.text
|
|
3276
|
-
})),
|
|
3277
|
-
tokensUsed: data.meta?.tokens?.input_tokens
|
|
3278
|
-
};
|
|
3279
|
-
} catch (error) {
|
|
3280
|
-
clearTimeout(timeout);
|
|
3281
|
-
if (error instanceof Error && error.name === "AbortError") {
|
|
3282
|
-
throw new Error(`Rerank API request timed out after ${timeoutMs}ms`);
|
|
3283
|
-
}
|
|
3284
|
-
throw error;
|
|
3285
|
-
}
|
|
3286
|
-
}
|
|
3287
|
-
};
|
|
3288
|
-
|
|
3289
3210
|
// src/utils/files.ts
|
|
3290
3211
|
var import_ignore = __toESM(require_ignore(), 1);
|
|
3291
3212
|
import { existsSync as existsSync2, readFileSync as readFileSync3, promises as fsPromises } from "fs";
|
|
@@ -3447,8 +3368,8 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
|
|
|
3447
3368
|
if (entry.isDirectory()) {
|
|
3448
3369
|
subdirs.push({ fullPath, relativePath });
|
|
3449
3370
|
} else if (entry.isFile()) {
|
|
3450
|
-
const
|
|
3451
|
-
if (
|
|
3371
|
+
const stat5 = await fsPromises.stat(fullPath);
|
|
3372
|
+
if (stat5.size > maxFileSize) {
|
|
3452
3373
|
skipped.push({ path: relativePath, reason: "too_large" });
|
|
3453
3374
|
continue;
|
|
3454
3375
|
}
|
|
@@ -3466,7 +3387,7 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
|
|
|
3466
3387
|
}
|
|
3467
3388
|
}
|
|
3468
3389
|
if (matched) {
|
|
3469
|
-
filesInDir.push({ path: fullPath, size:
|
|
3390
|
+
filesInDir.push({ path: fullPath, size: stat5.size });
|
|
3470
3391
|
}
|
|
3471
3392
|
}
|
|
3472
3393
|
}
|
|
@@ -3523,8 +3444,8 @@ async function collectFiles(projectRoot, includePatterns, excludePatterns, maxFi
|
|
|
3523
3444
|
}
|
|
3524
3445
|
for (const resolvedKbRoot of normalizedRoots) {
|
|
3525
3446
|
try {
|
|
3526
|
-
const
|
|
3527
|
-
if (!
|
|
3447
|
+
const stat5 = await fsPromises.stat(resolvedKbRoot);
|
|
3448
|
+
if (!stat5.isDirectory()) {
|
|
3528
3449
|
skipped.push({ path: resolvedKbRoot, reason: "excluded" });
|
|
3529
3450
|
continue;
|
|
3530
3451
|
}
|
|
@@ -4850,11 +4771,11 @@ function resolveGitDir(repoRoot) {
|
|
|
4850
4771
|
return null;
|
|
4851
4772
|
}
|
|
4852
4773
|
try {
|
|
4853
|
-
const
|
|
4854
|
-
if (
|
|
4774
|
+
const stat5 = statSync2(gitPath);
|
|
4775
|
+
if (stat5.isDirectory()) {
|
|
4855
4776
|
return gitPath;
|
|
4856
4777
|
}
|
|
4857
|
-
if (
|
|
4778
|
+
if (stat5.isFile()) {
|
|
4858
4779
|
const content = readFileSync5(gitPath, "utf-8").trim();
|
|
4859
4780
|
const match = content.match(/^gitdir:\s*(.+)$/);
|
|
4860
4781
|
if (match) {
|
|
@@ -5359,8 +5280,8 @@ async function isWorktreeRegistered(projectRoot, worktreePath) {
|
|
|
5359
5280
|
return false;
|
|
5360
5281
|
}
|
|
5361
5282
|
function isPathWithinRoot(filePath, rootPath) {
|
|
5362
|
-
const
|
|
5363
|
-
return
|
|
5283
|
+
const relative14 = path9.relative(path9.resolve(rootPath), path9.resolve(filePath));
|
|
5284
|
+
return relative14 === "" || !relative14.startsWith(`..${path9.sep}`) && relative14 !== ".." && !path9.isAbsolute(relative14);
|
|
5364
5285
|
}
|
|
5365
5286
|
async function pruneExactMissingWorktreeRegistration(projectRoot, worktreePath) {
|
|
5366
5287
|
if (await pathExists(worktreePath)) return false;
|
|
@@ -5918,11 +5839,11 @@ function normalizeFiles(rawFiles, projectRoot) {
|
|
|
5918
5839
|
for (const raw of rawFiles) {
|
|
5919
5840
|
if (raw.length === 0) continue;
|
|
5920
5841
|
const absolute = path11.resolve(root, raw);
|
|
5921
|
-
const
|
|
5922
|
-
if (path11.isAbsolute(raw) ||
|
|
5842
|
+
const relative14 = path11.relative(root, absolute);
|
|
5843
|
+
if (path11.isAbsolute(raw) || relative14 === ".." || relative14.startsWith(`..${path11.sep}`) || path11.isAbsolute(relative14)) {
|
|
5923
5844
|
throw new Error(`Changed file escapes the project root: ${JSON.stringify(raw)}`);
|
|
5924
5845
|
}
|
|
5925
|
-
const cleaned =
|
|
5846
|
+
const cleaned = relative14.startsWith(`.${path11.sep}`) ? relative14.slice(2) : relative14;
|
|
5926
5847
|
if (!seen.has(cleaned)) {
|
|
5927
5848
|
seen.add(cleaned);
|
|
5928
5849
|
result.push(cleaned);
|
|
@@ -6259,7 +6180,7 @@ function analyzeQueryIntent(query) {
|
|
|
6259
6180
|
}
|
|
6260
6181
|
function isTestPath(filePath) {
|
|
6261
6182
|
const normalized = normalizePath(filePath);
|
|
6262
|
-
return /(?:^|\/)(?:test|tests|__tests__|spec|specs)(?:\/|$)/u.test(normalized) ||
|
|
6183
|
+
return /(?:^|\/)(?:test|tests|__tests__|spec|specs)(?:\/|$)/u.test(normalized) || /(?:\.(?:test|spec)|_(?:test|spec))\.[^/]+$/u.test(normalized) || /(?:^|\/)(?:test|spec)_[^/]+\.[^/]+$/u.test(normalized);
|
|
6263
6184
|
}
|
|
6264
6185
|
function isFixturePath(filePath) {
|
|
6265
6186
|
const normalized = normalizePath(filePath);
|
|
@@ -6666,7 +6587,8 @@ function rankHybridResults(query, semanticResults, keywordResults, options) {
|
|
|
6666
6587
|
return cached;
|
|
6667
6588
|
}
|
|
6668
6589
|
}
|
|
6669
|
-
const
|
|
6590
|
+
const overfetchFactor = prioritizeSourcePaths ? 12 : 4;
|
|
6591
|
+
const overfetchLimit = Math.max(options.limit * overfetchFactor, options.limit);
|
|
6670
6592
|
const fused = options.fusionStrategy === "rrf" ? fuseResultsRrf(semanticResults, keywordResults, options.rrfK, overfetchLimit) : fuseResultsWeighted(semanticResults, keywordResults, options.hybridWeight, overfetchLimit);
|
|
6671
6593
|
const rerankPoolLimit = Math.max(overfetchLimit, options.rerankTopN * 3, options.limit * 6);
|
|
6672
6594
|
const rerankPool = fused.slice(0, rerankPoolLimit);
|
|
@@ -7052,6 +6974,29 @@ function extractPrimaryIdentifierQueryHint(query) {
|
|
|
7052
6974
|
const best = codeTerms.find((term) => term.length >= 6);
|
|
7053
6975
|
return best ?? null;
|
|
7054
6976
|
}
|
|
6977
|
+
function pathSegmentsForAffinityMatch(filePath) {
|
|
6978
|
+
const normalizedPath3 = normalizeRankingText(filePath).replace(/\\/g, "/");
|
|
6979
|
+
const segments = normalizedPath3.split("/").filter((segment) => segment.length > 0);
|
|
6980
|
+
if (segments.length === 0) {
|
|
6981
|
+
return [];
|
|
6982
|
+
}
|
|
6983
|
+
const basename8 = segments[segments.length - 1] ?? "";
|
|
6984
|
+
const basenameWithoutExt = basename8.replace(/\.[^/.]+$/u, "");
|
|
6985
|
+
const normalizedSegments = segments.map((segment) => segment.toLowerCase());
|
|
6986
|
+
return Array.from(/* @__PURE__ */ new Set([
|
|
6987
|
+
...normalizedSegments,
|
|
6988
|
+
basenameWithoutExt.toLowerCase()
|
|
6989
|
+
]));
|
|
6990
|
+
}
|
|
6991
|
+
function hasModuleAffinity(filePath, exactIdentifierVariants) {
|
|
6992
|
+
const haystack = pathSegmentsForAffinityMatch(filePath);
|
|
6993
|
+
return exactIdentifierVariants.some((variant) => {
|
|
6994
|
+
if (!variant || variant.length < 2) {
|
|
6995
|
+
return false;
|
|
6996
|
+
}
|
|
6997
|
+
return haystack.includes(variant);
|
|
6998
|
+
});
|
|
6999
|
+
}
|
|
7055
7000
|
var FILE_PATH_HINT_EXTENSIONS = [
|
|
7056
7001
|
"ts",
|
|
7057
7002
|
"tsx",
|
|
@@ -7127,10 +7072,13 @@ function buildDeterministicIdentifierPass(query, candidates, limit, prioritizeSo
|
|
|
7127
7072
|
).map((candidate) => {
|
|
7128
7073
|
const nameLower = (candidate.metadata.name ?? "").toLowerCase();
|
|
7129
7074
|
const pathLower = candidate.metadata.filePath.toLowerCase();
|
|
7130
|
-
|
|
7131
|
-
const
|
|
7075
|
+
const exactIdentifierVariants = primaryVariants.filter((value) => value.length >= 2);
|
|
7076
|
+
const exactMatch = exactIdentifierVariants.some(
|
|
7132
7077
|
(variant) => nameLower === variant || nameLower.replace(/[^a-z0-9]/g, "") === variant.replace(/[^a-z0-9]/g, "")
|
|
7133
7078
|
);
|
|
7079
|
+
let maxMatch = 0;
|
|
7080
|
+
const nameMatchesPrimary = exactMatch;
|
|
7081
|
+
const pathAffinity = exactMatch ? hasModuleAffinity(candidate.metadata.filePath, exactIdentifierVariants) : false;
|
|
7134
7082
|
const pathMatchesFileHint = filePathHint ? pathMatchesHint(candidate.metadata.filePath, filePathHint) : false;
|
|
7135
7083
|
for (const hint of hints) {
|
|
7136
7084
|
const variants = normalizeIdentifierVariants(hint);
|
|
@@ -7151,12 +7099,17 @@ function buildDeterministicIdentifierPass(query, candidates, limit, prioritizeSo
|
|
|
7151
7099
|
candidate,
|
|
7152
7100
|
maxMatch,
|
|
7153
7101
|
pathMatchesFileHint,
|
|
7154
|
-
nameMatchesPrimary
|
|
7102
|
+
nameMatchesPrimary,
|
|
7103
|
+
pathAffinity
|
|
7155
7104
|
};
|
|
7156
7105
|
}).filter((entry) => entry.maxMatch >= 0.7).sort((a, b) => {
|
|
7157
7106
|
const aAnchored = a.pathMatchesFileHint && a.nameMatchesPrimary ? 1 : 0;
|
|
7158
7107
|
const bAnchored = b.pathMatchesFileHint && b.nameMatchesPrimary ? 1 : 0;
|
|
7159
7108
|
if (aAnchored !== bAnchored) return bAnchored - aAnchored;
|
|
7109
|
+
if (a.nameMatchesPrimary !== b.nameMatchesPrimary) {
|
|
7110
|
+
return b.nameMatchesPrimary ? 1 : -1;
|
|
7111
|
+
}
|
|
7112
|
+
if (a.pathAffinity !== b.pathAffinity) return b.pathAffinity ? 1 : -1;
|
|
7160
7113
|
if (b.maxMatch !== a.maxMatch) return b.maxMatch - a.maxMatch;
|
|
7161
7114
|
if (b.candidate.score !== a.candidate.score) return b.candidate.score - a.candidate.score;
|
|
7162
7115
|
return a.candidate.id.localeCompare(b.candidate.id);
|
|
@@ -8547,7 +8500,6 @@ var Indexer = class _Indexer {
|
|
|
8547
8500
|
database = null;
|
|
8548
8501
|
provider = null;
|
|
8549
8502
|
configuredProviderInfo = null;
|
|
8550
|
-
reranker = null;
|
|
8551
8503
|
fileHashCache = /* @__PURE__ */ new Map();
|
|
8552
8504
|
fileHashCachePath = "";
|
|
8553
8505
|
failedBatchesPath = "";
|
|
@@ -8707,7 +8659,6 @@ var Indexer = class _Indexer {
|
|
|
8707
8659
|
this.database = null;
|
|
8708
8660
|
this.provider = null;
|
|
8709
8661
|
this.configuredProviderInfo = null;
|
|
8710
|
-
this.reranker = null;
|
|
8711
8662
|
this.indexCompatibility = null;
|
|
8712
8663
|
this.initializationMode = "none";
|
|
8713
8664
|
this.readIssues = [];
|
|
@@ -9437,7 +9388,7 @@ var Indexer = class _Indexer {
|
|
|
9437
9388
|
await options.queue.onSizeLessThan(Math.max(1, options.providerRateLimits.concurrency));
|
|
9438
9389
|
const task = options.queue.add(async () => {
|
|
9439
9390
|
if (options.rateLimitState.backoffMs > 0) {
|
|
9440
|
-
await new Promise((
|
|
9391
|
+
await new Promise((resolve20) => setTimeout(resolve20, options.rateLimitState.backoffMs));
|
|
9441
9392
|
}
|
|
9442
9393
|
try {
|
|
9443
9394
|
const embeddingResult = await pRetry(
|
|
@@ -10004,15 +9955,6 @@ var Indexer = class _Indexer {
|
|
|
10004
9955
|
rerankerEnabled: this.config.reranker?.enabled ?? false
|
|
10005
9956
|
});
|
|
10006
9957
|
this.provider = createEmbeddingProvider(this.configuredProviderInfo);
|
|
10007
|
-
if (this.config.reranker?.enabled) {
|
|
10008
|
-
this.reranker = createReranker(this.config.reranker);
|
|
10009
|
-
if (this.reranker.isAvailable()) {
|
|
10010
|
-
this.logger.info("Reranker initialized", {
|
|
10011
|
-
model: this.config.reranker.model,
|
|
10012
|
-
baseUrl: this.config.reranker.baseUrl
|
|
10013
|
-
});
|
|
10014
|
-
}
|
|
10015
|
-
}
|
|
10016
9958
|
const dimensions = this.configuredProviderInfo.modelInfo.dimensions;
|
|
10017
9959
|
const storePath = path15.join(this.indexPath, "vectors");
|
|
10018
9960
|
const vectorMetadataPath = `${storePath}.meta.json`;
|
|
@@ -11417,6 +11359,7 @@ var Indexer = class _Indexer {
|
|
|
11417
11359
|
const filterByBranch = options?.filterByBranch ?? true;
|
|
11418
11360
|
const sourceIntent = options?.definitionIntent === true || classifyQueryIntentRaw(query) === "source";
|
|
11419
11361
|
const identifierHints = extractIdentifierHints(query);
|
|
11362
|
+
const candidateLimit = maxResults * (sourceIntent ? 12 : 4);
|
|
11420
11363
|
this.logger.search("debug", "Starting search", {
|
|
11421
11364
|
query,
|
|
11422
11365
|
maxResults,
|
|
@@ -11453,7 +11396,7 @@ var Indexer = class _Indexer {
|
|
|
11453
11396
|
const semanticCandidates = embedding ? this.searchSemanticCandidates(
|
|
11454
11397
|
store,
|
|
11455
11398
|
embedding,
|
|
11456
|
-
|
|
11399
|
+
candidateLimit,
|
|
11457
11400
|
branchChunkIds,
|
|
11458
11401
|
shouldPrefilterByBranch
|
|
11459
11402
|
) : [];
|
|
@@ -11461,7 +11404,7 @@ var Indexer = class _Indexer {
|
|
|
11461
11404
|
const keywordStartTime = performance2.now();
|
|
11462
11405
|
const keywordCandidates = await this.keywordSearch(
|
|
11463
11406
|
query,
|
|
11464
|
-
|
|
11407
|
+
candidateLimit,
|
|
11465
11408
|
store,
|
|
11466
11409
|
invertedIndex,
|
|
11467
11410
|
branchChunkIds,
|
|
@@ -12219,9 +12162,9 @@ var Indexer = class _Indexer {
|
|
|
12219
12162
|
this.requireReadableComponents(readIssues, "database");
|
|
12220
12163
|
let shortest = [];
|
|
12221
12164
|
for (const branchKey of this.getBranchCatalogKeys()) {
|
|
12222
|
-
const
|
|
12223
|
-
if (
|
|
12224
|
-
shortest =
|
|
12165
|
+
const path33 = database.findShortestPath(fromName, toName, branchKey, maxDepth);
|
|
12166
|
+
if (path33.length > 0 && (shortest.length === 0 || path33.length < shortest.length)) {
|
|
12167
|
+
shortest = path33;
|
|
12225
12168
|
}
|
|
12226
12169
|
}
|
|
12227
12170
|
return shortest.map((hop) => this.resolveFilePathRecord(hop));
|
|
@@ -12269,13 +12212,13 @@ var Indexer = class _Indexer {
|
|
|
12269
12212
|
}
|
|
12270
12213
|
}
|
|
12271
12214
|
if (!found) continue;
|
|
12272
|
-
const
|
|
12215
|
+
const path33 = [];
|
|
12273
12216
|
let currentSymbolId = toSymbolId;
|
|
12274
12217
|
while (true) {
|
|
12275
12218
|
const symbol = symbolsById.get(currentSymbolId);
|
|
12276
12219
|
if (!symbol) break;
|
|
12277
12220
|
const parent = parentBySymbolId.get(currentSymbolId);
|
|
12278
|
-
|
|
12221
|
+
path33.push({
|
|
12279
12222
|
symbolId: symbol.id,
|
|
12280
12223
|
symbolName: symbol.name,
|
|
12281
12224
|
filePath: symbol.filePath,
|
|
@@ -12285,9 +12228,9 @@ var Indexer = class _Indexer {
|
|
|
12285
12228
|
if (!parent) break;
|
|
12286
12229
|
currentSymbolId = parent.parentId;
|
|
12287
12230
|
}
|
|
12288
|
-
|
|
12289
|
-
if (
|
|
12290
|
-
shortest =
|
|
12231
|
+
path33.reverse();
|
|
12232
|
+
if (path33.length > 0 && (shortest.length === 0 || path33.length < shortest.length)) {
|
|
12233
|
+
shortest = path33;
|
|
12291
12234
|
}
|
|
12292
12235
|
}
|
|
12293
12236
|
return shortest.map((hop) => this.resolveFilePathRecord(hop));
|
|
@@ -12623,7 +12566,6 @@ var Indexer = class _Indexer {
|
|
|
12623
12566
|
this.store = null;
|
|
12624
12567
|
this.invertedIndex = null;
|
|
12625
12568
|
this.provider = null;
|
|
12626
|
-
this.reranker = null;
|
|
12627
12569
|
this.configuredProviderInfo = null;
|
|
12628
12570
|
this.indexCompatibility = null;
|
|
12629
12571
|
this.initializationMode = "none";
|
|
@@ -12937,8 +12879,8 @@ function formatExactSearchHandoff(results) {
|
|
|
12937
12879
|
}
|
|
12938
12880
|
function formatContextEvidence(result, index) {
|
|
12939
12881
|
const symbol = result.name ? ` ${JSON.stringify(compactEvidenceValue(result.name, 80))}` : "";
|
|
12940
|
-
const
|
|
12941
|
-
return `[${index}] ${result.chunkType}${symbol} in ${
|
|
12882
|
+
const path33 = compactEvidenceValue(result.filePath, 120);
|
|
12883
|
+
return `[${index}] ${result.chunkType}${symbol} in ${path33}:${result.startLine}-${result.endLine} (score ${result.score.toFixed(2)})`;
|
|
12942
12884
|
}
|
|
12943
12885
|
function formatContextPack(heading, selected, candidateCount, duplicateCount, limitOmittedCount, budgetOmittedCount, includeExactSearchHandoff) {
|
|
12944
12886
|
const lines = selected.map((result, index) => formatContextEvidence(result, index + 1));
|
|
@@ -13592,7 +13534,7 @@ function getErrorMessage4(error) {
|
|
|
13592
13534
|
return error instanceof Error ? error.message : String(error);
|
|
13593
13535
|
}
|
|
13594
13536
|
function runCommand(file, args, options) {
|
|
13595
|
-
return new Promise((
|
|
13537
|
+
return new Promise((resolve20, reject) => {
|
|
13596
13538
|
childProcess.execFile(
|
|
13597
13539
|
file,
|
|
13598
13540
|
args,
|
|
@@ -13602,7 +13544,7 @@ function runCommand(file, args, options) {
|
|
|
13602
13544
|
reject(error);
|
|
13603
13545
|
return;
|
|
13604
13546
|
}
|
|
13605
|
-
|
|
13547
|
+
resolve20(stdout);
|
|
13606
13548
|
}
|
|
13607
13549
|
);
|
|
13608
13550
|
});
|
|
@@ -13747,10 +13689,10 @@ function safeFailureMessage(error) {
|
|
|
13747
13689
|
}
|
|
13748
13690
|
function cancellableDelay(delayMs, signal) {
|
|
13749
13691
|
if (signal.aborted) return Promise.reject(new AutoIndexCancelledError());
|
|
13750
|
-
return new Promise((
|
|
13692
|
+
return new Promise((resolve20, reject) => {
|
|
13751
13693
|
const timer = setTimeout(() => {
|
|
13752
13694
|
signal.removeEventListener("abort", onAbort);
|
|
13753
|
-
|
|
13695
|
+
resolve20();
|
|
13754
13696
|
}, delayMs);
|
|
13755
13697
|
timer.unref?.();
|
|
13756
13698
|
const onAbort = () => {
|
|
@@ -13762,15 +13704,15 @@ function cancellableDelay(delayMs, signal) {
|
|
|
13762
13704
|
}
|
|
13763
13705
|
function withTimeout(promise, timeoutMs) {
|
|
13764
13706
|
if (timeoutMs <= 0) return Promise.resolve(void 0);
|
|
13765
|
-
return new Promise((
|
|
13766
|
-
const timer = setTimeout(() =>
|
|
13707
|
+
return new Promise((resolve20) => {
|
|
13708
|
+
const timer = setTimeout(() => resolve20(void 0), timeoutMs);
|
|
13767
13709
|
timer.unref?.();
|
|
13768
13710
|
void promise.then((value) => {
|
|
13769
13711
|
clearTimeout(timer);
|
|
13770
|
-
|
|
13712
|
+
resolve20(value);
|
|
13771
13713
|
}, () => {
|
|
13772
13714
|
clearTimeout(timer);
|
|
13773
|
-
|
|
13715
|
+
resolve20(void 0);
|
|
13774
13716
|
});
|
|
13775
13717
|
});
|
|
13776
13718
|
}
|
|
@@ -14152,17 +14094,17 @@ var AutoIndexCoordinator = class {
|
|
|
14152
14094
|
}
|
|
14153
14095
|
}
|
|
14154
14096
|
waitForBatteryRetry(delayMs) {
|
|
14155
|
-
return new Promise((
|
|
14097
|
+
return new Promise((resolve20) => {
|
|
14156
14098
|
const timer = setTimeout(() => {
|
|
14157
14099
|
if (this.batteryRetryTimer === timer) {
|
|
14158
14100
|
this.batteryRetryTimer = null;
|
|
14159
14101
|
this.resolveBatteryRetry = null;
|
|
14160
14102
|
}
|
|
14161
|
-
|
|
14103
|
+
resolve20();
|
|
14162
14104
|
}, delayMs);
|
|
14163
14105
|
timer.unref?.();
|
|
14164
14106
|
this.batteryRetryTimer = timer;
|
|
14165
|
-
this.resolveBatteryRetry =
|
|
14107
|
+
this.resolveBatteryRetry = resolve20;
|
|
14166
14108
|
});
|
|
14167
14109
|
}
|
|
14168
14110
|
cancelBatteryRetry() {
|
|
@@ -14170,9 +14112,9 @@ var AutoIndexCoordinator = class {
|
|
|
14170
14112
|
clearTimeout(this.batteryRetryTimer);
|
|
14171
14113
|
this.batteryRetryTimer = null;
|
|
14172
14114
|
}
|
|
14173
|
-
const
|
|
14115
|
+
const resolve20 = this.resolveBatteryRetry;
|
|
14174
14116
|
this.resolveBatteryRetry = null;
|
|
14175
|
-
|
|
14117
|
+
resolve20?.();
|
|
14176
14118
|
}
|
|
14177
14119
|
finishBatteryCheck(batteryCheck) {
|
|
14178
14120
|
if (this.batteryCheck !== batteryCheck) return;
|
|
@@ -14847,12 +14789,12 @@ async function getCallGraphPath(projectRoot, host, from, to, maxDepth, fromFileP
|
|
|
14847
14789
|
if (fromResolution.status !== "resolved" || toResolution.status !== "resolved") {
|
|
14848
14790
|
return { from: fromResolution, to: toResolution, path: [] };
|
|
14849
14791
|
}
|
|
14850
|
-
const
|
|
14792
|
+
const path33 = await indexer.findCallPathBySymbolIds(
|
|
14851
14793
|
fromResolution.symbolId,
|
|
14852
14794
|
toResolution.symbolId,
|
|
14853
14795
|
maxDepth
|
|
14854
14796
|
);
|
|
14855
|
-
return { from: fromResolution, to: toResolution, path:
|
|
14797
|
+
return { from: fromResolution, to: toResolution, path: path33 };
|
|
14856
14798
|
}
|
|
14857
14799
|
async function runIndexCodebase(projectRoot, host, args, onProgress) {
|
|
14858
14800
|
const root = getProjectRoot(projectRoot, host);
|
|
@@ -15477,7 +15419,7 @@ async function resolveCodebaseContextUnmeasured(projectRoot, host, input) {
|
|
|
15477
15419
|
const directory = input.directory ?? void 0;
|
|
15478
15420
|
const tokenBudget = input.tokenBudget ?? void 0;
|
|
15479
15421
|
if (from && to) {
|
|
15480
|
-
const
|
|
15422
|
+
const path33 = await getCallGraphPath(
|
|
15481
15423
|
projectRoot,
|
|
15482
15424
|
host,
|
|
15483
15425
|
from,
|
|
@@ -15486,25 +15428,25 @@ async function resolveCodebaseContextUnmeasured(projectRoot, host, input) {
|
|
|
15486
15428
|
fromFilePath,
|
|
15487
15429
|
toFilePath
|
|
15488
15430
|
);
|
|
15489
|
-
const pathText = formatCallGraphPathResult(
|
|
15490
|
-
if (
|
|
15431
|
+
const pathText = formatCallGraphPathResult(path33);
|
|
15432
|
+
if (path33.path.length > 0) {
|
|
15491
15433
|
const fitted2 = fitTextToContextBudget(
|
|
15492
15434
|
pathText,
|
|
15493
15435
|
tokenBudget
|
|
15494
15436
|
);
|
|
15495
15437
|
return {
|
|
15496
15438
|
text: fitted2.text,
|
|
15497
|
-
details: fittedDetails("path", fitted2,
|
|
15439
|
+
details: fittedDetails("path", fitted2, path33.path.length)
|
|
15498
15440
|
};
|
|
15499
15441
|
}
|
|
15500
|
-
if (
|
|
15442
|
+
if (path33.from.status !== "resolved" || path33.to.status !== "resolved") {
|
|
15501
15443
|
const fitted2 = fitTextToContextBudget(pathText, tokenBudget);
|
|
15502
15444
|
return {
|
|
15503
15445
|
text: fitted2.text,
|
|
15504
15446
|
details: fittedDetails("path", fitted2, 0)
|
|
15505
15447
|
};
|
|
15506
15448
|
}
|
|
15507
|
-
const resolvedFrom =
|
|
15449
|
+
const resolvedFrom = path33.from;
|
|
15508
15450
|
const { callers } = await getCallGraphData(projectRoot, host, {
|
|
15509
15451
|
name: to,
|
|
15510
15452
|
direction: "callers",
|
|
@@ -15981,9 +15923,9 @@ function getRelevantEvidence(query) {
|
|
|
15981
15923
|
});
|
|
15982
15924
|
}
|
|
15983
15925
|
if (query.expected.acceptableFiles) {
|
|
15984
|
-
for (const
|
|
15926
|
+
for (const path33 of query.expected.acceptableFiles) {
|
|
15985
15927
|
legacyEvidence.push({
|
|
15986
|
-
path:
|
|
15928
|
+
path: path33,
|
|
15987
15929
|
...query.expected.symbol !== void 0 ? { symbol: query.expected.symbol } : {},
|
|
15988
15930
|
relevance: 1
|
|
15989
15931
|
});
|
|
@@ -16480,68 +16422,68 @@ function isStringArray4(value) {
|
|
|
16480
16422
|
function isNonEmptyString(value) {
|
|
16481
16423
|
return typeof value === "string" && value.trim().length > 0;
|
|
16482
16424
|
}
|
|
16483
|
-
function asPositiveNumber(value,
|
|
16425
|
+
function asPositiveNumber(value, path33) {
|
|
16484
16426
|
if (typeof value !== "number" || Number.isNaN(value) || value < 0) {
|
|
16485
|
-
throw new Error(`${
|
|
16427
|
+
throw new Error(`${path33} must be a non-negative number`);
|
|
16486
16428
|
}
|
|
16487
16429
|
return value;
|
|
16488
16430
|
}
|
|
16489
|
-
function parseQueryType(value,
|
|
16431
|
+
function parseQueryType(value, path33) {
|
|
16490
16432
|
if (value === "definition" || value === "implementation-intent" || value === "similarity" || value === "keyword-heavy" || value === "conceptual") {
|
|
16491
16433
|
return value;
|
|
16492
16434
|
}
|
|
16493
16435
|
throw new Error(
|
|
16494
|
-
`${
|
|
16436
|
+
`${path33} must be one of: definition, implementation-intent, similarity, keyword-heavy, conceptual`
|
|
16495
16437
|
);
|
|
16496
16438
|
}
|
|
16497
|
-
function parseExpectedRoute(value,
|
|
16439
|
+
function parseExpectedRoute(value, path33) {
|
|
16498
16440
|
if (value === void 0) return void 0;
|
|
16499
16441
|
if (value === "search" || value === "definition") return value;
|
|
16500
|
-
throw new Error(`${
|
|
16442
|
+
throw new Error(`${path33} must be one of: search, definition`);
|
|
16501
16443
|
}
|
|
16502
|
-
function parseExpectedOutcome(value,
|
|
16444
|
+
function parseExpectedOutcome(value, path33) {
|
|
16503
16445
|
if (value === void 0) return void 0;
|
|
16504
16446
|
if (value === "results" || value === "no-results") {
|
|
16505
16447
|
return value;
|
|
16506
16448
|
}
|
|
16507
|
-
throw new Error(`${
|
|
16449
|
+
throw new Error(`${path33} must be one of: results, no-results`);
|
|
16508
16450
|
}
|
|
16509
|
-
function parseRecoveryExpectation(value,
|
|
16451
|
+
function parseRecoveryExpectation(value, path33) {
|
|
16510
16452
|
if (value === void 0) return void 0;
|
|
16511
16453
|
if (value === "none" || value === "filter-relaxed") {
|
|
16512
16454
|
return value;
|
|
16513
16455
|
}
|
|
16514
|
-
throw new Error(`${
|
|
16456
|
+
throw new Error(`${path33} must be one of: none, filter-relaxed`);
|
|
16515
16457
|
}
|
|
16516
|
-
function parseQueryDifficulty(value,
|
|
16458
|
+
function parseQueryDifficulty(value, path33) {
|
|
16517
16459
|
if (value === void 0) return void 0;
|
|
16518
16460
|
if (value === "easy" || value === "medium" || value === "hard") {
|
|
16519
16461
|
return value;
|
|
16520
16462
|
}
|
|
16521
|
-
throw new Error(`${
|
|
16463
|
+
throw new Error(`${path33} must be one of: easy, medium, hard`);
|
|
16522
16464
|
}
|
|
16523
|
-
function parseQueryTags(value,
|
|
16465
|
+
function parseQueryTags(value, path33) {
|
|
16524
16466
|
if (value === void 0) return void 0;
|
|
16525
16467
|
if (!isStringArray4(value) || value.some((tag) => tag.trim().length === 0)) {
|
|
16526
|
-
throw new Error(`${
|
|
16468
|
+
throw new Error(`${path33} must be an array of non-empty strings`);
|
|
16527
16469
|
}
|
|
16528
16470
|
if (value.length > 16) {
|
|
16529
|
-
throw new Error(`${
|
|
16471
|
+
throw new Error(`${path33} must contain at most 16 tags`);
|
|
16530
16472
|
}
|
|
16531
16473
|
return value;
|
|
16532
16474
|
}
|
|
16533
|
-
function parseQueryArgs(value,
|
|
16475
|
+
function parseQueryArgs(value, path33) {
|
|
16534
16476
|
if (value === void 0) return void 0;
|
|
16535
16477
|
if (!isRecord3(value)) {
|
|
16536
|
-
throw new Error(`${
|
|
16537
|
-
}
|
|
16538
|
-
const symbol = parseStringOrUndefined(value.symbol, `${
|
|
16539
|
-
const filePath = parseStringOrUndefined(value.filePath, `${
|
|
16540
|
-
const fileType = parseStringOrUndefined(value.fileType, `${
|
|
16541
|
-
const directory = parseStringOrUndefined(value.directory, `${
|
|
16542
|
-
const callerLimit = parsePositiveIntegerOrUndefined(value.callerLimit, `${
|
|
16543
|
-
const calleeLimit = parsePositiveIntegerOrUndefined(value.calleeLimit, `${
|
|
16544
|
-
const tokenBudget = parsePositiveIntegerOrUndefined(value.tokenBudget, `${
|
|
16478
|
+
throw new Error(`${path33} must be an object`);
|
|
16479
|
+
}
|
|
16480
|
+
const symbol = parseStringOrUndefined(value.symbol, `${path33}.symbol`);
|
|
16481
|
+
const filePath = parseStringOrUndefined(value.filePath, `${path33}.filePath`);
|
|
16482
|
+
const fileType = parseStringOrUndefined(value.fileType, `${path33}.fileType`);
|
|
16483
|
+
const directory = parseStringOrUndefined(value.directory, `${path33}.directory`);
|
|
16484
|
+
const callerLimit = parsePositiveIntegerOrUndefined(value.callerLimit, `${path33}.callerLimit`);
|
|
16485
|
+
const calleeLimit = parsePositiveIntegerOrUndefined(value.calleeLimit, `${path33}.calleeLimit`);
|
|
16486
|
+
const tokenBudget = parsePositiveIntegerOrUndefined(value.tokenBudget, `${path33}.tokenBudget`);
|
|
16545
16487
|
return {
|
|
16546
16488
|
...symbol !== void 0 ? { symbol } : {},
|
|
16547
16489
|
...filePath !== void 0 ? { filePath } : {},
|
|
@@ -16552,50 +16494,50 @@ function parseQueryArgs(value, path31) {
|
|
|
16552
16494
|
...tokenBudget !== void 0 ? { tokenBudget } : {}
|
|
16553
16495
|
};
|
|
16554
16496
|
}
|
|
16555
|
-
function parsePositiveIntegerOrUndefined(value,
|
|
16497
|
+
function parsePositiveIntegerOrUndefined(value, path33) {
|
|
16556
16498
|
if (value === void 0 || value === null) return void 0;
|
|
16557
16499
|
if (typeof value !== "number" || !Number.isInteger(value) || value <= 0) {
|
|
16558
|
-
throw new Error(`${
|
|
16500
|
+
throw new Error(`${path33} must be a positive integer`);
|
|
16559
16501
|
}
|
|
16560
16502
|
return value;
|
|
16561
16503
|
}
|
|
16562
16504
|
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-]+)*)?$/;
|
|
16563
|
-
function parseSemanticVersion(value,
|
|
16505
|
+
function parseSemanticVersion(value, path33) {
|
|
16564
16506
|
if (!isNonEmptyString(value)) {
|
|
16565
|
-
throw new Error(`${
|
|
16507
|
+
throw new Error(`${path33} must be a non-empty string`);
|
|
16566
16508
|
}
|
|
16567
16509
|
if (!SEMVER_VERSION_PATTERN.test(value)) {
|
|
16568
|
-
throw new Error(`${
|
|
16510
|
+
throw new Error(`${path33} must be a valid semantic version (MAJOR.MINOR.PATCH)`);
|
|
16569
16511
|
}
|
|
16570
16512
|
return value;
|
|
16571
16513
|
}
|
|
16572
|
-
function parseRetrievalMode(value,
|
|
16514
|
+
function parseRetrievalMode(value, path33) {
|
|
16573
16515
|
if (value === void 0 || value === "search") return "search";
|
|
16574
16516
|
if (value === "context" || value === "edit-context") return value;
|
|
16575
|
-
throw new Error(`${
|
|
16517
|
+
throw new Error(`${path33} must be one of: search, context, edit-context`);
|
|
16576
16518
|
}
|
|
16577
|
-
function parseStringOrUndefined(value,
|
|
16519
|
+
function parseStringOrUndefined(value, path33) {
|
|
16578
16520
|
if (value === void 0 || value === null) return void 0;
|
|
16579
16521
|
if (!isNonEmptyString(value)) {
|
|
16580
|
-
throw new Error(`${
|
|
16522
|
+
throw new Error(`${path33} must be a non-empty string`);
|
|
16581
16523
|
}
|
|
16582
16524
|
return value;
|
|
16583
16525
|
}
|
|
16584
|
-
function parseGradedEvidence(value,
|
|
16526
|
+
function parseGradedEvidence(value, path33) {
|
|
16585
16527
|
if (value === void 0) return [];
|
|
16586
16528
|
if (!Array.isArray(value)) {
|
|
16587
|
-
throw new Error(`${
|
|
16529
|
+
throw new Error(`${path33} must be an array`);
|
|
16588
16530
|
}
|
|
16589
16531
|
return value.map((entry, index) => {
|
|
16590
16532
|
if (!isRecord3(entry)) {
|
|
16591
|
-
throw new Error(`${
|
|
16533
|
+
throw new Error(`${path33}[${index}] must be an object`);
|
|
16592
16534
|
}
|
|
16593
|
-
const evidencePath = parseStringOrUndefined(entry.path, `${
|
|
16535
|
+
const evidencePath = parseStringOrUndefined(entry.path, `${path33}[${index}].path`);
|
|
16594
16536
|
if (evidencePath === void 0) {
|
|
16595
|
-
throw new Error(`${
|
|
16537
|
+
throw new Error(`${path33}[${index}].path is required`);
|
|
16596
16538
|
}
|
|
16597
|
-
const symbol = parseStringOrUndefined(entry.symbol, `${
|
|
16598
|
-
const relevance = parseEvidenceRelevance(entry.relevance, `${
|
|
16539
|
+
const symbol = parseStringOrUndefined(entry.symbol, `${path33}[${index}].symbol`);
|
|
16540
|
+
const relevance = parseEvidenceRelevance(entry.relevance, `${path33}[${index}].relevance`);
|
|
16599
16541
|
return {
|
|
16600
16542
|
path: evidencePath,
|
|
16601
16543
|
...symbol !== void 0 ? { symbol } : {},
|
|
@@ -16603,27 +16545,27 @@ function parseGradedEvidence(value, path31) {
|
|
|
16603
16545
|
};
|
|
16604
16546
|
});
|
|
16605
16547
|
}
|
|
16606
|
-
function parseEvidenceRelevance(value,
|
|
16548
|
+
function parseEvidenceRelevance(value, path33) {
|
|
16607
16549
|
if (value === void 0) {
|
|
16608
|
-
throw new Error(`${
|
|
16550
|
+
throw new Error(`${path33} is required`);
|
|
16609
16551
|
}
|
|
16610
16552
|
if (value !== 1 && value !== 2 && value !== 3) {
|
|
16611
|
-
throw new Error(`${
|
|
16553
|
+
throw new Error(`${path33} must be 1, 2, or 3`);
|
|
16612
16554
|
}
|
|
16613
16555
|
return value;
|
|
16614
16556
|
}
|
|
16615
|
-
function parseExpectedGraphNeighbor(value,
|
|
16557
|
+
function parseExpectedGraphNeighbor(value, path33) {
|
|
16616
16558
|
if (value === void 0) return void 0;
|
|
16617
16559
|
if (!isRecord3(value)) {
|
|
16618
|
-
throw new Error(`${
|
|
16560
|
+
throw new Error(`${path33} must be an object`);
|
|
16619
16561
|
}
|
|
16620
16562
|
if (value.direction !== "caller" && value.direction !== "callee") {
|
|
16621
|
-
throw new Error(`${
|
|
16563
|
+
throw new Error(`${path33}.direction must be one of: caller, callee`);
|
|
16622
16564
|
}
|
|
16623
|
-
const filePath = parseStringOrUndefined(value.filePath, `${
|
|
16624
|
-
const symbol = parseStringOrUndefined(value.symbol, `${
|
|
16565
|
+
const filePath = parseStringOrUndefined(value.filePath, `${path33}.filePath`);
|
|
16566
|
+
const symbol = parseStringOrUndefined(value.symbol, `${path33}.symbol`);
|
|
16625
16567
|
if (filePath === void 0 && symbol === void 0) {
|
|
16626
|
-
throw new Error(`${
|
|
16568
|
+
throw new Error(`${path33} must include filePath or symbol`);
|
|
16627
16569
|
}
|
|
16628
16570
|
return {
|
|
16629
16571
|
direction: value.direction,
|
|
@@ -16631,9 +16573,9 @@ function parseExpectedGraphNeighbor(value, path31) {
|
|
|
16631
16573
|
...symbol !== void 0 ? { symbol } : {}
|
|
16632
16574
|
};
|
|
16633
16575
|
}
|
|
16634
|
-
function parseExpected(input,
|
|
16576
|
+
function parseExpected(input, path33) {
|
|
16635
16577
|
if (!isRecord3(input)) {
|
|
16636
|
-
throw new Error(`${
|
|
16578
|
+
throw new Error(`${path33} must be an object`);
|
|
16637
16579
|
}
|
|
16638
16580
|
const filePathRaw = input.filePath;
|
|
16639
16581
|
const acceptableFilesRaw = input.acceptableFiles;
|
|
@@ -16644,29 +16586,29 @@ function parseExpected(input, path31) {
|
|
|
16644
16586
|
const recoveryExpectationRaw = input.recoveryExpectation;
|
|
16645
16587
|
const gradedEvidenceRaw = input.gradedEvidence;
|
|
16646
16588
|
const graphNeighborRaw = input.graphNeighbor;
|
|
16647
|
-
const filePath = parseStringOrUndefined(filePathRaw, `${
|
|
16589
|
+
const filePath = parseStringOrUndefined(filePathRaw, `${path33}.filePath`);
|
|
16648
16590
|
const acceptableFiles = isStringArray4(acceptableFilesRaw) ? acceptableFilesRaw : void 0;
|
|
16649
|
-
const gradedEvidence = parseGradedEvidence(gradedEvidenceRaw, `${
|
|
16650
|
-
const graphNeighbor = parseExpectedGraphNeighbor(graphNeighborRaw, `${
|
|
16651
|
-
const expectedOutcome = parseExpectedOutcome(expectedOutcomeRaw, `${
|
|
16591
|
+
const gradedEvidence = parseGradedEvidence(gradedEvidenceRaw, `${path33}.gradedEvidence`);
|
|
16592
|
+
const graphNeighbor = parseExpectedGraphNeighbor(graphNeighborRaw, `${path33}.graphNeighbor`);
|
|
16593
|
+
const expectedOutcome = parseExpectedOutcome(expectedOutcomeRaw, `${path33}.expectedOutcome`);
|
|
16652
16594
|
if (expectedOutcome !== "no-results" && !filePath && (!acceptableFiles || acceptableFiles.length === 0) && gradedEvidence.length === 0) {
|
|
16653
16595
|
throw new Error(
|
|
16654
|
-
`${
|
|
16596
|
+
`${path33} must include expected.filePath, expected.acceptableFiles, or expected.gradedEvidence`
|
|
16655
16597
|
);
|
|
16656
16598
|
}
|
|
16657
16599
|
if (acceptableFilesRaw !== void 0 && !isStringArray4(acceptableFilesRaw)) {
|
|
16658
|
-
throw new Error(`${
|
|
16600
|
+
throw new Error(`${path33}.acceptableFiles must be an array of strings`);
|
|
16659
16601
|
}
|
|
16660
16602
|
if (symbolRaw !== void 0 && typeof symbolRaw !== "string") {
|
|
16661
|
-
throw new Error(`${
|
|
16603
|
+
throw new Error(`${path33}.symbol must be a string when provided`);
|
|
16662
16604
|
}
|
|
16663
16605
|
if (branchRaw !== void 0 && typeof branchRaw !== "string") {
|
|
16664
|
-
throw new Error(`${
|
|
16606
|
+
throw new Error(`${path33}.branch must be a string when provided`);
|
|
16665
16607
|
}
|
|
16666
|
-
const expectedRoute = parseExpectedRoute(expectedRouteRaw, `${
|
|
16608
|
+
const expectedRoute = parseExpectedRoute(expectedRouteRaw, `${path33}.expectedRoute`);
|
|
16667
16609
|
const recoveryExpectation = parseRecoveryExpectation(
|
|
16668
16610
|
recoveryExpectationRaw,
|
|
16669
|
-
`${
|
|
16611
|
+
`${path33}.recoveryExpectation`
|
|
16670
16612
|
);
|
|
16671
16613
|
return {
|
|
16672
16614
|
filePath,
|
|
@@ -16680,13 +16622,13 @@ function parseExpected(input, path31) {
|
|
|
16680
16622
|
...graphNeighbor !== void 0 ? { graphNeighbor } : {}
|
|
16681
16623
|
};
|
|
16682
16624
|
}
|
|
16683
|
-
function parseQueryLanguage(value,
|
|
16684
|
-
return parseStringOrUndefined(value,
|
|
16625
|
+
function parseQueryLanguage(value, path33) {
|
|
16626
|
+
return parseStringOrUndefined(value, path33);
|
|
16685
16627
|
}
|
|
16686
16628
|
function parseQuery(input, index) {
|
|
16687
|
-
const
|
|
16629
|
+
const path33 = `queries[${index}]`;
|
|
16688
16630
|
if (!isRecord3(input)) {
|
|
16689
|
-
throw new Error(`${
|
|
16631
|
+
throw new Error(`${path33} must be an object`);
|
|
16690
16632
|
}
|
|
16691
16633
|
const id = input.id;
|
|
16692
16634
|
const query = input.query;
|
|
@@ -16698,21 +16640,21 @@ function parseQuery(input, index) {
|
|
|
16698
16640
|
const tags = input.tags;
|
|
16699
16641
|
const args = input.args;
|
|
16700
16642
|
if (typeof id !== "string" || id.trim().length === 0) {
|
|
16701
|
-
throw new Error(`${
|
|
16643
|
+
throw new Error(`${path33}.id must be a non-empty string`);
|
|
16702
16644
|
}
|
|
16703
16645
|
if (typeof query !== "string" || query.trim().length === 0) {
|
|
16704
|
-
throw new Error(`${
|
|
16646
|
+
throw new Error(`${path33}.query must be a non-empty string`);
|
|
16705
16647
|
}
|
|
16706
16648
|
return {
|
|
16707
16649
|
id,
|
|
16708
16650
|
query,
|
|
16709
|
-
queryType: parseQueryType(queryType, `${
|
|
16710
|
-
retrievalMode: parseRetrievalMode(retrievalMode, `${
|
|
16711
|
-
language: parseQueryLanguage(language, `${
|
|
16712
|
-
difficulty: parseQueryDifficulty(difficulty, `${
|
|
16713
|
-
args: parseQueryArgs(args, `${
|
|
16714
|
-
tags: parseQueryTags(tags, `${
|
|
16715
|
-
expected: parseExpected(expected, `${
|
|
16651
|
+
queryType: parseQueryType(queryType, `${path33}.queryType`),
|
|
16652
|
+
retrievalMode: parseRetrievalMode(retrievalMode, `${path33}.retrievalMode`),
|
|
16653
|
+
language: parseQueryLanguage(language, `${path33}.language`),
|
|
16654
|
+
difficulty: parseQueryDifficulty(difficulty, `${path33}.difficulty`),
|
|
16655
|
+
args: parseQueryArgs(args, `${path33}.args`),
|
|
16656
|
+
tags: parseQueryTags(tags, `${path33}.tags`),
|
|
16657
|
+
expected: parseExpected(expected, `${path33}.expected`)
|
|
16716
16658
|
};
|
|
16717
16659
|
}
|
|
16718
16660
|
function parseGoldenDataset(raw, sourceLabel) {
|
|
@@ -17678,7 +17620,7 @@ async function executeCallGraph(projectRoot, host, args) {
|
|
|
17678
17620
|
return { text: formatCallGraphResult(await getCallGraphData(projectRoot, host, args)) };
|
|
17679
17621
|
}
|
|
17680
17622
|
async function executeCallGraphPath(projectRoot, host, args) {
|
|
17681
|
-
const
|
|
17623
|
+
const path33 = await getCallGraphPath(
|
|
17682
17624
|
projectRoot,
|
|
17683
17625
|
host,
|
|
17684
17626
|
args.from,
|
|
@@ -17687,7 +17629,7 @@ async function executeCallGraphPath(projectRoot, host, args) {
|
|
|
17687
17629
|
args.fromFilePath,
|
|
17688
17630
|
args.toFilePath
|
|
17689
17631
|
);
|
|
17690
|
-
return { text: formatCallGraphPathResult(
|
|
17632
|
+
return { text: formatCallGraphPathResult(path33) };
|
|
17691
17633
|
}
|
|
17692
17634
|
async function executeCodeCommunities(projectRoot, host, args) {
|
|
17693
17635
|
const result = await getCodeCommunities(projectRoot, host, args);
|
|
@@ -18174,7 +18116,7 @@ function createMcpServer(projectRoot, config, host) {
|
|
|
18174
18116
|
}
|
|
18175
18117
|
|
|
18176
18118
|
// src/watcher/file-watcher.ts
|
|
18177
|
-
import { existsSync as existsSync15 } from "fs";
|
|
18119
|
+
import { existsSync as existsSync15, statSync as statSync6 } from "fs";
|
|
18178
18120
|
|
|
18179
18121
|
// node_modules/chokidar/index.js
|
|
18180
18122
|
import { EventEmitter as EventEmitter2 } from "events";
|
|
@@ -18266,7 +18208,7 @@ var ReaddirpStream = class extends Readable {
|
|
|
18266
18208
|
this._directoryFilter = normalizeFilter(opts.directoryFilter);
|
|
18267
18209
|
const statMethod = opts.lstat ? lstat : stat;
|
|
18268
18210
|
if (wantBigintFsStats) {
|
|
18269
|
-
this._stat = (
|
|
18211
|
+
this._stat = (path33) => statMethod(path33, { bigint: true });
|
|
18270
18212
|
} else {
|
|
18271
18213
|
this._stat = statMethod;
|
|
18272
18214
|
}
|
|
@@ -18291,8 +18233,8 @@ var ReaddirpStream = class extends Readable {
|
|
|
18291
18233
|
const par = this.parent;
|
|
18292
18234
|
const fil = par && par.files;
|
|
18293
18235
|
if (fil && fil.length > 0) {
|
|
18294
|
-
const { path:
|
|
18295
|
-
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent,
|
|
18236
|
+
const { path: path33, depth } = par;
|
|
18237
|
+
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path33));
|
|
18296
18238
|
const awaited = await Promise.all(slice);
|
|
18297
18239
|
for (const entry of awaited) {
|
|
18298
18240
|
if (!entry)
|
|
@@ -18332,20 +18274,20 @@ var ReaddirpStream = class extends Readable {
|
|
|
18332
18274
|
this.reading = false;
|
|
18333
18275
|
}
|
|
18334
18276
|
}
|
|
18335
|
-
async _exploreDir(
|
|
18277
|
+
async _exploreDir(path33, depth) {
|
|
18336
18278
|
let files;
|
|
18337
18279
|
try {
|
|
18338
|
-
files = await readdir(
|
|
18280
|
+
files = await readdir(path33, this._rdOptions);
|
|
18339
18281
|
} catch (error) {
|
|
18340
18282
|
this._onError(error);
|
|
18341
18283
|
}
|
|
18342
|
-
return { files, depth, path:
|
|
18284
|
+
return { files, depth, path: path33 };
|
|
18343
18285
|
}
|
|
18344
|
-
async _formatEntry(dirent,
|
|
18286
|
+
async _formatEntry(dirent, path33) {
|
|
18345
18287
|
let entry;
|
|
18346
18288
|
const basename8 = this._isDirent ? dirent.name : dirent;
|
|
18347
18289
|
try {
|
|
18348
|
-
const fullPath = presolve(pjoin(
|
|
18290
|
+
const fullPath = presolve(pjoin(path33, basename8));
|
|
18349
18291
|
entry = { path: prelative(this._root, fullPath), fullPath, basename: basename8 };
|
|
18350
18292
|
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
18351
18293
|
} catch (err) {
|
|
@@ -18745,16 +18687,16 @@ var delFromSet = (main, prop, item) => {
|
|
|
18745
18687
|
};
|
|
18746
18688
|
var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
|
|
18747
18689
|
var FsWatchInstances = /* @__PURE__ */ new Map();
|
|
18748
|
-
function createFsWatchInstance(
|
|
18690
|
+
function createFsWatchInstance(path33, options, listener, errHandler, emitRaw) {
|
|
18749
18691
|
const handleEvent = (rawEvent, evPath) => {
|
|
18750
|
-
listener(
|
|
18751
|
-
emitRaw(rawEvent, evPath, { watchedPath:
|
|
18752
|
-
if (evPath &&
|
|
18753
|
-
fsWatchBroadcast(sp.resolve(
|
|
18692
|
+
listener(path33);
|
|
18693
|
+
emitRaw(rawEvent, evPath, { watchedPath: path33 });
|
|
18694
|
+
if (evPath && path33 !== evPath) {
|
|
18695
|
+
fsWatchBroadcast(sp.resolve(path33, evPath), KEY_LISTENERS, sp.join(path33, evPath));
|
|
18754
18696
|
}
|
|
18755
18697
|
};
|
|
18756
18698
|
try {
|
|
18757
|
-
return fs_watch(
|
|
18699
|
+
return fs_watch(path33, {
|
|
18758
18700
|
persistent: options.persistent
|
|
18759
18701
|
}, handleEvent);
|
|
18760
18702
|
} catch (error) {
|
|
@@ -18770,12 +18712,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
|
|
|
18770
18712
|
listener(val1, val2, val3);
|
|
18771
18713
|
});
|
|
18772
18714
|
};
|
|
18773
|
-
var setFsWatchListener = (
|
|
18715
|
+
var setFsWatchListener = (path33, fullPath, options, handlers) => {
|
|
18774
18716
|
const { listener, errHandler, rawEmitter } = handlers;
|
|
18775
18717
|
let cont = FsWatchInstances.get(fullPath);
|
|
18776
18718
|
let watcher;
|
|
18777
18719
|
if (!options.persistent) {
|
|
18778
|
-
watcher = createFsWatchInstance(
|
|
18720
|
+
watcher = createFsWatchInstance(path33, options, listener, errHandler, rawEmitter);
|
|
18779
18721
|
if (!watcher)
|
|
18780
18722
|
return;
|
|
18781
18723
|
return watcher.close.bind(watcher);
|
|
@@ -18786,7 +18728,7 @@ var setFsWatchListener = (path31, fullPath, options, handlers) => {
|
|
|
18786
18728
|
addAndConvert(cont, KEY_RAW, rawEmitter);
|
|
18787
18729
|
} else {
|
|
18788
18730
|
watcher = createFsWatchInstance(
|
|
18789
|
-
|
|
18731
|
+
path33,
|
|
18790
18732
|
options,
|
|
18791
18733
|
fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
|
|
18792
18734
|
errHandler,
|
|
@@ -18801,7 +18743,7 @@ var setFsWatchListener = (path31, fullPath, options, handlers) => {
|
|
|
18801
18743
|
cont.watcherUnusable = true;
|
|
18802
18744
|
if (isWindows && error.code === "EPERM") {
|
|
18803
18745
|
try {
|
|
18804
|
-
const fd = await open(
|
|
18746
|
+
const fd = await open(path33, "r");
|
|
18805
18747
|
await fd.close();
|
|
18806
18748
|
broadcastErr(error);
|
|
18807
18749
|
} catch (err) {
|
|
@@ -18832,7 +18774,7 @@ var setFsWatchListener = (path31, fullPath, options, handlers) => {
|
|
|
18832
18774
|
};
|
|
18833
18775
|
};
|
|
18834
18776
|
var FsWatchFileInstances = /* @__PURE__ */ new Map();
|
|
18835
|
-
var setFsWatchFileListener = (
|
|
18777
|
+
var setFsWatchFileListener = (path33, fullPath, options, handlers) => {
|
|
18836
18778
|
const { listener, rawEmitter } = handlers;
|
|
18837
18779
|
let cont = FsWatchFileInstances.get(fullPath);
|
|
18838
18780
|
const copts = cont && cont.options;
|
|
@@ -18854,7 +18796,7 @@ var setFsWatchFileListener = (path31, fullPath, options, handlers) => {
|
|
|
18854
18796
|
});
|
|
18855
18797
|
const currmtime = curr.mtimeMs;
|
|
18856
18798
|
if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
|
|
18857
|
-
foreach(cont.listeners, (listener2) => listener2(
|
|
18799
|
+
foreach(cont.listeners, (listener2) => listener2(path33, curr));
|
|
18858
18800
|
}
|
|
18859
18801
|
})
|
|
18860
18802
|
};
|
|
@@ -18884,13 +18826,13 @@ var NodeFsHandler = class {
|
|
|
18884
18826
|
* @param listener on fs change
|
|
18885
18827
|
* @returns closer for the watcher instance
|
|
18886
18828
|
*/
|
|
18887
|
-
_watchWithNodeFs(
|
|
18829
|
+
_watchWithNodeFs(path33, listener) {
|
|
18888
18830
|
const opts = this.fsw.options;
|
|
18889
|
-
const directory = sp.dirname(
|
|
18890
|
-
const basename8 = sp.basename(
|
|
18831
|
+
const directory = sp.dirname(path33);
|
|
18832
|
+
const basename8 = sp.basename(path33);
|
|
18891
18833
|
const parent = this.fsw._getWatchedDir(directory);
|
|
18892
18834
|
parent.add(basename8);
|
|
18893
|
-
const absolutePath = sp.resolve(
|
|
18835
|
+
const absolutePath = sp.resolve(path33);
|
|
18894
18836
|
const options = {
|
|
18895
18837
|
persistent: opts.persistent
|
|
18896
18838
|
};
|
|
@@ -18900,12 +18842,12 @@ var NodeFsHandler = class {
|
|
|
18900
18842
|
if (opts.usePolling) {
|
|
18901
18843
|
const enableBin = opts.interval !== opts.binaryInterval;
|
|
18902
18844
|
options.interval = enableBin && isBinaryPath(basename8) ? opts.binaryInterval : opts.interval;
|
|
18903
|
-
closer = setFsWatchFileListener(
|
|
18845
|
+
closer = setFsWatchFileListener(path33, absolutePath, options, {
|
|
18904
18846
|
listener,
|
|
18905
18847
|
rawEmitter: this.fsw._emitRaw
|
|
18906
18848
|
});
|
|
18907
18849
|
} else {
|
|
18908
|
-
closer = setFsWatchListener(
|
|
18850
|
+
closer = setFsWatchListener(path33, absolutePath, options, {
|
|
18909
18851
|
listener,
|
|
18910
18852
|
errHandler: this._boundHandleError,
|
|
18911
18853
|
rawEmitter: this.fsw._emitRaw
|
|
@@ -18927,7 +18869,7 @@ var NodeFsHandler = class {
|
|
|
18927
18869
|
let prevStats = stats;
|
|
18928
18870
|
if (parent.has(basename8))
|
|
18929
18871
|
return;
|
|
18930
|
-
const listener = async (
|
|
18872
|
+
const listener = async (path33, newStats) => {
|
|
18931
18873
|
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
|
|
18932
18874
|
return;
|
|
18933
18875
|
if (!newStats || newStats.mtimeMs === 0) {
|
|
@@ -18941,11 +18883,11 @@ var NodeFsHandler = class {
|
|
|
18941
18883
|
this.fsw._emit(EV.CHANGE, file, newStats2);
|
|
18942
18884
|
}
|
|
18943
18885
|
if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
|
|
18944
|
-
this.fsw._closeFile(
|
|
18886
|
+
this.fsw._closeFile(path33);
|
|
18945
18887
|
prevStats = newStats2;
|
|
18946
18888
|
const closer2 = this._watchWithNodeFs(file, listener);
|
|
18947
18889
|
if (closer2)
|
|
18948
|
-
this.fsw._addPathCloser(
|
|
18890
|
+
this.fsw._addPathCloser(path33, closer2);
|
|
18949
18891
|
} else {
|
|
18950
18892
|
prevStats = newStats2;
|
|
18951
18893
|
}
|
|
@@ -18977,7 +18919,7 @@ var NodeFsHandler = class {
|
|
|
18977
18919
|
* @param item basename of this item
|
|
18978
18920
|
* @returns true if no more processing is needed for this entry.
|
|
18979
18921
|
*/
|
|
18980
|
-
async _handleSymlink(entry, directory,
|
|
18922
|
+
async _handleSymlink(entry, directory, path33, item) {
|
|
18981
18923
|
if (this.fsw.closed) {
|
|
18982
18924
|
return;
|
|
18983
18925
|
}
|
|
@@ -18987,7 +18929,7 @@ var NodeFsHandler = class {
|
|
|
18987
18929
|
this.fsw._incrReadyCount();
|
|
18988
18930
|
let linkPath;
|
|
18989
18931
|
try {
|
|
18990
|
-
linkPath = await fsrealpath(
|
|
18932
|
+
linkPath = await fsrealpath(path33);
|
|
18991
18933
|
} catch (e) {
|
|
18992
18934
|
this.fsw._emitReady();
|
|
18993
18935
|
return true;
|
|
@@ -18997,12 +18939,12 @@ var NodeFsHandler = class {
|
|
|
18997
18939
|
if (dir.has(item)) {
|
|
18998
18940
|
if (this.fsw._symlinkPaths.get(full) !== linkPath) {
|
|
18999
18941
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
19000
|
-
this.fsw._emit(EV.CHANGE,
|
|
18942
|
+
this.fsw._emit(EV.CHANGE, path33, entry.stats);
|
|
19001
18943
|
}
|
|
19002
18944
|
} else {
|
|
19003
18945
|
dir.add(item);
|
|
19004
18946
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
19005
|
-
this.fsw._emit(EV.ADD,
|
|
18947
|
+
this.fsw._emit(EV.ADD, path33, entry.stats);
|
|
19006
18948
|
}
|
|
19007
18949
|
this.fsw._emitReady();
|
|
19008
18950
|
return true;
|
|
@@ -19032,9 +18974,9 @@ var NodeFsHandler = class {
|
|
|
19032
18974
|
return;
|
|
19033
18975
|
}
|
|
19034
18976
|
const item = entry.path;
|
|
19035
|
-
let
|
|
18977
|
+
let path33 = sp.join(directory, item);
|
|
19036
18978
|
current.add(item);
|
|
19037
|
-
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory,
|
|
18979
|
+
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path33, item)) {
|
|
19038
18980
|
return;
|
|
19039
18981
|
}
|
|
19040
18982
|
if (this.fsw.closed) {
|
|
@@ -19043,11 +18985,11 @@ var NodeFsHandler = class {
|
|
|
19043
18985
|
}
|
|
19044
18986
|
if (item === target || !target && !previous.has(item)) {
|
|
19045
18987
|
this.fsw._incrReadyCount();
|
|
19046
|
-
|
|
19047
|
-
this._addToNodeFs(
|
|
18988
|
+
path33 = sp.join(dir, sp.relative(dir, path33));
|
|
18989
|
+
this._addToNodeFs(path33, initialAdd, wh, depth + 1);
|
|
19048
18990
|
}
|
|
19049
18991
|
}).on(EV.ERROR, this._boundHandleError);
|
|
19050
|
-
return new Promise((
|
|
18992
|
+
return new Promise((resolve20, reject) => {
|
|
19051
18993
|
if (!stream)
|
|
19052
18994
|
return reject();
|
|
19053
18995
|
stream.once(STR_END, () => {
|
|
@@ -19056,7 +18998,7 @@ var NodeFsHandler = class {
|
|
|
19056
18998
|
return;
|
|
19057
18999
|
}
|
|
19058
19000
|
const wasThrottled = throttler ? throttler.clear() : false;
|
|
19059
|
-
|
|
19001
|
+
resolve20(void 0);
|
|
19060
19002
|
previous.getChildren().filter((item) => {
|
|
19061
19003
|
return item !== directory && !current.has(item);
|
|
19062
19004
|
}).forEach((item) => {
|
|
@@ -19113,13 +19055,13 @@ var NodeFsHandler = class {
|
|
|
19113
19055
|
* @param depth Child path actually targeted for watch
|
|
19114
19056
|
* @param target Child path actually targeted for watch
|
|
19115
19057
|
*/
|
|
19116
|
-
async _addToNodeFs(
|
|
19058
|
+
async _addToNodeFs(path33, initialAdd, priorWh, depth, target) {
|
|
19117
19059
|
const ready = this.fsw._emitReady;
|
|
19118
|
-
if (this.fsw._isIgnored(
|
|
19060
|
+
if (this.fsw._isIgnored(path33) || this.fsw.closed) {
|
|
19119
19061
|
ready();
|
|
19120
19062
|
return false;
|
|
19121
19063
|
}
|
|
19122
|
-
const wh = this.fsw._getWatchHelpers(
|
|
19064
|
+
const wh = this.fsw._getWatchHelpers(path33);
|
|
19123
19065
|
if (priorWh) {
|
|
19124
19066
|
wh.filterPath = (entry) => priorWh.filterPath(entry);
|
|
19125
19067
|
wh.filterDir = (entry) => priorWh.filterDir(entry);
|
|
@@ -19135,8 +19077,8 @@ var NodeFsHandler = class {
|
|
|
19135
19077
|
const follow = this.fsw.options.followSymlinks;
|
|
19136
19078
|
let closer;
|
|
19137
19079
|
if (stats.isDirectory()) {
|
|
19138
|
-
const absPath = sp.resolve(
|
|
19139
|
-
const targetPath = follow ? await fsrealpath(
|
|
19080
|
+
const absPath = sp.resolve(path33);
|
|
19081
|
+
const targetPath = follow ? await fsrealpath(path33) : path33;
|
|
19140
19082
|
if (this.fsw.closed)
|
|
19141
19083
|
return;
|
|
19142
19084
|
closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
|
|
@@ -19146,29 +19088,29 @@ var NodeFsHandler = class {
|
|
|
19146
19088
|
this.fsw._symlinkPaths.set(absPath, targetPath);
|
|
19147
19089
|
}
|
|
19148
19090
|
} else if (stats.isSymbolicLink()) {
|
|
19149
|
-
const targetPath = follow ? await fsrealpath(
|
|
19091
|
+
const targetPath = follow ? await fsrealpath(path33) : path33;
|
|
19150
19092
|
if (this.fsw.closed)
|
|
19151
19093
|
return;
|
|
19152
19094
|
const parent = sp.dirname(wh.watchPath);
|
|
19153
19095
|
this.fsw._getWatchedDir(parent).add(wh.watchPath);
|
|
19154
19096
|
this.fsw._emit(EV.ADD, wh.watchPath, stats);
|
|
19155
|
-
closer = await this._handleDir(parent, stats, initialAdd, depth,
|
|
19097
|
+
closer = await this._handleDir(parent, stats, initialAdd, depth, path33, wh, targetPath);
|
|
19156
19098
|
if (this.fsw.closed)
|
|
19157
19099
|
return;
|
|
19158
19100
|
if (targetPath !== void 0) {
|
|
19159
|
-
this.fsw._symlinkPaths.set(sp.resolve(
|
|
19101
|
+
this.fsw._symlinkPaths.set(sp.resolve(path33), targetPath);
|
|
19160
19102
|
}
|
|
19161
19103
|
} else {
|
|
19162
19104
|
closer = this._handleFile(wh.watchPath, stats, initialAdd);
|
|
19163
19105
|
}
|
|
19164
19106
|
ready();
|
|
19165
19107
|
if (closer)
|
|
19166
|
-
this.fsw._addPathCloser(
|
|
19108
|
+
this.fsw._addPathCloser(path33, closer);
|
|
19167
19109
|
return false;
|
|
19168
19110
|
} catch (error) {
|
|
19169
19111
|
if (this.fsw._handleError(error)) {
|
|
19170
19112
|
ready();
|
|
19171
|
-
return
|
|
19113
|
+
return path33;
|
|
19172
19114
|
}
|
|
19173
19115
|
}
|
|
19174
19116
|
}
|
|
@@ -19200,35 +19142,35 @@ function createPattern(matcher) {
|
|
|
19200
19142
|
if (matcher.path === string)
|
|
19201
19143
|
return true;
|
|
19202
19144
|
if (matcher.recursive) {
|
|
19203
|
-
const
|
|
19204
|
-
if (!
|
|
19145
|
+
const relative14 = sp2.relative(matcher.path, string);
|
|
19146
|
+
if (!relative14) {
|
|
19205
19147
|
return false;
|
|
19206
19148
|
}
|
|
19207
|
-
return !
|
|
19149
|
+
return !relative14.startsWith("..") && !sp2.isAbsolute(relative14);
|
|
19208
19150
|
}
|
|
19209
19151
|
return false;
|
|
19210
19152
|
};
|
|
19211
19153
|
}
|
|
19212
19154
|
return () => false;
|
|
19213
19155
|
}
|
|
19214
|
-
function normalizePath3(
|
|
19215
|
-
if (typeof
|
|
19156
|
+
function normalizePath3(path33) {
|
|
19157
|
+
if (typeof path33 !== "string")
|
|
19216
19158
|
throw new Error("string expected");
|
|
19217
|
-
|
|
19218
|
-
|
|
19159
|
+
path33 = sp2.normalize(path33);
|
|
19160
|
+
path33 = path33.replace(/\\/g, "/");
|
|
19219
19161
|
let prepend = false;
|
|
19220
|
-
if (
|
|
19162
|
+
if (path33.startsWith("//"))
|
|
19221
19163
|
prepend = true;
|
|
19222
|
-
|
|
19164
|
+
path33 = path33.replace(DOUBLE_SLASH_RE, "/");
|
|
19223
19165
|
if (prepend)
|
|
19224
|
-
|
|
19225
|
-
return
|
|
19166
|
+
path33 = "/" + path33;
|
|
19167
|
+
return path33;
|
|
19226
19168
|
}
|
|
19227
19169
|
function matchPatterns(patterns, testString, stats) {
|
|
19228
|
-
const
|
|
19170
|
+
const path33 = normalizePath3(testString);
|
|
19229
19171
|
for (let index = 0; index < patterns.length; index++) {
|
|
19230
19172
|
const pattern = patterns[index];
|
|
19231
|
-
if (pattern(
|
|
19173
|
+
if (pattern(path33, stats)) {
|
|
19232
19174
|
return true;
|
|
19233
19175
|
}
|
|
19234
19176
|
}
|
|
@@ -19266,19 +19208,19 @@ var toUnix = (string) => {
|
|
|
19266
19208
|
}
|
|
19267
19209
|
return str;
|
|
19268
19210
|
};
|
|
19269
|
-
var normalizePathToUnix = (
|
|
19270
|
-
var normalizeIgnored = (cwd = "") => (
|
|
19271
|
-
if (typeof
|
|
19272
|
-
return normalizePathToUnix(sp2.isAbsolute(
|
|
19211
|
+
var normalizePathToUnix = (path33) => toUnix(sp2.normalize(toUnix(path33)));
|
|
19212
|
+
var normalizeIgnored = (cwd = "") => (path33) => {
|
|
19213
|
+
if (typeof path33 === "string") {
|
|
19214
|
+
return normalizePathToUnix(sp2.isAbsolute(path33) ? path33 : sp2.join(cwd, path33));
|
|
19273
19215
|
} else {
|
|
19274
|
-
return
|
|
19216
|
+
return path33;
|
|
19275
19217
|
}
|
|
19276
19218
|
};
|
|
19277
|
-
var getAbsolutePath = (
|
|
19278
|
-
if (sp2.isAbsolute(
|
|
19279
|
-
return
|
|
19219
|
+
var getAbsolutePath = (path33, cwd) => {
|
|
19220
|
+
if (sp2.isAbsolute(path33)) {
|
|
19221
|
+
return path33;
|
|
19280
19222
|
}
|
|
19281
|
-
return sp2.join(cwd,
|
|
19223
|
+
return sp2.join(cwd, path33);
|
|
19282
19224
|
};
|
|
19283
19225
|
var EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
|
|
19284
19226
|
var DirEntry = class {
|
|
@@ -19343,10 +19285,10 @@ var WatchHelper = class {
|
|
|
19343
19285
|
dirParts;
|
|
19344
19286
|
followSymlinks;
|
|
19345
19287
|
statMethod;
|
|
19346
|
-
constructor(
|
|
19288
|
+
constructor(path33, follow, fsw) {
|
|
19347
19289
|
this.fsw = fsw;
|
|
19348
|
-
const watchPath =
|
|
19349
|
-
this.path =
|
|
19290
|
+
const watchPath = path33;
|
|
19291
|
+
this.path = path33 = path33.replace(REPLACER_RE, "");
|
|
19350
19292
|
this.watchPath = watchPath;
|
|
19351
19293
|
this.fullWatchPath = sp2.resolve(watchPath);
|
|
19352
19294
|
this.dirParts = [];
|
|
@@ -19486,20 +19428,20 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
19486
19428
|
this._closePromise = void 0;
|
|
19487
19429
|
let paths = unifyPaths(paths_);
|
|
19488
19430
|
if (cwd) {
|
|
19489
|
-
paths = paths.map((
|
|
19490
|
-
const absPath = getAbsolutePath(
|
|
19431
|
+
paths = paths.map((path33) => {
|
|
19432
|
+
const absPath = getAbsolutePath(path33, cwd);
|
|
19491
19433
|
return absPath;
|
|
19492
19434
|
});
|
|
19493
19435
|
}
|
|
19494
|
-
paths.forEach((
|
|
19495
|
-
this._removeIgnoredPath(
|
|
19436
|
+
paths.forEach((path33) => {
|
|
19437
|
+
this._removeIgnoredPath(path33);
|
|
19496
19438
|
});
|
|
19497
19439
|
this._userIgnored = void 0;
|
|
19498
19440
|
if (!this._readyCount)
|
|
19499
19441
|
this._readyCount = 0;
|
|
19500
19442
|
this._readyCount += paths.length;
|
|
19501
|
-
Promise.all(paths.map(async (
|
|
19502
|
-
const res = await this._nodeFsHandler._addToNodeFs(
|
|
19443
|
+
Promise.all(paths.map(async (path33) => {
|
|
19444
|
+
const res = await this._nodeFsHandler._addToNodeFs(path33, !_internal, void 0, 0, _origAdd);
|
|
19503
19445
|
if (res)
|
|
19504
19446
|
this._emitReady();
|
|
19505
19447
|
return res;
|
|
@@ -19521,17 +19463,17 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
19521
19463
|
return this;
|
|
19522
19464
|
const paths = unifyPaths(paths_);
|
|
19523
19465
|
const { cwd } = this.options;
|
|
19524
|
-
paths.forEach((
|
|
19525
|
-
if (!sp2.isAbsolute(
|
|
19466
|
+
paths.forEach((path33) => {
|
|
19467
|
+
if (!sp2.isAbsolute(path33) && !this._closers.has(path33)) {
|
|
19526
19468
|
if (cwd)
|
|
19527
|
-
|
|
19528
|
-
|
|
19469
|
+
path33 = sp2.join(cwd, path33);
|
|
19470
|
+
path33 = sp2.resolve(path33);
|
|
19529
19471
|
}
|
|
19530
|
-
this._closePath(
|
|
19531
|
-
this._addIgnoredPath(
|
|
19532
|
-
if (this._watched.has(
|
|
19472
|
+
this._closePath(path33);
|
|
19473
|
+
this._addIgnoredPath(path33);
|
|
19474
|
+
if (this._watched.has(path33)) {
|
|
19533
19475
|
this._addIgnoredPath({
|
|
19534
|
-
path:
|
|
19476
|
+
path: path33,
|
|
19535
19477
|
recursive: true
|
|
19536
19478
|
});
|
|
19537
19479
|
}
|
|
@@ -19595,38 +19537,38 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
19595
19537
|
* @param stats arguments to be passed with event
|
|
19596
19538
|
* @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
|
|
19597
19539
|
*/
|
|
19598
|
-
async _emit(event,
|
|
19540
|
+
async _emit(event, path33, stats) {
|
|
19599
19541
|
if (this.closed)
|
|
19600
19542
|
return;
|
|
19601
19543
|
const opts = this.options;
|
|
19602
19544
|
if (isWindows)
|
|
19603
|
-
|
|
19545
|
+
path33 = sp2.normalize(path33);
|
|
19604
19546
|
if (opts.cwd)
|
|
19605
|
-
|
|
19606
|
-
const args = [
|
|
19547
|
+
path33 = sp2.relative(opts.cwd, path33);
|
|
19548
|
+
const args = [path33];
|
|
19607
19549
|
if (stats != null)
|
|
19608
19550
|
args.push(stats);
|
|
19609
19551
|
const awf = opts.awaitWriteFinish;
|
|
19610
19552
|
let pw;
|
|
19611
|
-
if (awf && (pw = this._pendingWrites.get(
|
|
19553
|
+
if (awf && (pw = this._pendingWrites.get(path33))) {
|
|
19612
19554
|
pw.lastChange = /* @__PURE__ */ new Date();
|
|
19613
19555
|
return this;
|
|
19614
19556
|
}
|
|
19615
19557
|
if (opts.atomic) {
|
|
19616
19558
|
if (event === EVENTS.UNLINK) {
|
|
19617
|
-
this._pendingUnlinks.set(
|
|
19559
|
+
this._pendingUnlinks.set(path33, [event, ...args]);
|
|
19618
19560
|
setTimeout(() => {
|
|
19619
|
-
this._pendingUnlinks.forEach((entry,
|
|
19561
|
+
this._pendingUnlinks.forEach((entry, path34) => {
|
|
19620
19562
|
this.emit(...entry);
|
|
19621
19563
|
this.emit(EVENTS.ALL, ...entry);
|
|
19622
|
-
this._pendingUnlinks.delete(
|
|
19564
|
+
this._pendingUnlinks.delete(path34);
|
|
19623
19565
|
});
|
|
19624
19566
|
}, typeof opts.atomic === "number" ? opts.atomic : 100);
|
|
19625
19567
|
return this;
|
|
19626
19568
|
}
|
|
19627
|
-
if (event === EVENTS.ADD && this._pendingUnlinks.has(
|
|
19569
|
+
if (event === EVENTS.ADD && this._pendingUnlinks.has(path33)) {
|
|
19628
19570
|
event = EVENTS.CHANGE;
|
|
19629
|
-
this._pendingUnlinks.delete(
|
|
19571
|
+
this._pendingUnlinks.delete(path33);
|
|
19630
19572
|
}
|
|
19631
19573
|
}
|
|
19632
19574
|
if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
|
|
@@ -19644,16 +19586,16 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
19644
19586
|
this.emitWithAll(event, args);
|
|
19645
19587
|
}
|
|
19646
19588
|
};
|
|
19647
|
-
this._awaitWriteFinish(
|
|
19589
|
+
this._awaitWriteFinish(path33, awf.stabilityThreshold, event, awfEmit);
|
|
19648
19590
|
return this;
|
|
19649
19591
|
}
|
|
19650
19592
|
if (event === EVENTS.CHANGE) {
|
|
19651
|
-
const isThrottled = !this._throttle(EVENTS.CHANGE,
|
|
19593
|
+
const isThrottled = !this._throttle(EVENTS.CHANGE, path33, 50);
|
|
19652
19594
|
if (isThrottled)
|
|
19653
19595
|
return this;
|
|
19654
19596
|
}
|
|
19655
19597
|
if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
|
|
19656
|
-
const fullPath = opts.cwd ? sp2.join(opts.cwd,
|
|
19598
|
+
const fullPath = opts.cwd ? sp2.join(opts.cwd, path33) : path33;
|
|
19657
19599
|
let stats2;
|
|
19658
19600
|
try {
|
|
19659
19601
|
stats2 = await stat3(fullPath);
|
|
@@ -19684,23 +19626,23 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
19684
19626
|
* @param timeout duration of time to suppress duplicate actions
|
|
19685
19627
|
* @returns tracking object or false if action should be suppressed
|
|
19686
19628
|
*/
|
|
19687
|
-
_throttle(actionType,
|
|
19629
|
+
_throttle(actionType, path33, timeout) {
|
|
19688
19630
|
if (!this._throttled.has(actionType)) {
|
|
19689
19631
|
this._throttled.set(actionType, /* @__PURE__ */ new Map());
|
|
19690
19632
|
}
|
|
19691
19633
|
const action = this._throttled.get(actionType);
|
|
19692
19634
|
if (!action)
|
|
19693
19635
|
throw new Error("invalid throttle");
|
|
19694
|
-
const actionPath = action.get(
|
|
19636
|
+
const actionPath = action.get(path33);
|
|
19695
19637
|
if (actionPath) {
|
|
19696
19638
|
actionPath.count++;
|
|
19697
19639
|
return false;
|
|
19698
19640
|
}
|
|
19699
19641
|
let timeoutObject;
|
|
19700
19642
|
const clear = () => {
|
|
19701
|
-
const item = action.get(
|
|
19643
|
+
const item = action.get(path33);
|
|
19702
19644
|
const count = item ? item.count : 0;
|
|
19703
|
-
action.delete(
|
|
19645
|
+
action.delete(path33);
|
|
19704
19646
|
clearTimeout(timeoutObject);
|
|
19705
19647
|
if (item)
|
|
19706
19648
|
clearTimeout(item.timeoutObject);
|
|
@@ -19708,7 +19650,7 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
19708
19650
|
};
|
|
19709
19651
|
timeoutObject = setTimeout(clear, timeout);
|
|
19710
19652
|
const thr = { timeoutObject, clear, count: 0 };
|
|
19711
|
-
action.set(
|
|
19653
|
+
action.set(path33, thr);
|
|
19712
19654
|
return thr;
|
|
19713
19655
|
}
|
|
19714
19656
|
_incrReadyCount() {
|
|
@@ -19722,44 +19664,44 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
19722
19664
|
* @param event
|
|
19723
19665
|
* @param awfEmit Callback to be called when ready for event to be emitted.
|
|
19724
19666
|
*/
|
|
19725
|
-
_awaitWriteFinish(
|
|
19667
|
+
_awaitWriteFinish(path33, threshold, event, awfEmit) {
|
|
19726
19668
|
const awf = this.options.awaitWriteFinish;
|
|
19727
19669
|
if (typeof awf !== "object")
|
|
19728
19670
|
return;
|
|
19729
19671
|
const pollInterval = awf.pollInterval;
|
|
19730
19672
|
let timeoutHandler;
|
|
19731
|
-
let fullPath =
|
|
19732
|
-
if (this.options.cwd && !sp2.isAbsolute(
|
|
19733
|
-
fullPath = sp2.join(this.options.cwd,
|
|
19673
|
+
let fullPath = path33;
|
|
19674
|
+
if (this.options.cwd && !sp2.isAbsolute(path33)) {
|
|
19675
|
+
fullPath = sp2.join(this.options.cwd, path33);
|
|
19734
19676
|
}
|
|
19735
19677
|
const now2 = /* @__PURE__ */ new Date();
|
|
19736
19678
|
const writes = this._pendingWrites;
|
|
19737
19679
|
function awaitWriteFinishFn(prevStat) {
|
|
19738
19680
|
statcb(fullPath, (err, curStat) => {
|
|
19739
|
-
if (err || !writes.has(
|
|
19681
|
+
if (err || !writes.has(path33)) {
|
|
19740
19682
|
if (err && err.code !== "ENOENT")
|
|
19741
19683
|
awfEmit(err);
|
|
19742
19684
|
return;
|
|
19743
19685
|
}
|
|
19744
19686
|
const now3 = Number(/* @__PURE__ */ new Date());
|
|
19745
19687
|
if (prevStat && curStat.size !== prevStat.size) {
|
|
19746
|
-
writes.get(
|
|
19688
|
+
writes.get(path33).lastChange = now3;
|
|
19747
19689
|
}
|
|
19748
|
-
const pw = writes.get(
|
|
19690
|
+
const pw = writes.get(path33);
|
|
19749
19691
|
const df = now3 - pw.lastChange;
|
|
19750
19692
|
if (df >= threshold) {
|
|
19751
|
-
writes.delete(
|
|
19693
|
+
writes.delete(path33);
|
|
19752
19694
|
awfEmit(void 0, curStat);
|
|
19753
19695
|
} else {
|
|
19754
19696
|
timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
|
|
19755
19697
|
}
|
|
19756
19698
|
});
|
|
19757
19699
|
}
|
|
19758
|
-
if (!writes.has(
|
|
19759
|
-
writes.set(
|
|
19700
|
+
if (!writes.has(path33)) {
|
|
19701
|
+
writes.set(path33, {
|
|
19760
19702
|
lastChange: now2,
|
|
19761
19703
|
cancelWait: () => {
|
|
19762
|
-
writes.delete(
|
|
19704
|
+
writes.delete(path33);
|
|
19763
19705
|
clearTimeout(timeoutHandler);
|
|
19764
19706
|
return event;
|
|
19765
19707
|
}
|
|
@@ -19770,8 +19712,8 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
19770
19712
|
/**
|
|
19771
19713
|
* Determines whether user has asked to ignore this path.
|
|
19772
19714
|
*/
|
|
19773
|
-
_isIgnored(
|
|
19774
|
-
if (this.options.atomic && DOT_RE.test(
|
|
19715
|
+
_isIgnored(path33, stats) {
|
|
19716
|
+
if (this.options.atomic && DOT_RE.test(path33))
|
|
19775
19717
|
return true;
|
|
19776
19718
|
if (!this._userIgnored) {
|
|
19777
19719
|
const { cwd } = this.options;
|
|
@@ -19781,17 +19723,17 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
19781
19723
|
const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
|
|
19782
19724
|
this._userIgnored = anymatch(list, void 0);
|
|
19783
19725
|
}
|
|
19784
|
-
return this._userIgnored(
|
|
19726
|
+
return this._userIgnored(path33, stats);
|
|
19785
19727
|
}
|
|
19786
|
-
_isntIgnored(
|
|
19787
|
-
return !this._isIgnored(
|
|
19728
|
+
_isntIgnored(path33, stat5) {
|
|
19729
|
+
return !this._isIgnored(path33, stat5);
|
|
19788
19730
|
}
|
|
19789
19731
|
/**
|
|
19790
19732
|
* Provides a set of common helpers and properties relating to symlink handling.
|
|
19791
19733
|
* @param path file or directory pattern being watched
|
|
19792
19734
|
*/
|
|
19793
|
-
_getWatchHelpers(
|
|
19794
|
-
return new WatchHelper(
|
|
19735
|
+
_getWatchHelpers(path33) {
|
|
19736
|
+
return new WatchHelper(path33, this.options.followSymlinks, this);
|
|
19795
19737
|
}
|
|
19796
19738
|
// Directory helpers
|
|
19797
19739
|
// -----------------
|
|
@@ -19823,63 +19765,63 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
19823
19765
|
* @param item base path of item/directory
|
|
19824
19766
|
*/
|
|
19825
19767
|
_remove(directory, item, isDirectory) {
|
|
19826
|
-
const
|
|
19827
|
-
const fullPath = sp2.resolve(
|
|
19828
|
-
isDirectory = isDirectory != null ? isDirectory : this._watched.has(
|
|
19829
|
-
if (!this._throttle("remove",
|
|
19768
|
+
const path33 = sp2.join(directory, item);
|
|
19769
|
+
const fullPath = sp2.resolve(path33);
|
|
19770
|
+
isDirectory = isDirectory != null ? isDirectory : this._watched.has(path33) || this._watched.has(fullPath);
|
|
19771
|
+
if (!this._throttle("remove", path33, 100))
|
|
19830
19772
|
return;
|
|
19831
19773
|
if (!isDirectory && this._watched.size === 1) {
|
|
19832
19774
|
this.add(directory, item, true);
|
|
19833
19775
|
}
|
|
19834
|
-
const wp = this._getWatchedDir(
|
|
19776
|
+
const wp = this._getWatchedDir(path33);
|
|
19835
19777
|
const nestedDirectoryChildren = wp.getChildren();
|
|
19836
|
-
nestedDirectoryChildren.forEach((nested) => this._remove(
|
|
19778
|
+
nestedDirectoryChildren.forEach((nested) => this._remove(path33, nested));
|
|
19837
19779
|
const parent = this._getWatchedDir(directory);
|
|
19838
19780
|
const wasTracked = parent.has(item);
|
|
19839
19781
|
parent.remove(item);
|
|
19840
19782
|
if (this._symlinkPaths.has(fullPath)) {
|
|
19841
19783
|
this._symlinkPaths.delete(fullPath);
|
|
19842
19784
|
}
|
|
19843
|
-
let relPath =
|
|
19785
|
+
let relPath = path33;
|
|
19844
19786
|
if (this.options.cwd)
|
|
19845
|
-
relPath = sp2.relative(this.options.cwd,
|
|
19787
|
+
relPath = sp2.relative(this.options.cwd, path33);
|
|
19846
19788
|
if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
|
|
19847
19789
|
const event = this._pendingWrites.get(relPath).cancelWait();
|
|
19848
19790
|
if (event === EVENTS.ADD)
|
|
19849
19791
|
return;
|
|
19850
19792
|
}
|
|
19851
|
-
this._watched.delete(
|
|
19793
|
+
this._watched.delete(path33);
|
|
19852
19794
|
this._watched.delete(fullPath);
|
|
19853
19795
|
const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
|
|
19854
|
-
if (wasTracked && !this._isIgnored(
|
|
19855
|
-
this._emit(eventName,
|
|
19856
|
-
this._closePath(
|
|
19796
|
+
if (wasTracked && !this._isIgnored(path33))
|
|
19797
|
+
this._emit(eventName, path33);
|
|
19798
|
+
this._closePath(path33);
|
|
19857
19799
|
}
|
|
19858
19800
|
/**
|
|
19859
19801
|
* Closes all watchers for a path
|
|
19860
19802
|
*/
|
|
19861
|
-
_closePath(
|
|
19862
|
-
this._closeFile(
|
|
19863
|
-
const dir = sp2.dirname(
|
|
19864
|
-
this._getWatchedDir(dir).remove(sp2.basename(
|
|
19803
|
+
_closePath(path33) {
|
|
19804
|
+
this._closeFile(path33);
|
|
19805
|
+
const dir = sp2.dirname(path33);
|
|
19806
|
+
this._getWatchedDir(dir).remove(sp2.basename(path33));
|
|
19865
19807
|
}
|
|
19866
19808
|
/**
|
|
19867
19809
|
* Closes only file-specific watchers
|
|
19868
19810
|
*/
|
|
19869
|
-
_closeFile(
|
|
19870
|
-
const closers = this._closers.get(
|
|
19811
|
+
_closeFile(path33) {
|
|
19812
|
+
const closers = this._closers.get(path33);
|
|
19871
19813
|
if (!closers)
|
|
19872
19814
|
return;
|
|
19873
19815
|
closers.forEach((closer) => closer());
|
|
19874
|
-
this._closers.delete(
|
|
19816
|
+
this._closers.delete(path33);
|
|
19875
19817
|
}
|
|
19876
|
-
_addPathCloser(
|
|
19818
|
+
_addPathCloser(path33, closer) {
|
|
19877
19819
|
if (!closer)
|
|
19878
19820
|
return;
|
|
19879
|
-
let list = this._closers.get(
|
|
19821
|
+
let list = this._closers.get(path33);
|
|
19880
19822
|
if (!list) {
|
|
19881
19823
|
list = [];
|
|
19882
|
-
this._closers.set(
|
|
19824
|
+
this._closers.set(path33, list);
|
|
19883
19825
|
}
|
|
19884
19826
|
list.push(closer);
|
|
19885
19827
|
}
|
|
@@ -19909,12 +19851,291 @@ function watch(paths, options = {}) {
|
|
|
19909
19851
|
var chokidar_default = { watch, FSWatcher };
|
|
19910
19852
|
|
|
19911
19853
|
// src/watcher/file-watcher.ts
|
|
19854
|
+
import * as path28 from "path";
|
|
19855
|
+
|
|
19856
|
+
// src/watcher/native-recursive-watcher.ts
|
|
19857
|
+
import { watch as watch2 } from "fs";
|
|
19912
19858
|
import * as path26 from "path";
|
|
19859
|
+
var NativeRecursiveWatcher = class {
|
|
19860
|
+
constructor(root, onChange, options = {}) {
|
|
19861
|
+
this.root = root;
|
|
19862
|
+
this.onChange = onChange;
|
|
19863
|
+
this.watchFactory = options.watchFactory ?? this.defaultWatchFactory;
|
|
19864
|
+
this.onError = options.onError;
|
|
19865
|
+
}
|
|
19866
|
+
root;
|
|
19867
|
+
onChange;
|
|
19868
|
+
watcher = null;
|
|
19869
|
+
listenerToken = 0;
|
|
19870
|
+
watchFactory;
|
|
19871
|
+
onError;
|
|
19872
|
+
start() {
|
|
19873
|
+
if (this.watcher) return;
|
|
19874
|
+
const token = ++this.listenerToken;
|
|
19875
|
+
const listener = (_eventType, filename) => {
|
|
19876
|
+
if (this.watcher === null || this.listenerToken !== token) return;
|
|
19877
|
+
const absolutePath = this.toAbsolutePath(filename);
|
|
19878
|
+
const nextResult = this.onChange(absolutePath);
|
|
19879
|
+
if (nextResult instanceof Promise) {
|
|
19880
|
+
void nextResult.catch((error) => {
|
|
19881
|
+
console.error("[codebase-index] Error handling native watcher event:", error);
|
|
19882
|
+
});
|
|
19883
|
+
}
|
|
19884
|
+
};
|
|
19885
|
+
const watcher = this.watchFactory(this.root, listener, {
|
|
19886
|
+
persistent: true,
|
|
19887
|
+
recursive: true
|
|
19888
|
+
});
|
|
19889
|
+
watcher.on?.("error", (error) => {
|
|
19890
|
+
if (this.watcher === watcher && this.listenerToken === token) {
|
|
19891
|
+
this.onError?.(error);
|
|
19892
|
+
}
|
|
19893
|
+
});
|
|
19894
|
+
this.watcher = watcher;
|
|
19895
|
+
}
|
|
19896
|
+
async stop() {
|
|
19897
|
+
const watcher = this.watcher;
|
|
19898
|
+
this.watcher = null;
|
|
19899
|
+
this.listenerToken += 1;
|
|
19900
|
+
if (!watcher) return;
|
|
19901
|
+
await watcher.close();
|
|
19902
|
+
}
|
|
19903
|
+
toAbsolutePath(filename) {
|
|
19904
|
+
if (filename == null) return null;
|
|
19905
|
+
const normalizedFilename = typeof filename === "string" ? filename : filename.toString();
|
|
19906
|
+
const absolutePath = path26.resolve(this.root, normalizedFilename);
|
|
19907
|
+
const relativePath = path26.relative(this.root, absolutePath);
|
|
19908
|
+
const outsideRoot = relativePath === ".." || relativePath.startsWith(`..${path26.sep}`) || path26.isAbsolute(relativePath);
|
|
19909
|
+
return outsideRoot ? null : absolutePath;
|
|
19910
|
+
}
|
|
19911
|
+
defaultWatchFactory = (root, listener, options) => watch2(root, options, listener);
|
|
19912
|
+
};
|
|
19913
|
+
|
|
19914
|
+
// src/watcher/snapshot.ts
|
|
19915
|
+
import * as fsPromises4 from "fs/promises";
|
|
19916
|
+
import * as path27 from "path";
|
|
19917
|
+
async function buildFileSnapshotScan(projectRoot, config, configPaths = []) {
|
|
19918
|
+
const normalizedProjectRoot = path27.resolve(projectRoot);
|
|
19919
|
+
const ignoreFilter = createIgnoreFilter(normalizedProjectRoot);
|
|
19920
|
+
const includePatterns = [...config.include, ...config.additionalInclude ?? []];
|
|
19921
|
+
const maxDepth = config.indexing?.maxDepth ?? -1;
|
|
19922
|
+
const snapshot = /* @__PURE__ */ new Map();
|
|
19923
|
+
const unreadablePrefixes = /* @__PURE__ */ new Set();
|
|
19924
|
+
const includeFile = async (filePath) => {
|
|
19925
|
+
const normalizedPath3 = path27.resolve(filePath);
|
|
19926
|
+
if (!shouldIncludeFile(normalizedPath3, normalizedProjectRoot, includePatterns, config.exclude, ignoreFilter)) return;
|
|
19927
|
+
const stat5 = await readStatIfFile(normalizedPath3, unreadablePrefixes);
|
|
19928
|
+
if (stat5) snapshot.set(normalizedPath3, { size: stat5.size, mtimeMs: stat5.mtimeMs });
|
|
19929
|
+
};
|
|
19930
|
+
const walk = async (directoryPath, depth) => {
|
|
19931
|
+
let entries;
|
|
19932
|
+
try {
|
|
19933
|
+
entries = await fsPromises4.readdir(directoryPath, { withFileTypes: true });
|
|
19934
|
+
} catch (error) {
|
|
19935
|
+
if (isMissingFsError(error)) return;
|
|
19936
|
+
if (isPermissionFsError(error)) {
|
|
19937
|
+
unreadablePrefixes.add(path27.resolve(directoryPath));
|
|
19938
|
+
return;
|
|
19939
|
+
}
|
|
19940
|
+
throw error;
|
|
19941
|
+
}
|
|
19942
|
+
for (const entry of entries) {
|
|
19943
|
+
const fullPath = path27.join(directoryPath, entry.name);
|
|
19944
|
+
const relativePath = path27.relative(normalizedProjectRoot, fullPath);
|
|
19945
|
+
if (entry.isDirectory()) {
|
|
19946
|
+
if (hasFilteredPathSegment(relativePath, path27.sep) || isRestrictedDirectory(relativePath, path27.sep)) continue;
|
|
19947
|
+
if (ignoreFilter.ignores(relativePath)) continue;
|
|
19948
|
+
if (maxDepth === -1 || depth < maxDepth) await walk(fullPath, depth + 1);
|
|
19949
|
+
} else if (entry.isFile()) {
|
|
19950
|
+
await includeFile(fullPath);
|
|
19951
|
+
}
|
|
19952
|
+
}
|
|
19953
|
+
};
|
|
19954
|
+
await walk(normalizedProjectRoot, 0);
|
|
19955
|
+
await includeExplicitConfigPaths(snapshot, unreadablePrefixes, configPaths);
|
|
19956
|
+
return { entries: snapshot, unreadablePrefixes };
|
|
19957
|
+
}
|
|
19958
|
+
async function buildFileSnapshotForPathScan(projectRoot, config, configPaths, targetPath) {
|
|
19959
|
+
const normalizedProjectRoot = path27.resolve(projectRoot);
|
|
19960
|
+
const normalizedTargetPath = path27.resolve(targetPath);
|
|
19961
|
+
if (!isWithinPath(normalizedProjectRoot, normalizedTargetPath)) {
|
|
19962
|
+
return { entries: /* @__PURE__ */ new Map(), unreadablePrefixes: /* @__PURE__ */ new Set() };
|
|
19963
|
+
}
|
|
19964
|
+
const ignoreFilter = createIgnoreFilter(normalizedProjectRoot);
|
|
19965
|
+
const includePatterns = [...config.include, ...config.additionalInclude ?? []];
|
|
19966
|
+
const maxDepth = config.indexing?.maxDepth ?? -1;
|
|
19967
|
+
const explicitConfigPaths = new Set(configPaths.map((configPath) => path27.resolve(configPath)));
|
|
19968
|
+
const snapshot = /* @__PURE__ */ new Map();
|
|
19969
|
+
const unreadablePrefixes = /* @__PURE__ */ new Set();
|
|
19970
|
+
const includeFile = async (filePath) => {
|
|
19971
|
+
const normalizedPath3 = path27.resolve(filePath);
|
|
19972
|
+
if (!explicitConfigPaths.has(normalizedPath3) && !shouldIncludeFile(
|
|
19973
|
+
normalizedPath3,
|
|
19974
|
+
normalizedProjectRoot,
|
|
19975
|
+
includePatterns,
|
|
19976
|
+
config.exclude,
|
|
19977
|
+
ignoreFilter
|
|
19978
|
+
)) return;
|
|
19979
|
+
const stat5 = await readStatIfFile(normalizedPath3, unreadablePrefixes);
|
|
19980
|
+
if (stat5) snapshot.set(normalizedPath3, { size: stat5.size, mtimeMs: stat5.mtimeMs });
|
|
19981
|
+
};
|
|
19982
|
+
const walk = async (directoryPath, depth) => {
|
|
19983
|
+
let entries;
|
|
19984
|
+
try {
|
|
19985
|
+
entries = await fsPromises4.readdir(directoryPath, { withFileTypes: true });
|
|
19986
|
+
} catch (error) {
|
|
19987
|
+
if (isMissingFsError(error)) return;
|
|
19988
|
+
if (isPermissionFsError(error)) {
|
|
19989
|
+
unreadablePrefixes.add(path27.resolve(directoryPath));
|
|
19990
|
+
return;
|
|
19991
|
+
}
|
|
19992
|
+
throw error;
|
|
19993
|
+
}
|
|
19994
|
+
for (const entry of entries) {
|
|
19995
|
+
const fullPath = path27.join(directoryPath, entry.name);
|
|
19996
|
+
const relativePath = path27.relative(normalizedProjectRoot, fullPath);
|
|
19997
|
+
if (entry.isDirectory()) {
|
|
19998
|
+
if (hasFilteredPathSegment(relativePath, path27.sep) || isRestrictedDirectory(relativePath, path27.sep)) continue;
|
|
19999
|
+
if (ignoreFilter.ignores(relativePath)) continue;
|
|
20000
|
+
if (maxDepth === -1 || depth < maxDepth) await walk(fullPath, depth + 1);
|
|
20001
|
+
} else if (entry.isFile()) {
|
|
20002
|
+
await includeFile(fullPath);
|
|
20003
|
+
}
|
|
20004
|
+
}
|
|
20005
|
+
};
|
|
20006
|
+
const targetStat = await readStatIfFile(normalizedTargetPath, unreadablePrefixes);
|
|
20007
|
+
if (targetStat) await includeFile(normalizedTargetPath);
|
|
20008
|
+
else await walk(normalizedTargetPath, 0);
|
|
20009
|
+
await includeExplicitConfigPathsInPath(snapshot, unreadablePrefixes, configPaths, normalizedTargetPath);
|
|
20010
|
+
return { entries: snapshot, unreadablePrefixes };
|
|
20011
|
+
}
|
|
20012
|
+
function completeFileSnapshot(previous, scan) {
|
|
20013
|
+
const completed = new Map(scan.entries);
|
|
20014
|
+
for (const unreadablePrefix of scan.unreadablePrefixes) {
|
|
20015
|
+
for (const [entryPath, entry] of previous) {
|
|
20016
|
+
if (isWithinPath(unreadablePrefix, entryPath) && !completed.has(entryPath)) completed.set(entryPath, entry);
|
|
20017
|
+
}
|
|
20018
|
+
}
|
|
20019
|
+
return completed;
|
|
20020
|
+
}
|
|
20021
|
+
async function includeExplicitConfigPaths(snapshot, unreadablePrefixes, configPaths) {
|
|
20022
|
+
for (const configPath of [...new Set(configPaths.map((value) => path27.resolve(value)))]) {
|
|
20023
|
+
if (snapshot.has(configPath)) continue;
|
|
20024
|
+
const stat5 = await readStatIfFile(configPath, unreadablePrefixes);
|
|
20025
|
+
if (stat5) snapshot.set(configPath, { size: stat5.size, mtimeMs: stat5.mtimeMs });
|
|
20026
|
+
}
|
|
20027
|
+
}
|
|
20028
|
+
async function includeExplicitConfigPathsInPath(snapshot, unreadablePrefixes, configPaths, targetPath) {
|
|
20029
|
+
await includeExplicitConfigPaths(
|
|
20030
|
+
snapshot,
|
|
20031
|
+
unreadablePrefixes,
|
|
20032
|
+
configPaths.filter((configPath) => isWithinPath(targetPath, path27.resolve(configPath)))
|
|
20033
|
+
);
|
|
20034
|
+
}
|
|
20035
|
+
function isWithinPath(parentPath, childPath) {
|
|
20036
|
+
const relativePath = path27.relative(parentPath, childPath);
|
|
20037
|
+
return relativePath === "" || !relativePath.startsWith(`..${path27.sep}`) && relativePath !== ".." && !path27.isAbsolute(relativePath);
|
|
20038
|
+
}
|
|
20039
|
+
async function readStatIfFile(filePath, unreadablePrefixes) {
|
|
20040
|
+
try {
|
|
20041
|
+
const stat5 = await fsPromises4.stat(filePath);
|
|
20042
|
+
return stat5.isFile() ? stat5 : null;
|
|
20043
|
+
} catch (error) {
|
|
20044
|
+
if (isMissingFsError(error)) return null;
|
|
20045
|
+
if (isPermissionFsError(error)) {
|
|
20046
|
+
unreadablePrefixes.add(path27.resolve(filePath));
|
|
20047
|
+
return null;
|
|
20048
|
+
}
|
|
20049
|
+
throw error;
|
|
20050
|
+
}
|
|
20051
|
+
}
|
|
20052
|
+
function isMissingFsError(error) {
|
|
20053
|
+
return error instanceof Error && ["ENOENT", "ENOTDIR"].includes(error.code ?? "");
|
|
20054
|
+
}
|
|
20055
|
+
function isPermissionFsError(error) {
|
|
20056
|
+
return error instanceof Error && ["EACCES", "EPERM"].includes(error.code ?? "");
|
|
20057
|
+
}
|
|
20058
|
+
var diffTypeOrder = { add: 0, change: 1, unlink: 2 };
|
|
20059
|
+
function diffFileSnapshots(previous, current, forcedChanges = /* @__PURE__ */ new Set()) {
|
|
20060
|
+
const changes = [];
|
|
20061
|
+
for (const [filePath, previousEntry] of previous) {
|
|
20062
|
+
const currentEntry = current.get(filePath);
|
|
20063
|
+
if (!currentEntry) changes.push({ type: "unlink", path: filePath });
|
|
20064
|
+
else if (forcedChanges.has(filePath) || currentEntry.size !== previousEntry.size || currentEntry.mtimeMs !== previousEntry.mtimeMs) {
|
|
20065
|
+
changes.push({ type: "change", path: filePath });
|
|
20066
|
+
}
|
|
20067
|
+
}
|
|
20068
|
+
for (const [filePath] of current) {
|
|
20069
|
+
if (!previous.has(filePath)) changes.push({ type: "add", path: filePath });
|
|
20070
|
+
}
|
|
20071
|
+
return changes.sort((left, right) => left.path.localeCompare(right.path) || diffTypeOrder[left.type] - diffTypeOrder[right.type]);
|
|
20072
|
+
}
|
|
20073
|
+
|
|
20074
|
+
// src/watcher/snapshot-reconciler.ts
|
|
20075
|
+
var FileSnapshotReconciler = class {
|
|
20076
|
+
constructor(projectRoot, config, configPaths) {
|
|
20077
|
+
this.projectRoot = projectRoot;
|
|
20078
|
+
this.config = config;
|
|
20079
|
+
this.configPaths = configPaths;
|
|
20080
|
+
}
|
|
20081
|
+
projectRoot;
|
|
20082
|
+
config;
|
|
20083
|
+
configPaths;
|
|
20084
|
+
snapshot = null;
|
|
20085
|
+
reconciliationTail = Promise.resolve();
|
|
20086
|
+
async initialize() {
|
|
20087
|
+
this.snapshot = (await buildFileSnapshotScan(this.projectRoot, this.config, this.configPaths)).entries;
|
|
20088
|
+
}
|
|
20089
|
+
async reconcile(invalidations = []) {
|
|
20090
|
+
if (this.snapshot === null) {
|
|
20091
|
+
throw new Error("FileSnapshotReconciler is not initialized. Call initialize() before reconcile().");
|
|
20092
|
+
}
|
|
20093
|
+
const reconciliation = this.reconciliationTail.then(async () => {
|
|
20094
|
+
const previousSnapshot = this.snapshot;
|
|
20095
|
+
if (previousSnapshot === null) {
|
|
20096
|
+
throw new Error("FileSnapshotReconciler is not initialized. Call initialize() before reconcile().");
|
|
20097
|
+
}
|
|
20098
|
+
const normalizedInvalidations = invalidations.map((invalidation) => typeof invalidation === "string" || invalidation === null ? { path: invalidation, forceChange: false } : { path: invalidation.path, forceChange: invalidation.forceChange === true });
|
|
20099
|
+
const scopedPaths = normalizedInvalidations.map((invalidation) => invalidation.path).filter((filePath) => filePath !== null);
|
|
20100
|
+
const scan = scopedPaths.length === 0 || scopedPaths.length !== normalizedInvalidations.length ? await buildFileSnapshotScan(this.projectRoot, this.config, this.configPaths) : await this.reconcilePaths(previousSnapshot, scopedPaths);
|
|
20101
|
+
const nextSnapshot = completeFileSnapshot(previousSnapshot, scan);
|
|
20102
|
+
const forcedChanges = new Set(normalizedInvalidations.filter((invalidation) => invalidation.path !== null && invalidation.forceChange).map((invalidation) => invalidation.path));
|
|
20103
|
+
const changes = diffFileSnapshots(previousSnapshot, nextSnapshot, forcedChanges);
|
|
20104
|
+
this.snapshot = nextSnapshot;
|
|
20105
|
+
return changes;
|
|
20106
|
+
});
|
|
20107
|
+
this.reconciliationTail = reconciliation.then(() => void 0, () => void 0);
|
|
20108
|
+
return reconciliation;
|
|
20109
|
+
}
|
|
20110
|
+
async reconcilePaths(previousSnapshot, invalidatedPaths) {
|
|
20111
|
+
const scopes = this.getScopes(invalidatedPaths);
|
|
20112
|
+
const entries = new Map(previousSnapshot);
|
|
20113
|
+
const unreadablePrefixes = /* @__PURE__ */ new Set();
|
|
20114
|
+
for (const scope of scopes) {
|
|
20115
|
+
for (const previousPath of entries.keys()) {
|
|
20116
|
+
if (isWithinPath(scope, previousPath)) entries.delete(previousPath);
|
|
20117
|
+
}
|
|
20118
|
+
const scopedScan = await buildFileSnapshotForPathScan(this.projectRoot, this.config, this.configPaths, scope);
|
|
20119
|
+
for (const [filePath, entry] of scopedScan.entries) entries.set(filePath, entry);
|
|
20120
|
+
for (const unreadablePrefix of scopedScan.unreadablePrefixes) unreadablePrefixes.add(unreadablePrefix);
|
|
20121
|
+
}
|
|
20122
|
+
return { entries, unreadablePrefixes };
|
|
20123
|
+
}
|
|
20124
|
+
getScopes(invalidatedPaths) {
|
|
20125
|
+
const uniquePaths = [...new Set(invalidatedPaths)].sort((left, right) => left.length - right.length);
|
|
20126
|
+
return uniquePaths.filter((candidate, index) => !uniquePaths.slice(0, index).some(
|
|
20127
|
+
(ancestor) => isWithinPath(ancestor, candidate)
|
|
20128
|
+
));
|
|
20129
|
+
}
|
|
20130
|
+
};
|
|
20131
|
+
|
|
20132
|
+
// src/watcher/file-watcher.ts
|
|
19913
20133
|
var FileWatcher = class {
|
|
19914
20134
|
watcher = null;
|
|
19915
20135
|
projectRoot;
|
|
19916
20136
|
config;
|
|
19917
20137
|
configPath;
|
|
20138
|
+
backend;
|
|
19918
20139
|
projectConfigPaths;
|
|
19919
20140
|
pendingChanges = /* @__PURE__ */ new Map();
|
|
19920
20141
|
debounceTimer = null;
|
|
@@ -19924,44 +20145,74 @@ var FileWatcher = class {
|
|
|
19924
20145
|
resolveReady = null;
|
|
19925
20146
|
pollingFallbackAttempted = false;
|
|
19926
20147
|
pendingClose = null;
|
|
20148
|
+
startupReadySignals = 1;
|
|
20149
|
+
nativeWatcher = null;
|
|
20150
|
+
nativeReconciler = null;
|
|
20151
|
+
nativeSetupGeneration = 0;
|
|
20152
|
+
nativeStarting = false;
|
|
20153
|
+
nativeInitializing = false;
|
|
20154
|
+
nativeReconcileTimer = null;
|
|
20155
|
+
nativeInvalidatedPaths = /* @__PURE__ */ new Map();
|
|
20156
|
+
configPathStates = /* @__PURE__ */ new Map();
|
|
19927
20157
|
constructor(projectRoot, config, host, options = {}) {
|
|
19928
20158
|
this.projectRoot = projectRoot;
|
|
19929
20159
|
this.config = config;
|
|
20160
|
+
this.backend = options.backend ?? "auto";
|
|
19930
20161
|
this.configPath = options.configPath;
|
|
19931
20162
|
this.projectConfigPaths = options.configPath ? [options.configPath] : getProjectConfigCandidatePaths(projectRoot, host);
|
|
19932
20163
|
}
|
|
19933
20164
|
start(handler) {
|
|
19934
|
-
if (this.watcher) {
|
|
20165
|
+
if (this.watcher || this.nativeWatcher || this.nativeStarting) {
|
|
19935
20166
|
return;
|
|
19936
20167
|
}
|
|
19937
20168
|
this.onChanges = handler;
|
|
19938
20169
|
this.pollingFallbackAttempted = false;
|
|
19939
20170
|
this.resetReady();
|
|
20171
|
+
if (this.shouldUseNativeWatcher()) {
|
|
20172
|
+
if (this.hasExternalConfigWatchTarget()) {
|
|
20173
|
+
this.setStartupReadySignals(2);
|
|
20174
|
+
this.startExternalConfigWatcher();
|
|
20175
|
+
}
|
|
20176
|
+
this.nativeStarting = true;
|
|
20177
|
+
void this.createNativeWatcher();
|
|
20178
|
+
return;
|
|
20179
|
+
}
|
|
19940
20180
|
this.createWatcher();
|
|
19941
20181
|
}
|
|
19942
20182
|
resetReady() {
|
|
19943
|
-
this.readyPromise = new Promise((
|
|
19944
|
-
this.resolveReady =
|
|
20183
|
+
this.readyPromise = new Promise((resolve20) => {
|
|
20184
|
+
this.resolveReady = resolve20;
|
|
19945
20185
|
});
|
|
20186
|
+
this.startupReadySignals = 1;
|
|
19946
20187
|
}
|
|
19947
|
-
|
|
19948
|
-
|
|
19949
|
-
|
|
19950
|
-
if (this.configPath) {
|
|
19951
|
-
watchTargets = [this.projectRoot, this.configPath];
|
|
19952
|
-
} else {
|
|
19953
|
-
const externalConfigTargets = this.projectConfigPaths.filter((projectConfigPath) => {
|
|
19954
|
-
const relativeConfigPath = path26.relative(this.projectRoot, projectConfigPath);
|
|
19955
|
-
return this.isOutsideProjectPath(relativeConfigPath);
|
|
19956
|
-
}).map((projectConfigPath) => existsSync15(projectConfigPath) ? projectConfigPath : this.getNearestExistingDirectory(path26.dirname(projectConfigPath)));
|
|
19957
|
-
const uniqueExternalConfigTargets = [...new Set(externalConfigTargets)];
|
|
19958
|
-
if (uniqueExternalConfigTargets.length > 0) {
|
|
19959
|
-
watchTargets = [this.projectRoot, ...uniqueExternalConfigTargets];
|
|
19960
|
-
}
|
|
20188
|
+
setStartupReadySignals(expectedSignals) {
|
|
20189
|
+
if (!this.readyPromise) {
|
|
20190
|
+
return;
|
|
19961
20191
|
}
|
|
20192
|
+
this.startupReadySignals = Math.max(0, expectedSignals);
|
|
20193
|
+
}
|
|
20194
|
+
reportStartupReadySignal() {
|
|
20195
|
+
if (!this.readyPromise || !this.resolveReady) {
|
|
20196
|
+
return;
|
|
20197
|
+
}
|
|
20198
|
+
if (this.startupReadySignals <= 0) {
|
|
20199
|
+
return;
|
|
20200
|
+
}
|
|
20201
|
+
this.startupReadySignals -= 1;
|
|
20202
|
+
if (this.startupReadySignals !== 0) {
|
|
20203
|
+
return;
|
|
20204
|
+
}
|
|
20205
|
+
this.resolveReady();
|
|
20206
|
+
this.resolveReady = null;
|
|
20207
|
+
}
|
|
20208
|
+
createWatcher(watchTargets, usePolling = false, reportsStartupReady = true) {
|
|
20209
|
+
let reportedStartupReady = false;
|
|
20210
|
+
this.configPathStates = this.getConfigPathStates();
|
|
20211
|
+
const ignoreFilter = createIgnoreFilter(this.projectRoot);
|
|
20212
|
+
const resolvedWatchTargets = watchTargets ?? this.getFullChokidarWatchTargets();
|
|
19962
20213
|
const watcherOptions = {
|
|
19963
20214
|
ignored: (filePath) => {
|
|
19964
|
-
const relativePath =
|
|
20215
|
+
const relativePath = path28.relative(this.projectRoot, filePath);
|
|
19965
20216
|
if (!relativePath) return false;
|
|
19966
20217
|
if (this.isProjectConfigPathOrAncestor(relativePath)) {
|
|
19967
20218
|
return false;
|
|
@@ -19969,10 +20220,10 @@ var FileWatcher = class {
|
|
|
19969
20220
|
if (this.isOutsideProjectPath(relativePath)) {
|
|
19970
20221
|
return true;
|
|
19971
20222
|
}
|
|
19972
|
-
if (hasFilteredPathSegment(relativePath,
|
|
20223
|
+
if (hasFilteredPathSegment(relativePath, path28.sep)) {
|
|
19973
20224
|
return true;
|
|
19974
20225
|
}
|
|
19975
|
-
if (isRestrictedDirectory(relativePath,
|
|
20226
|
+
if (isRestrictedDirectory(relativePath, path28.sep)) {
|
|
19976
20227
|
return true;
|
|
19977
20228
|
}
|
|
19978
20229
|
if (ignoreFilter.ignores(relativePath)) {
|
|
@@ -20005,10 +20256,13 @@ var FileWatcher = class {
|
|
|
20005
20256
|
watcher = new FSWatcher(watcherOptions);
|
|
20006
20257
|
}
|
|
20007
20258
|
this.watcher = watcher;
|
|
20008
|
-
watcher.
|
|
20259
|
+
watcher.on("ready", () => {
|
|
20009
20260
|
if (this.watcher !== watcher) return;
|
|
20010
|
-
this.
|
|
20011
|
-
|
|
20261
|
+
this.reconcileConfigPathStates();
|
|
20262
|
+
if (reportsStartupReady) {
|
|
20263
|
+
this.reportStartupReadySignal();
|
|
20264
|
+
reportedStartupReady = true;
|
|
20265
|
+
}
|
|
20012
20266
|
});
|
|
20013
20267
|
watcher.on("error", (error) => {
|
|
20014
20268
|
const err = error instanceof Error ? error : null;
|
|
@@ -20022,10 +20276,13 @@ var FileWatcher = class {
|
|
|
20022
20276
|
console.error("[codebase-index] Failed to close exhausted file watcher:", closeError);
|
|
20023
20277
|
});
|
|
20024
20278
|
if (this.onChanges) {
|
|
20279
|
+
const replacementReportsStartupReady = reportsStartupReady || reportedStartupReady;
|
|
20025
20280
|
if (!this.resolveReady) {
|
|
20026
20281
|
this.resetReady();
|
|
20282
|
+
} else if (reportedStartupReady) {
|
|
20283
|
+
this.startupReadySignals += 1;
|
|
20027
20284
|
}
|
|
20028
|
-
this.createWatcher(true);
|
|
20285
|
+
this.createWatcher(resolvedWatchTargets, true, replacementReportsStartupReady);
|
|
20029
20286
|
} else {
|
|
20030
20287
|
this.watcher = null;
|
|
20031
20288
|
}
|
|
@@ -20036,13 +20293,166 @@ var FileWatcher = class {
|
|
|
20036
20293
|
watcher.on("add", (filePath) => this.handleChange(watcher, "add", filePath));
|
|
20037
20294
|
watcher.on("change", (filePath) => this.handleChange(watcher, "change", filePath));
|
|
20038
20295
|
watcher.on("unlink", (filePath) => this.handleChange(watcher, "unlink", filePath));
|
|
20039
|
-
watcher.add(
|
|
20296
|
+
watcher.add(resolvedWatchTargets);
|
|
20297
|
+
}
|
|
20298
|
+
shouldUseNativeWatcher() {
|
|
20299
|
+
if (this.backend === "chokidar") {
|
|
20300
|
+
return false;
|
|
20301
|
+
}
|
|
20302
|
+
return true;
|
|
20303
|
+
}
|
|
20304
|
+
getFullChokidarWatchTargets() {
|
|
20305
|
+
if (this.configPath) {
|
|
20306
|
+
return [this.projectRoot, this.configPath];
|
|
20307
|
+
}
|
|
20308
|
+
const externalConfigTargets = this.getExternalConfigWatchTargets();
|
|
20309
|
+
if (externalConfigTargets.length === 0) {
|
|
20310
|
+
return this.projectRoot;
|
|
20311
|
+
}
|
|
20312
|
+
return [this.projectRoot, ...externalConfigTargets];
|
|
20313
|
+
}
|
|
20314
|
+
getExternalConfigWatchTargets() {
|
|
20315
|
+
return [...new Set(
|
|
20316
|
+
this.projectConfigPaths.filter((projectConfigPath) => {
|
|
20317
|
+
const relativeConfigPath = path28.relative(this.projectRoot, projectConfigPath);
|
|
20318
|
+
return this.isOutsideProjectPath(relativeConfigPath);
|
|
20319
|
+
}).map((projectConfigPath) => {
|
|
20320
|
+
if (existsSync15(projectConfigPath)) {
|
|
20321
|
+
return projectConfigPath;
|
|
20322
|
+
}
|
|
20323
|
+
return this.getNearestExistingDirectory(path28.dirname(projectConfigPath));
|
|
20324
|
+
})
|
|
20325
|
+
)];
|
|
20326
|
+
}
|
|
20327
|
+
hasExternalConfigWatchTarget() {
|
|
20328
|
+
return this.getExternalConfigWatchTargets().length > 0;
|
|
20329
|
+
}
|
|
20330
|
+
startExternalConfigWatcher(usePolling = false) {
|
|
20331
|
+
const externalTargets = this.getExternalConfigWatchTargets();
|
|
20332
|
+
if (externalTargets.length === 0) {
|
|
20333
|
+
return;
|
|
20334
|
+
}
|
|
20335
|
+
this.createWatcher(externalTargets, usePolling);
|
|
20336
|
+
}
|
|
20337
|
+
async createNativeWatcher() {
|
|
20338
|
+
const generation = ++this.nativeSetupGeneration;
|
|
20339
|
+
const reconciler = new FileSnapshotReconciler(this.projectRoot, this.config, this.projectConfigPaths);
|
|
20340
|
+
const watcher = new NativeRecursiveWatcher(
|
|
20341
|
+
this.projectRoot,
|
|
20342
|
+
(filePath) => this.scheduleNativeReconciliation(generation, filePath),
|
|
20343
|
+
{ onError: (error) => void this.fallbackFromNativeWatcher(generation, error) }
|
|
20344
|
+
);
|
|
20345
|
+
this.nativeReconciler = reconciler;
|
|
20346
|
+
this.nativeWatcher = watcher;
|
|
20347
|
+
this.nativeInitializing = true;
|
|
20348
|
+
try {
|
|
20349
|
+
watcher.start();
|
|
20350
|
+
if (!this.isCurrentNativeSetup(generation)) {
|
|
20351
|
+
await watcher.stop();
|
|
20352
|
+
return;
|
|
20353
|
+
}
|
|
20354
|
+
await reconciler.initialize();
|
|
20355
|
+
if (!this.isCurrentNativeSetup(generation) || this.nativeWatcher !== watcher) {
|
|
20356
|
+
await watcher.stop();
|
|
20357
|
+
return;
|
|
20358
|
+
}
|
|
20359
|
+
this.nativeStarting = false;
|
|
20360
|
+
this.nativeInitializing = false;
|
|
20361
|
+
await this.reconcileNativeWatcherWithPendingInvalidations(generation);
|
|
20362
|
+
this.reportStartupReadySignal();
|
|
20363
|
+
} catch (error) {
|
|
20364
|
+
if (!this.isCurrentNativeSetup(generation)) return;
|
|
20365
|
+
this.nativeInitializing = false;
|
|
20366
|
+
if (this.nativeWatcher) {
|
|
20367
|
+
await this.fallbackFromNativeWatcher(generation, error);
|
|
20368
|
+
return;
|
|
20369
|
+
}
|
|
20370
|
+
this.nativeStarting = false;
|
|
20371
|
+
const externalWatcher = this.watcher;
|
|
20372
|
+
this.watcher = null;
|
|
20373
|
+
this.nativeReconciler = null;
|
|
20374
|
+
await externalWatcher?.close();
|
|
20375
|
+
console.warn("[codebase-index] Native recursive watcher unavailable; using Chokidar fallback.", error);
|
|
20376
|
+
this.setStartupReadySignals(1);
|
|
20377
|
+
this.createWatcher();
|
|
20378
|
+
}
|
|
20379
|
+
}
|
|
20380
|
+
isCurrentNativeSetup(generation) {
|
|
20381
|
+
return this.nativeSetupGeneration === generation && this.onChanges !== null;
|
|
20382
|
+
}
|
|
20383
|
+
scheduleNativeReconciliation(generation, filePath) {
|
|
20384
|
+
if (!this.isCurrentNativeSetup(generation)) return;
|
|
20385
|
+
const requiresFullReconciliation = filePath === path28.join(this.projectRoot, ".gitignore");
|
|
20386
|
+
const invalidatedPath = requiresFullReconciliation ? null : filePath;
|
|
20387
|
+
this.nativeInvalidatedPaths.set(invalidatedPath, invalidatedPath !== null);
|
|
20388
|
+
if (this.nativeReconcileTimer) {
|
|
20389
|
+
clearTimeout(this.nativeReconcileTimer);
|
|
20390
|
+
}
|
|
20391
|
+
this.nativeReconcileTimer = setTimeout(() => {
|
|
20392
|
+
this.nativeReconcileTimer = null;
|
|
20393
|
+
void this.reconcileNativeWatcherFromQueue(generation);
|
|
20394
|
+
}, 100);
|
|
20395
|
+
}
|
|
20396
|
+
reconcileNativeWatcherFromQueue(generation) {
|
|
20397
|
+
if (!this.isCurrentNativeSetup(generation) || this.nativeInitializing) return;
|
|
20398
|
+
const invalidatedPaths = this.popNativeInvalidations();
|
|
20399
|
+
if (invalidatedPaths.length === 0) return;
|
|
20400
|
+
void this.reconcileNativeWatcher(generation, invalidatedPaths);
|
|
20401
|
+
}
|
|
20402
|
+
async reconcileNativeWatcher(generation, invalidatedPaths) {
|
|
20403
|
+
if (!this.isCurrentNativeSetup(generation) || !this.nativeReconciler) return;
|
|
20404
|
+
try {
|
|
20405
|
+
const reconciler = this.nativeReconciler;
|
|
20406
|
+
const changes = await reconciler.reconcile(invalidatedPaths);
|
|
20407
|
+
if (!this.isCurrentNativeSetup(generation) || this.nativeReconciler !== reconciler) return;
|
|
20408
|
+
this.recordChanges(changes);
|
|
20409
|
+
} catch (error) {
|
|
20410
|
+
await this.fallbackFromNativeWatcher(generation, error);
|
|
20411
|
+
}
|
|
20412
|
+
}
|
|
20413
|
+
async reconcileNativeWatcherWithPendingInvalidations(generation) {
|
|
20414
|
+
const invalidatedPaths = this.popNativeInvalidations();
|
|
20415
|
+
if (invalidatedPaths.length === 0) return;
|
|
20416
|
+
await this.reconcileNativeWatcher(generation, invalidatedPaths);
|
|
20417
|
+
}
|
|
20418
|
+
popNativeInvalidations() {
|
|
20419
|
+
if (this.nativeInvalidatedPaths.size === 0) return [];
|
|
20420
|
+
const invalidations = [...this.nativeInvalidatedPaths].map(([invalidatedPath, forceChange]) => ({
|
|
20421
|
+
path: invalidatedPath,
|
|
20422
|
+
forceChange
|
|
20423
|
+
}));
|
|
20424
|
+
this.nativeInvalidatedPaths.clear();
|
|
20425
|
+
return invalidations;
|
|
20426
|
+
}
|
|
20427
|
+
async fallbackFromNativeWatcher(generation, error) {
|
|
20428
|
+
if (!this.isCurrentNativeSetup(generation)) return;
|
|
20429
|
+
const watcher = this.nativeWatcher;
|
|
20430
|
+
const externalWatcher = this.watcher;
|
|
20431
|
+
this.nativeWatcher = null;
|
|
20432
|
+
this.watcher = null;
|
|
20433
|
+
this.nativeReconciler = null;
|
|
20434
|
+
this.nativeStarting = false;
|
|
20435
|
+
this.nativeInitializing = false;
|
|
20436
|
+
this.nativeSetupGeneration += 1;
|
|
20437
|
+
if (this.nativeReconcileTimer) {
|
|
20438
|
+
clearTimeout(this.nativeReconcileTimer);
|
|
20439
|
+
this.nativeReconcileTimer = null;
|
|
20440
|
+
}
|
|
20441
|
+
this.nativeInvalidatedPaths.clear();
|
|
20442
|
+
this.setStartupReadySignals(1);
|
|
20443
|
+
console.warn("[codebase-index] Native recursive watcher failed; using Chokidar fallback.", error);
|
|
20444
|
+
await watcher?.stop();
|
|
20445
|
+
await externalWatcher?.close();
|
|
20446
|
+
if (this.onChanges) {
|
|
20447
|
+
this.createWatcher();
|
|
20448
|
+
}
|
|
20040
20449
|
}
|
|
20041
20450
|
handleChange(watcher, type, filePath) {
|
|
20042
20451
|
if (this.watcher !== watcher) {
|
|
20043
20452
|
return;
|
|
20044
20453
|
}
|
|
20045
20454
|
if (this.isProjectConfigPath(filePath)) {
|
|
20455
|
+
this.updateConfigPathState(filePath);
|
|
20046
20456
|
this.pendingChanges.set(filePath, type);
|
|
20047
20457
|
this.scheduleFlush();
|
|
20048
20458
|
return;
|
|
@@ -20057,27 +20467,33 @@ var FileWatcher = class {
|
|
|
20057
20467
|
)) {
|
|
20058
20468
|
return;
|
|
20059
20469
|
}
|
|
20060
|
-
this.
|
|
20470
|
+
this.recordChanges([{ path: filePath, type }]);
|
|
20471
|
+
}
|
|
20472
|
+
recordChanges(changes) {
|
|
20473
|
+
if (changes.length === 0) return;
|
|
20474
|
+
for (const change of changes) {
|
|
20475
|
+
this.pendingChanges.set(change.path, change.type);
|
|
20476
|
+
}
|
|
20061
20477
|
this.scheduleFlush();
|
|
20062
20478
|
}
|
|
20063
20479
|
isProjectConfigPath(filePath) {
|
|
20064
|
-
const relativePath =
|
|
20065
|
-
const normalizedRelativePath =
|
|
20480
|
+
const relativePath = path28.relative(this.projectRoot, filePath);
|
|
20481
|
+
const normalizedRelativePath = path28.normalize(relativePath);
|
|
20066
20482
|
return this.getProjectConfigRelativePaths().some((configPath) => configPath === normalizedRelativePath);
|
|
20067
20483
|
}
|
|
20068
20484
|
isProjectConfigPathOrAncestor(relativePath) {
|
|
20069
|
-
const normalizedRelativePath =
|
|
20485
|
+
const normalizedRelativePath = path28.normalize(relativePath);
|
|
20070
20486
|
return this.getProjectConfigRelativePaths().some(
|
|
20071
|
-
(configPath) => configPath === normalizedRelativePath || configPath.startsWith(`${normalizedRelativePath}${
|
|
20487
|
+
(configPath) => configPath === normalizedRelativePath || configPath.startsWith(`${normalizedRelativePath}${path28.sep}`)
|
|
20072
20488
|
);
|
|
20073
20489
|
}
|
|
20074
20490
|
isOutsideProjectPath(relativePath) {
|
|
20075
|
-
return relativePath === ".." || relativePath.startsWith(`..${
|
|
20491
|
+
return relativePath === ".." || relativePath.startsWith(`..${path28.sep}`) || path28.isAbsolute(relativePath);
|
|
20076
20492
|
}
|
|
20077
20493
|
getNearestExistingDirectory(directoryPath) {
|
|
20078
20494
|
let candidate = directoryPath;
|
|
20079
20495
|
while (!existsSync15(candidate)) {
|
|
20080
|
-
const parent =
|
|
20496
|
+
const parent = path28.dirname(candidate);
|
|
20081
20497
|
if (parent === candidate) break;
|
|
20082
20498
|
candidate = parent;
|
|
20083
20499
|
}
|
|
@@ -20085,9 +20501,51 @@ var FileWatcher = class {
|
|
|
20085
20501
|
}
|
|
20086
20502
|
getProjectConfigRelativePaths() {
|
|
20087
20503
|
return this.projectConfigPaths.map(
|
|
20088
|
-
(configPath) =>
|
|
20504
|
+
(configPath) => path28.normalize(path28.relative(this.projectRoot, configPath))
|
|
20089
20505
|
);
|
|
20090
20506
|
}
|
|
20507
|
+
getConfigPathStates() {
|
|
20508
|
+
const states = /* @__PURE__ */ new Map();
|
|
20509
|
+
for (const configPath of this.projectConfigPaths) {
|
|
20510
|
+
const state = this.getConfigPathState(configPath);
|
|
20511
|
+
if (state) states.set(configPath, state);
|
|
20512
|
+
}
|
|
20513
|
+
return states;
|
|
20514
|
+
}
|
|
20515
|
+
getConfigPathState(configPath) {
|
|
20516
|
+
try {
|
|
20517
|
+
const stats = statSync6(configPath);
|
|
20518
|
+
return stats.isFile() ? { mtimeMs: stats.mtimeMs, size: stats.size } : void 0;
|
|
20519
|
+
} catch (error) {
|
|
20520
|
+
void error;
|
|
20521
|
+
return void 0;
|
|
20522
|
+
}
|
|
20523
|
+
}
|
|
20524
|
+
updateConfigPathState(configPath) {
|
|
20525
|
+
const state = this.getConfigPathState(configPath);
|
|
20526
|
+
if (state) {
|
|
20527
|
+
this.configPathStates.set(configPath, state);
|
|
20528
|
+
} else {
|
|
20529
|
+
this.configPathStates.delete(configPath);
|
|
20530
|
+
}
|
|
20531
|
+
}
|
|
20532
|
+
reconcileConfigPathStates() {
|
|
20533
|
+
const nextStates = this.getConfigPathStates();
|
|
20534
|
+
const changes = [];
|
|
20535
|
+
for (const configPath of this.projectConfigPaths) {
|
|
20536
|
+
const previous = this.configPathStates.get(configPath);
|
|
20537
|
+
const next = nextStates.get(configPath);
|
|
20538
|
+
if (!previous && next) {
|
|
20539
|
+
changes.push({ path: configPath, type: "add" });
|
|
20540
|
+
} else if (previous && !next) {
|
|
20541
|
+
changes.push({ path: configPath, type: "unlink" });
|
|
20542
|
+
} else if (previous && next && (previous.size !== next.size || previous.mtimeMs !== next.mtimeMs)) {
|
|
20543
|
+
changes.push({ path: configPath, type: "change" });
|
|
20544
|
+
}
|
|
20545
|
+
}
|
|
20546
|
+
this.configPathStates = nextStates;
|
|
20547
|
+
this.recordChanges(changes);
|
|
20548
|
+
}
|
|
20091
20549
|
scheduleFlush() {
|
|
20092
20550
|
if (this.debounceTimer) {
|
|
20093
20551
|
clearTimeout(this.debounceTimer);
|
|
@@ -20101,7 +20559,7 @@ var FileWatcher = class {
|
|
|
20101
20559
|
return;
|
|
20102
20560
|
}
|
|
20103
20561
|
const changes = Array.from(this.pendingChanges.entries()).map(
|
|
20104
|
-
([
|
|
20562
|
+
([path33, type]) => ({ path: path33, type })
|
|
20105
20563
|
);
|
|
20106
20564
|
this.pendingChanges.clear();
|
|
20107
20565
|
try {
|
|
@@ -20115,20 +20573,31 @@ var FileWatcher = class {
|
|
|
20115
20573
|
clearTimeout(this.debounceTimer);
|
|
20116
20574
|
this.debounceTimer = null;
|
|
20117
20575
|
}
|
|
20576
|
+
if (this.nativeReconcileTimer) {
|
|
20577
|
+
clearTimeout(this.nativeReconcileTimer);
|
|
20578
|
+
this.nativeReconcileTimer = null;
|
|
20579
|
+
}
|
|
20580
|
+
this.nativeInvalidatedPaths.clear();
|
|
20118
20581
|
const watcher = this.watcher;
|
|
20582
|
+
const nativeWatcher = this.nativeWatcher;
|
|
20119
20583
|
const pendingClose = this.pendingClose;
|
|
20120
20584
|
const resolveReady = this.resolveReady;
|
|
20121
20585
|
this.watcher = null;
|
|
20586
|
+
this.nativeWatcher = null;
|
|
20587
|
+
this.nativeReconciler = null;
|
|
20588
|
+
this.nativeStarting = false;
|
|
20589
|
+
this.nativeInitializing = false;
|
|
20590
|
+
this.nativeSetupGeneration += 1;
|
|
20122
20591
|
this.pendingClose = null;
|
|
20123
20592
|
this.resolveReady = null;
|
|
20124
20593
|
this.readyPromise = null;
|
|
20125
20594
|
this.pendingChanges.clear();
|
|
20126
20595
|
this.onChanges = null;
|
|
20127
|
-
await Promise.all([watcher?.close(), pendingClose]);
|
|
20596
|
+
await Promise.all([watcher?.close(), nativeWatcher?.stop(), pendingClose]);
|
|
20128
20597
|
resolveReady?.();
|
|
20129
20598
|
}
|
|
20130
20599
|
isRunning() {
|
|
20131
|
-
return this.watcher !== null;
|
|
20600
|
+
return this.watcher !== null || this.nativeWatcher !== null || this.nativeStarting;
|
|
20132
20601
|
}
|
|
20133
20602
|
async waitUntilReady() {
|
|
20134
20603
|
await (this.readyPromise ?? Promise.resolve());
|
|
@@ -20136,7 +20605,7 @@ var FileWatcher = class {
|
|
|
20136
20605
|
};
|
|
20137
20606
|
|
|
20138
20607
|
// src/watcher/git-head-watcher.ts
|
|
20139
|
-
import * as
|
|
20608
|
+
import * as path29 from "path";
|
|
20140
20609
|
var GitHeadWatcher = class {
|
|
20141
20610
|
watcher = null;
|
|
20142
20611
|
projectRoot;
|
|
@@ -20158,13 +20627,13 @@ var GitHeadWatcher = class {
|
|
|
20158
20627
|
this.readyPromise = Promise.resolve();
|
|
20159
20628
|
return;
|
|
20160
20629
|
}
|
|
20161
|
-
this.readyPromise = new Promise((
|
|
20162
|
-
this.resolveReady =
|
|
20630
|
+
this.readyPromise = new Promise((resolve20) => {
|
|
20631
|
+
this.resolveReady = resolve20;
|
|
20163
20632
|
});
|
|
20164
20633
|
this.onBranchChange = handler;
|
|
20165
20634
|
this.currentBranch = getCurrentBranch(this.projectRoot);
|
|
20166
20635
|
const headPath = getHeadPath(this.projectRoot);
|
|
20167
|
-
const refsPath =
|
|
20636
|
+
const refsPath = path29.join(this.projectRoot, ".git", "refs", "heads");
|
|
20168
20637
|
this.watcher = chokidar_default.watch([headPath, refsPath], {
|
|
20169
20638
|
persistent: true,
|
|
20170
20639
|
ignoreInitial: true,
|
|
@@ -20300,7 +20769,7 @@ function getConfigPaths(projectRoot, host, options) {
|
|
|
20300
20769
|
|
|
20301
20770
|
// src/tools/visualize/activity.ts
|
|
20302
20771
|
import { execFileSync } from "child_process";
|
|
20303
|
-
import * as
|
|
20772
|
+
import * as path30 from "path";
|
|
20304
20773
|
function attachRecentActivity(data, projectRoot) {
|
|
20305
20774
|
const activity = readGitActivity(projectRoot);
|
|
20306
20775
|
const changes = activity.size > 0 ? buildGitChanges(data, activity, projectRoot) : buildGraphChanges(data);
|
|
@@ -20462,7 +20931,7 @@ function normalizePath4(filePath) {
|
|
|
20462
20931
|
return filePath.replace(/\\/g, "/");
|
|
20463
20932
|
}
|
|
20464
20933
|
function toGitRelativePath(projectRoot, filePath) {
|
|
20465
|
-
const relativePath =
|
|
20934
|
+
const relativePath = path30.isAbsolute(filePath) ? path30.relative(projectRoot, filePath) : filePath;
|
|
20466
20935
|
return normalizePath4(relativePath);
|
|
20467
20936
|
}
|
|
20468
20937
|
|
|
@@ -20720,7 +21189,7 @@ render();
|
|
|
20720
21189
|
}
|
|
20721
21190
|
|
|
20722
21191
|
// src/tools/visualize/transform.ts
|
|
20723
|
-
import * as
|
|
21192
|
+
import * as path31 from "path";
|
|
20724
21193
|
|
|
20725
21194
|
// src/tools/visualize/modules.ts
|
|
20726
21195
|
var MAX_MODULES = 18;
|
|
@@ -20853,8 +21322,8 @@ function compactModules(prefixToNodes) {
|
|
|
20853
21322
|
function deriveModules(nodes) {
|
|
20854
21323
|
const initial = /* @__PURE__ */ new Map();
|
|
20855
21324
|
for (const node of nodes) {
|
|
20856
|
-
const
|
|
20857
|
-
const prefix = modulePrefixFromRelativePath(
|
|
21325
|
+
const relative14 = stripToProjectRelative(node.filePath);
|
|
21326
|
+
const prefix = modulePrefixFromRelativePath(relative14);
|
|
20858
21327
|
if (!initial.has(prefix)) initial.set(prefix, []);
|
|
20859
21328
|
initial.get(prefix)?.push(node);
|
|
20860
21329
|
}
|
|
@@ -20980,7 +21449,7 @@ function transformForVisualization(symbols, edges, options = {}) {
|
|
|
20980
21449
|
filePath: s.filePath,
|
|
20981
21450
|
kind: s.kind,
|
|
20982
21451
|
line: s.startLine,
|
|
20983
|
-
directory:
|
|
21452
|
+
directory: path31.dirname(s.filePath),
|
|
20984
21453
|
moduleId: "",
|
|
20985
21454
|
moduleLabel: ""
|
|
20986
21455
|
}));
|
|
@@ -21008,9 +21477,9 @@ function parseArgs(argv) {
|
|
|
21008
21477
|
let host = "opencode";
|
|
21009
21478
|
for (let i = 2; i < argv.length; i++) {
|
|
21010
21479
|
if (argv[i] === "--project" && argv[i + 1]) {
|
|
21011
|
-
project =
|
|
21480
|
+
project = path32.resolve(argv[++i]);
|
|
21012
21481
|
} else if (argv[i] === "--config" && argv[i + 1]) {
|
|
21013
|
-
config =
|
|
21482
|
+
config = path32.resolve(argv[++i]);
|
|
21014
21483
|
} else if (argv[i] === "--host" && argv[i + 1]) {
|
|
21015
21484
|
host = parseHostMode(argv[++i]);
|
|
21016
21485
|
} else if (argv[i] === "--host") {
|
|
@@ -21037,7 +21506,7 @@ function parseIndexArgs(argv, cwd) {
|
|
|
21037
21506
|
if (!arg.startsWith("--project=")) {
|
|
21038
21507
|
i += 1;
|
|
21039
21508
|
}
|
|
21040
|
-
project =
|
|
21509
|
+
project = path32.resolve(cwd, value);
|
|
21041
21510
|
continue;
|
|
21042
21511
|
}
|
|
21043
21512
|
if (arg === "--config" || arg.startsWith("--config=")) {
|
|
@@ -21048,7 +21517,7 @@ function parseIndexArgs(argv, cwd) {
|
|
|
21048
21517
|
if (!arg.startsWith("--config=")) {
|
|
21049
21518
|
i += 1;
|
|
21050
21519
|
}
|
|
21051
|
-
config =
|
|
21520
|
+
config = path32.resolve(cwd, value);
|
|
21052
21521
|
continue;
|
|
21053
21522
|
}
|
|
21054
21523
|
if (arg === "--host" || arg.startsWith("--host=")) {
|
|
@@ -21114,7 +21583,7 @@ function parseVisualizeArgs(argv, cwd) {
|
|
|
21114
21583
|
for (let i = 0; i < argv.length; i++) {
|
|
21115
21584
|
const arg = argv[i];
|
|
21116
21585
|
if (arg === "--project" && argv[i + 1]) {
|
|
21117
|
-
project =
|
|
21586
|
+
project = path32.resolve(argv[++i]);
|
|
21118
21587
|
} else if (arg === "--max" && argv[i + 1]) {
|
|
21119
21588
|
maxNodes = Number(argv[++i]);
|
|
21120
21589
|
} else if (arg.startsWith("--max=") || arg.startsWith("max=")) {
|
|
@@ -21151,7 +21620,7 @@ async function handleVisualizeCommand(argv, cwd) {
|
|
|
21151
21620
|
console.error("No connected symbols found. Retry with: npm run visualize -- orphans");
|
|
21152
21621
|
return 1;
|
|
21153
21622
|
}
|
|
21154
|
-
const outputPath =
|
|
21623
|
+
const outputPath = path32.join(os8.tmpdir(), `call-graph-${Date.now()}.html`);
|
|
21155
21624
|
writeFileSync6(outputPath, generateVisualizationHtml(vizData), "utf-8");
|
|
21156
21625
|
console.log(`Temporal call graph visualization generated: ${outputPath}`);
|
|
21157
21626
|
console.log(`Nodes: ${vizData.nodes.length} | Edges: ${vizData.edges.length}`);
|
|
@@ -21183,8 +21652,60 @@ async function runMcpCli(argv) {
|
|
|
21183
21652
|
const config = parseConfig(rawConfig);
|
|
21184
21653
|
const server = createMcpServer(args.project, config, args.host);
|
|
21185
21654
|
const transport = new StdioServerTransport();
|
|
21186
|
-
await server.connect(transport);
|
|
21187
21655
|
let watcher = null;
|
|
21656
|
+
let shutdownPromise;
|
|
21657
|
+
const onServerClose = server.server.onclose;
|
|
21658
|
+
const shutdown = () => {
|
|
21659
|
+
if (shutdownPromise) return shutdownPromise;
|
|
21660
|
+
process.stdin.removeListener("end", requestShutdown);
|
|
21661
|
+
process.stdin.removeListener("close", requestShutdown);
|
|
21662
|
+
process.removeListener("SIGHUP", requestShutdown);
|
|
21663
|
+
process.removeListener("SIGINT", requestShutdown);
|
|
21664
|
+
process.removeListener("SIGTERM", requestShutdown);
|
|
21665
|
+
server.server.onclose = onServerClose;
|
|
21666
|
+
shutdownPromise = (async () => {
|
|
21667
|
+
let exitCode = 0;
|
|
21668
|
+
try {
|
|
21669
|
+
await watcher?.stop();
|
|
21670
|
+
} catch (error) {
|
|
21671
|
+
exitCode = 1;
|
|
21672
|
+
console.error("Failed to stop MCP file watcher cleanly:", error);
|
|
21673
|
+
}
|
|
21674
|
+
try {
|
|
21675
|
+
await stopAutoIndex(args.project, args.host);
|
|
21676
|
+
} catch (error) {
|
|
21677
|
+
exitCode = 1;
|
|
21678
|
+
console.error("Failed to stop automatic indexing cleanly:", error);
|
|
21679
|
+
}
|
|
21680
|
+
try {
|
|
21681
|
+
await server.close();
|
|
21682
|
+
} catch (error) {
|
|
21683
|
+
exitCode = 1;
|
|
21684
|
+
console.error("Failed to close MCP server cleanly:", error);
|
|
21685
|
+
}
|
|
21686
|
+
process.exit(exitCode);
|
|
21687
|
+
})();
|
|
21688
|
+
return shutdownPromise;
|
|
21689
|
+
};
|
|
21690
|
+
const requestShutdown = () => {
|
|
21691
|
+
void shutdown();
|
|
21692
|
+
};
|
|
21693
|
+
server.server.onclose = () => {
|
|
21694
|
+
try {
|
|
21695
|
+
onServerClose?.();
|
|
21696
|
+
} finally {
|
|
21697
|
+
requestShutdown();
|
|
21698
|
+
}
|
|
21699
|
+
};
|
|
21700
|
+
process.stdin.once("end", requestShutdown);
|
|
21701
|
+
process.stdin.once("close", requestShutdown);
|
|
21702
|
+
process.once("SIGINT", requestShutdown);
|
|
21703
|
+
if (process.platform !== "win32") {
|
|
21704
|
+
process.once("SIGHUP", requestShutdown);
|
|
21705
|
+
process.once("SIGTERM", requestShutdown);
|
|
21706
|
+
}
|
|
21707
|
+
await server.connect(transport);
|
|
21708
|
+
if (shutdownPromise) return;
|
|
21188
21709
|
const isHomeDir = isHomeDirectory(args.project);
|
|
21189
21710
|
const isValidProject = !isHomeDir && (!config.indexing.requireProjectMarker || hasProjectMarker(args.project));
|
|
21190
21711
|
if (config.indexing.watchFiles && isValidProject) {
|
|
@@ -21196,26 +21717,6 @@ async function runMcpCli(argv) {
|
|
|
21196
21717
|
args.config ? { configPath: args.config } : {}
|
|
21197
21718
|
);
|
|
21198
21719
|
}
|
|
21199
|
-
let shuttingDown = false;
|
|
21200
|
-
const shutdown = async () => {
|
|
21201
|
-
if (shuttingDown) return;
|
|
21202
|
-
shuttingDown = true;
|
|
21203
|
-
try {
|
|
21204
|
-
await watcher?.stop();
|
|
21205
|
-
await stopAutoIndex(args.project, args.host);
|
|
21206
|
-
await server.close();
|
|
21207
|
-
process.exit(0);
|
|
21208
|
-
} catch (error) {
|
|
21209
|
-
console.error("Failed to stop MCP server cleanly:", error);
|
|
21210
|
-
process.exit(1);
|
|
21211
|
-
}
|
|
21212
|
-
};
|
|
21213
|
-
process.on("SIGINT", () => {
|
|
21214
|
-
void shutdown();
|
|
21215
|
-
});
|
|
21216
|
-
process.on("SIGTERM", () => {
|
|
21217
|
-
void shutdown();
|
|
21218
|
-
});
|
|
21219
21720
|
}
|
|
21220
21721
|
function printIndexProgress(onProgress, title, metadata) {
|
|
21221
21722
|
const details = Object.entries(metadata).filter(([, value]) => value !== void 0 && value !== null).map(([key, value]) => `${key}=${isSensitiveKey(key) ? "[REDACTED]" : String(value)}`).join(" ");
|