open-codebase-index 0.22.5 → 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 +949 -479
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +950 -480
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +854 -395
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +855 -396
- package/dist/index.js.map +1 -1
- package/dist/pi-extension.cjs +6 -95
- package/dist/pi-extension.cjs.map +1 -1
- package/dist/pi-extension.js +6 -95
- 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);
|
|
@@ -8578,7 +8500,6 @@ var Indexer = class _Indexer {
|
|
|
8578
8500
|
database = null;
|
|
8579
8501
|
provider = null;
|
|
8580
8502
|
configuredProviderInfo = null;
|
|
8581
|
-
reranker = null;
|
|
8582
8503
|
fileHashCache = /* @__PURE__ */ new Map();
|
|
8583
8504
|
fileHashCachePath = "";
|
|
8584
8505
|
failedBatchesPath = "";
|
|
@@ -8738,7 +8659,6 @@ var Indexer = class _Indexer {
|
|
|
8738
8659
|
this.database = null;
|
|
8739
8660
|
this.provider = null;
|
|
8740
8661
|
this.configuredProviderInfo = null;
|
|
8741
|
-
this.reranker = null;
|
|
8742
8662
|
this.indexCompatibility = null;
|
|
8743
8663
|
this.initializationMode = "none";
|
|
8744
8664
|
this.readIssues = [];
|
|
@@ -9468,7 +9388,7 @@ var Indexer = class _Indexer {
|
|
|
9468
9388
|
await options.queue.onSizeLessThan(Math.max(1, options.providerRateLimits.concurrency));
|
|
9469
9389
|
const task = options.queue.add(async () => {
|
|
9470
9390
|
if (options.rateLimitState.backoffMs > 0) {
|
|
9471
|
-
await new Promise((
|
|
9391
|
+
await new Promise((resolve20) => setTimeout(resolve20, options.rateLimitState.backoffMs));
|
|
9472
9392
|
}
|
|
9473
9393
|
try {
|
|
9474
9394
|
const embeddingResult = await pRetry(
|
|
@@ -10035,15 +9955,6 @@ var Indexer = class _Indexer {
|
|
|
10035
9955
|
rerankerEnabled: this.config.reranker?.enabled ?? false
|
|
10036
9956
|
});
|
|
10037
9957
|
this.provider = createEmbeddingProvider(this.configuredProviderInfo);
|
|
10038
|
-
if (this.config.reranker?.enabled) {
|
|
10039
|
-
this.reranker = createReranker(this.config.reranker);
|
|
10040
|
-
if (this.reranker.isAvailable()) {
|
|
10041
|
-
this.logger.info("Reranker initialized", {
|
|
10042
|
-
model: this.config.reranker.model,
|
|
10043
|
-
baseUrl: this.config.reranker.baseUrl
|
|
10044
|
-
});
|
|
10045
|
-
}
|
|
10046
|
-
}
|
|
10047
9958
|
const dimensions = this.configuredProviderInfo.modelInfo.dimensions;
|
|
10048
9959
|
const storePath = path15.join(this.indexPath, "vectors");
|
|
10049
9960
|
const vectorMetadataPath = `${storePath}.meta.json`;
|
|
@@ -11448,6 +11359,7 @@ var Indexer = class _Indexer {
|
|
|
11448
11359
|
const filterByBranch = options?.filterByBranch ?? true;
|
|
11449
11360
|
const sourceIntent = options?.definitionIntent === true || classifyQueryIntentRaw(query) === "source";
|
|
11450
11361
|
const identifierHints = extractIdentifierHints(query);
|
|
11362
|
+
const candidateLimit = maxResults * (sourceIntent ? 12 : 4);
|
|
11451
11363
|
this.logger.search("debug", "Starting search", {
|
|
11452
11364
|
query,
|
|
11453
11365
|
maxResults,
|
|
@@ -11484,7 +11396,7 @@ var Indexer = class _Indexer {
|
|
|
11484
11396
|
const semanticCandidates = embedding ? this.searchSemanticCandidates(
|
|
11485
11397
|
store,
|
|
11486
11398
|
embedding,
|
|
11487
|
-
|
|
11399
|
+
candidateLimit,
|
|
11488
11400
|
branchChunkIds,
|
|
11489
11401
|
shouldPrefilterByBranch
|
|
11490
11402
|
) : [];
|
|
@@ -11492,7 +11404,7 @@ var Indexer = class _Indexer {
|
|
|
11492
11404
|
const keywordStartTime = performance2.now();
|
|
11493
11405
|
const keywordCandidates = await this.keywordSearch(
|
|
11494
11406
|
query,
|
|
11495
|
-
|
|
11407
|
+
candidateLimit,
|
|
11496
11408
|
store,
|
|
11497
11409
|
invertedIndex,
|
|
11498
11410
|
branchChunkIds,
|
|
@@ -12250,9 +12162,9 @@ var Indexer = class _Indexer {
|
|
|
12250
12162
|
this.requireReadableComponents(readIssues, "database");
|
|
12251
12163
|
let shortest = [];
|
|
12252
12164
|
for (const branchKey of this.getBranchCatalogKeys()) {
|
|
12253
|
-
const
|
|
12254
|
-
if (
|
|
12255
|
-
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;
|
|
12256
12168
|
}
|
|
12257
12169
|
}
|
|
12258
12170
|
return shortest.map((hop) => this.resolveFilePathRecord(hop));
|
|
@@ -12300,13 +12212,13 @@ var Indexer = class _Indexer {
|
|
|
12300
12212
|
}
|
|
12301
12213
|
}
|
|
12302
12214
|
if (!found) continue;
|
|
12303
|
-
const
|
|
12215
|
+
const path33 = [];
|
|
12304
12216
|
let currentSymbolId = toSymbolId;
|
|
12305
12217
|
while (true) {
|
|
12306
12218
|
const symbol = symbolsById.get(currentSymbolId);
|
|
12307
12219
|
if (!symbol) break;
|
|
12308
12220
|
const parent = parentBySymbolId.get(currentSymbolId);
|
|
12309
|
-
|
|
12221
|
+
path33.push({
|
|
12310
12222
|
symbolId: symbol.id,
|
|
12311
12223
|
symbolName: symbol.name,
|
|
12312
12224
|
filePath: symbol.filePath,
|
|
@@ -12316,9 +12228,9 @@ var Indexer = class _Indexer {
|
|
|
12316
12228
|
if (!parent) break;
|
|
12317
12229
|
currentSymbolId = parent.parentId;
|
|
12318
12230
|
}
|
|
12319
|
-
|
|
12320
|
-
if (
|
|
12321
|
-
shortest =
|
|
12231
|
+
path33.reverse();
|
|
12232
|
+
if (path33.length > 0 && (shortest.length === 0 || path33.length < shortest.length)) {
|
|
12233
|
+
shortest = path33;
|
|
12322
12234
|
}
|
|
12323
12235
|
}
|
|
12324
12236
|
return shortest.map((hop) => this.resolveFilePathRecord(hop));
|
|
@@ -12654,7 +12566,6 @@ var Indexer = class _Indexer {
|
|
|
12654
12566
|
this.store = null;
|
|
12655
12567
|
this.invertedIndex = null;
|
|
12656
12568
|
this.provider = null;
|
|
12657
|
-
this.reranker = null;
|
|
12658
12569
|
this.configuredProviderInfo = null;
|
|
12659
12570
|
this.indexCompatibility = null;
|
|
12660
12571
|
this.initializationMode = "none";
|
|
@@ -12968,8 +12879,8 @@ function formatExactSearchHandoff(results) {
|
|
|
12968
12879
|
}
|
|
12969
12880
|
function formatContextEvidence(result, index) {
|
|
12970
12881
|
const symbol = result.name ? ` ${JSON.stringify(compactEvidenceValue(result.name, 80))}` : "";
|
|
12971
|
-
const
|
|
12972
|
-
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)})`;
|
|
12973
12884
|
}
|
|
12974
12885
|
function formatContextPack(heading, selected, candidateCount, duplicateCount, limitOmittedCount, budgetOmittedCount, includeExactSearchHandoff) {
|
|
12975
12886
|
const lines = selected.map((result, index) => formatContextEvidence(result, index + 1));
|
|
@@ -13623,7 +13534,7 @@ function getErrorMessage4(error) {
|
|
|
13623
13534
|
return error instanceof Error ? error.message : String(error);
|
|
13624
13535
|
}
|
|
13625
13536
|
function runCommand(file, args, options) {
|
|
13626
|
-
return new Promise((
|
|
13537
|
+
return new Promise((resolve20, reject) => {
|
|
13627
13538
|
childProcess.execFile(
|
|
13628
13539
|
file,
|
|
13629
13540
|
args,
|
|
@@ -13633,7 +13544,7 @@ function runCommand(file, args, options) {
|
|
|
13633
13544
|
reject(error);
|
|
13634
13545
|
return;
|
|
13635
13546
|
}
|
|
13636
|
-
|
|
13547
|
+
resolve20(stdout);
|
|
13637
13548
|
}
|
|
13638
13549
|
);
|
|
13639
13550
|
});
|
|
@@ -13778,10 +13689,10 @@ function safeFailureMessage(error) {
|
|
|
13778
13689
|
}
|
|
13779
13690
|
function cancellableDelay(delayMs, signal) {
|
|
13780
13691
|
if (signal.aborted) return Promise.reject(new AutoIndexCancelledError());
|
|
13781
|
-
return new Promise((
|
|
13692
|
+
return new Promise((resolve20, reject) => {
|
|
13782
13693
|
const timer = setTimeout(() => {
|
|
13783
13694
|
signal.removeEventListener("abort", onAbort);
|
|
13784
|
-
|
|
13695
|
+
resolve20();
|
|
13785
13696
|
}, delayMs);
|
|
13786
13697
|
timer.unref?.();
|
|
13787
13698
|
const onAbort = () => {
|
|
@@ -13793,15 +13704,15 @@ function cancellableDelay(delayMs, signal) {
|
|
|
13793
13704
|
}
|
|
13794
13705
|
function withTimeout(promise, timeoutMs) {
|
|
13795
13706
|
if (timeoutMs <= 0) return Promise.resolve(void 0);
|
|
13796
|
-
return new Promise((
|
|
13797
|
-
const timer = setTimeout(() =>
|
|
13707
|
+
return new Promise((resolve20) => {
|
|
13708
|
+
const timer = setTimeout(() => resolve20(void 0), timeoutMs);
|
|
13798
13709
|
timer.unref?.();
|
|
13799
13710
|
void promise.then((value) => {
|
|
13800
13711
|
clearTimeout(timer);
|
|
13801
|
-
|
|
13712
|
+
resolve20(value);
|
|
13802
13713
|
}, () => {
|
|
13803
13714
|
clearTimeout(timer);
|
|
13804
|
-
|
|
13715
|
+
resolve20(void 0);
|
|
13805
13716
|
});
|
|
13806
13717
|
});
|
|
13807
13718
|
}
|
|
@@ -14183,17 +14094,17 @@ var AutoIndexCoordinator = class {
|
|
|
14183
14094
|
}
|
|
14184
14095
|
}
|
|
14185
14096
|
waitForBatteryRetry(delayMs) {
|
|
14186
|
-
return new Promise((
|
|
14097
|
+
return new Promise((resolve20) => {
|
|
14187
14098
|
const timer = setTimeout(() => {
|
|
14188
14099
|
if (this.batteryRetryTimer === timer) {
|
|
14189
14100
|
this.batteryRetryTimer = null;
|
|
14190
14101
|
this.resolveBatteryRetry = null;
|
|
14191
14102
|
}
|
|
14192
|
-
|
|
14103
|
+
resolve20();
|
|
14193
14104
|
}, delayMs);
|
|
14194
14105
|
timer.unref?.();
|
|
14195
14106
|
this.batteryRetryTimer = timer;
|
|
14196
|
-
this.resolveBatteryRetry =
|
|
14107
|
+
this.resolveBatteryRetry = resolve20;
|
|
14197
14108
|
});
|
|
14198
14109
|
}
|
|
14199
14110
|
cancelBatteryRetry() {
|
|
@@ -14201,9 +14112,9 @@ var AutoIndexCoordinator = class {
|
|
|
14201
14112
|
clearTimeout(this.batteryRetryTimer);
|
|
14202
14113
|
this.batteryRetryTimer = null;
|
|
14203
14114
|
}
|
|
14204
|
-
const
|
|
14115
|
+
const resolve20 = this.resolveBatteryRetry;
|
|
14205
14116
|
this.resolveBatteryRetry = null;
|
|
14206
|
-
|
|
14117
|
+
resolve20?.();
|
|
14207
14118
|
}
|
|
14208
14119
|
finishBatteryCheck(batteryCheck) {
|
|
14209
14120
|
if (this.batteryCheck !== batteryCheck) return;
|
|
@@ -14878,12 +14789,12 @@ async function getCallGraphPath(projectRoot, host, from, to, maxDepth, fromFileP
|
|
|
14878
14789
|
if (fromResolution.status !== "resolved" || toResolution.status !== "resolved") {
|
|
14879
14790
|
return { from: fromResolution, to: toResolution, path: [] };
|
|
14880
14791
|
}
|
|
14881
|
-
const
|
|
14792
|
+
const path33 = await indexer.findCallPathBySymbolIds(
|
|
14882
14793
|
fromResolution.symbolId,
|
|
14883
14794
|
toResolution.symbolId,
|
|
14884
14795
|
maxDepth
|
|
14885
14796
|
);
|
|
14886
|
-
return { from: fromResolution, to: toResolution, path:
|
|
14797
|
+
return { from: fromResolution, to: toResolution, path: path33 };
|
|
14887
14798
|
}
|
|
14888
14799
|
async function runIndexCodebase(projectRoot, host, args, onProgress) {
|
|
14889
14800
|
const root = getProjectRoot(projectRoot, host);
|
|
@@ -15508,7 +15419,7 @@ async function resolveCodebaseContextUnmeasured(projectRoot, host, input) {
|
|
|
15508
15419
|
const directory = input.directory ?? void 0;
|
|
15509
15420
|
const tokenBudget = input.tokenBudget ?? void 0;
|
|
15510
15421
|
if (from && to) {
|
|
15511
|
-
const
|
|
15422
|
+
const path33 = await getCallGraphPath(
|
|
15512
15423
|
projectRoot,
|
|
15513
15424
|
host,
|
|
15514
15425
|
from,
|
|
@@ -15517,25 +15428,25 @@ async function resolveCodebaseContextUnmeasured(projectRoot, host, input) {
|
|
|
15517
15428
|
fromFilePath,
|
|
15518
15429
|
toFilePath
|
|
15519
15430
|
);
|
|
15520
|
-
const pathText = formatCallGraphPathResult(
|
|
15521
|
-
if (
|
|
15431
|
+
const pathText = formatCallGraphPathResult(path33);
|
|
15432
|
+
if (path33.path.length > 0) {
|
|
15522
15433
|
const fitted2 = fitTextToContextBudget(
|
|
15523
15434
|
pathText,
|
|
15524
15435
|
tokenBudget
|
|
15525
15436
|
);
|
|
15526
15437
|
return {
|
|
15527
15438
|
text: fitted2.text,
|
|
15528
|
-
details: fittedDetails("path", fitted2,
|
|
15439
|
+
details: fittedDetails("path", fitted2, path33.path.length)
|
|
15529
15440
|
};
|
|
15530
15441
|
}
|
|
15531
|
-
if (
|
|
15442
|
+
if (path33.from.status !== "resolved" || path33.to.status !== "resolved") {
|
|
15532
15443
|
const fitted2 = fitTextToContextBudget(pathText, tokenBudget);
|
|
15533
15444
|
return {
|
|
15534
15445
|
text: fitted2.text,
|
|
15535
15446
|
details: fittedDetails("path", fitted2, 0)
|
|
15536
15447
|
};
|
|
15537
15448
|
}
|
|
15538
|
-
const resolvedFrom =
|
|
15449
|
+
const resolvedFrom = path33.from;
|
|
15539
15450
|
const { callers } = await getCallGraphData(projectRoot, host, {
|
|
15540
15451
|
name: to,
|
|
15541
15452
|
direction: "callers",
|
|
@@ -16012,9 +15923,9 @@ function getRelevantEvidence(query) {
|
|
|
16012
15923
|
});
|
|
16013
15924
|
}
|
|
16014
15925
|
if (query.expected.acceptableFiles) {
|
|
16015
|
-
for (const
|
|
15926
|
+
for (const path33 of query.expected.acceptableFiles) {
|
|
16016
15927
|
legacyEvidence.push({
|
|
16017
|
-
path:
|
|
15928
|
+
path: path33,
|
|
16018
15929
|
...query.expected.symbol !== void 0 ? { symbol: query.expected.symbol } : {},
|
|
16019
15930
|
relevance: 1
|
|
16020
15931
|
});
|
|
@@ -16511,68 +16422,68 @@ function isStringArray4(value) {
|
|
|
16511
16422
|
function isNonEmptyString(value) {
|
|
16512
16423
|
return typeof value === "string" && value.trim().length > 0;
|
|
16513
16424
|
}
|
|
16514
|
-
function asPositiveNumber(value,
|
|
16425
|
+
function asPositiveNumber(value, path33) {
|
|
16515
16426
|
if (typeof value !== "number" || Number.isNaN(value) || value < 0) {
|
|
16516
|
-
throw new Error(`${
|
|
16427
|
+
throw new Error(`${path33} must be a non-negative number`);
|
|
16517
16428
|
}
|
|
16518
16429
|
return value;
|
|
16519
16430
|
}
|
|
16520
|
-
function parseQueryType(value,
|
|
16431
|
+
function parseQueryType(value, path33) {
|
|
16521
16432
|
if (value === "definition" || value === "implementation-intent" || value === "similarity" || value === "keyword-heavy" || value === "conceptual") {
|
|
16522
16433
|
return value;
|
|
16523
16434
|
}
|
|
16524
16435
|
throw new Error(
|
|
16525
|
-
`${
|
|
16436
|
+
`${path33} must be one of: definition, implementation-intent, similarity, keyword-heavy, conceptual`
|
|
16526
16437
|
);
|
|
16527
16438
|
}
|
|
16528
|
-
function parseExpectedRoute(value,
|
|
16439
|
+
function parseExpectedRoute(value, path33) {
|
|
16529
16440
|
if (value === void 0) return void 0;
|
|
16530
16441
|
if (value === "search" || value === "definition") return value;
|
|
16531
|
-
throw new Error(`${
|
|
16442
|
+
throw new Error(`${path33} must be one of: search, definition`);
|
|
16532
16443
|
}
|
|
16533
|
-
function parseExpectedOutcome(value,
|
|
16444
|
+
function parseExpectedOutcome(value, path33) {
|
|
16534
16445
|
if (value === void 0) return void 0;
|
|
16535
16446
|
if (value === "results" || value === "no-results") {
|
|
16536
16447
|
return value;
|
|
16537
16448
|
}
|
|
16538
|
-
throw new Error(`${
|
|
16449
|
+
throw new Error(`${path33} must be one of: results, no-results`);
|
|
16539
16450
|
}
|
|
16540
|
-
function parseRecoveryExpectation(value,
|
|
16451
|
+
function parseRecoveryExpectation(value, path33) {
|
|
16541
16452
|
if (value === void 0) return void 0;
|
|
16542
16453
|
if (value === "none" || value === "filter-relaxed") {
|
|
16543
16454
|
return value;
|
|
16544
16455
|
}
|
|
16545
|
-
throw new Error(`${
|
|
16456
|
+
throw new Error(`${path33} must be one of: none, filter-relaxed`);
|
|
16546
16457
|
}
|
|
16547
|
-
function parseQueryDifficulty(value,
|
|
16458
|
+
function parseQueryDifficulty(value, path33) {
|
|
16548
16459
|
if (value === void 0) return void 0;
|
|
16549
16460
|
if (value === "easy" || value === "medium" || value === "hard") {
|
|
16550
16461
|
return value;
|
|
16551
16462
|
}
|
|
16552
|
-
throw new Error(`${
|
|
16463
|
+
throw new Error(`${path33} must be one of: easy, medium, hard`);
|
|
16553
16464
|
}
|
|
16554
|
-
function parseQueryTags(value,
|
|
16465
|
+
function parseQueryTags(value, path33) {
|
|
16555
16466
|
if (value === void 0) return void 0;
|
|
16556
16467
|
if (!isStringArray4(value) || value.some((tag) => tag.trim().length === 0)) {
|
|
16557
|
-
throw new Error(`${
|
|
16468
|
+
throw new Error(`${path33} must be an array of non-empty strings`);
|
|
16558
16469
|
}
|
|
16559
16470
|
if (value.length > 16) {
|
|
16560
|
-
throw new Error(`${
|
|
16471
|
+
throw new Error(`${path33} must contain at most 16 tags`);
|
|
16561
16472
|
}
|
|
16562
16473
|
return value;
|
|
16563
16474
|
}
|
|
16564
|
-
function parseQueryArgs(value,
|
|
16475
|
+
function parseQueryArgs(value, path33) {
|
|
16565
16476
|
if (value === void 0) return void 0;
|
|
16566
16477
|
if (!isRecord3(value)) {
|
|
16567
|
-
throw new Error(`${
|
|
16568
|
-
}
|
|
16569
|
-
const symbol = parseStringOrUndefined(value.symbol, `${
|
|
16570
|
-
const filePath = parseStringOrUndefined(value.filePath, `${
|
|
16571
|
-
const fileType = parseStringOrUndefined(value.fileType, `${
|
|
16572
|
-
const directory = parseStringOrUndefined(value.directory, `${
|
|
16573
|
-
const callerLimit = parsePositiveIntegerOrUndefined(value.callerLimit, `${
|
|
16574
|
-
const calleeLimit = parsePositiveIntegerOrUndefined(value.calleeLimit, `${
|
|
16575
|
-
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`);
|
|
16576
16487
|
return {
|
|
16577
16488
|
...symbol !== void 0 ? { symbol } : {},
|
|
16578
16489
|
...filePath !== void 0 ? { filePath } : {},
|
|
@@ -16583,50 +16494,50 @@ function parseQueryArgs(value, path31) {
|
|
|
16583
16494
|
...tokenBudget !== void 0 ? { tokenBudget } : {}
|
|
16584
16495
|
};
|
|
16585
16496
|
}
|
|
16586
|
-
function parsePositiveIntegerOrUndefined(value,
|
|
16497
|
+
function parsePositiveIntegerOrUndefined(value, path33) {
|
|
16587
16498
|
if (value === void 0 || value === null) return void 0;
|
|
16588
16499
|
if (typeof value !== "number" || !Number.isInteger(value) || value <= 0) {
|
|
16589
|
-
throw new Error(`${
|
|
16500
|
+
throw new Error(`${path33} must be a positive integer`);
|
|
16590
16501
|
}
|
|
16591
16502
|
return value;
|
|
16592
16503
|
}
|
|
16593
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-]+)*)?$/;
|
|
16594
|
-
function parseSemanticVersion(value,
|
|
16505
|
+
function parseSemanticVersion(value, path33) {
|
|
16595
16506
|
if (!isNonEmptyString(value)) {
|
|
16596
|
-
throw new Error(`${
|
|
16507
|
+
throw new Error(`${path33} must be a non-empty string`);
|
|
16597
16508
|
}
|
|
16598
16509
|
if (!SEMVER_VERSION_PATTERN.test(value)) {
|
|
16599
|
-
throw new Error(`${
|
|
16510
|
+
throw new Error(`${path33} must be a valid semantic version (MAJOR.MINOR.PATCH)`);
|
|
16600
16511
|
}
|
|
16601
16512
|
return value;
|
|
16602
16513
|
}
|
|
16603
|
-
function parseRetrievalMode(value,
|
|
16514
|
+
function parseRetrievalMode(value, path33) {
|
|
16604
16515
|
if (value === void 0 || value === "search") return "search";
|
|
16605
16516
|
if (value === "context" || value === "edit-context") return value;
|
|
16606
|
-
throw new Error(`${
|
|
16517
|
+
throw new Error(`${path33} must be one of: search, context, edit-context`);
|
|
16607
16518
|
}
|
|
16608
|
-
function parseStringOrUndefined(value,
|
|
16519
|
+
function parseStringOrUndefined(value, path33) {
|
|
16609
16520
|
if (value === void 0 || value === null) return void 0;
|
|
16610
16521
|
if (!isNonEmptyString(value)) {
|
|
16611
|
-
throw new Error(`${
|
|
16522
|
+
throw new Error(`${path33} must be a non-empty string`);
|
|
16612
16523
|
}
|
|
16613
16524
|
return value;
|
|
16614
16525
|
}
|
|
16615
|
-
function parseGradedEvidence(value,
|
|
16526
|
+
function parseGradedEvidence(value, path33) {
|
|
16616
16527
|
if (value === void 0) return [];
|
|
16617
16528
|
if (!Array.isArray(value)) {
|
|
16618
|
-
throw new Error(`${
|
|
16529
|
+
throw new Error(`${path33} must be an array`);
|
|
16619
16530
|
}
|
|
16620
16531
|
return value.map((entry, index) => {
|
|
16621
16532
|
if (!isRecord3(entry)) {
|
|
16622
|
-
throw new Error(`${
|
|
16533
|
+
throw new Error(`${path33}[${index}] must be an object`);
|
|
16623
16534
|
}
|
|
16624
|
-
const evidencePath = parseStringOrUndefined(entry.path, `${
|
|
16535
|
+
const evidencePath = parseStringOrUndefined(entry.path, `${path33}[${index}].path`);
|
|
16625
16536
|
if (evidencePath === void 0) {
|
|
16626
|
-
throw new Error(`${
|
|
16537
|
+
throw new Error(`${path33}[${index}].path is required`);
|
|
16627
16538
|
}
|
|
16628
|
-
const symbol = parseStringOrUndefined(entry.symbol, `${
|
|
16629
|
-
const relevance = parseEvidenceRelevance(entry.relevance, `${
|
|
16539
|
+
const symbol = parseStringOrUndefined(entry.symbol, `${path33}[${index}].symbol`);
|
|
16540
|
+
const relevance = parseEvidenceRelevance(entry.relevance, `${path33}[${index}].relevance`);
|
|
16630
16541
|
return {
|
|
16631
16542
|
path: evidencePath,
|
|
16632
16543
|
...symbol !== void 0 ? { symbol } : {},
|
|
@@ -16634,27 +16545,27 @@ function parseGradedEvidence(value, path31) {
|
|
|
16634
16545
|
};
|
|
16635
16546
|
});
|
|
16636
16547
|
}
|
|
16637
|
-
function parseEvidenceRelevance(value,
|
|
16548
|
+
function parseEvidenceRelevance(value, path33) {
|
|
16638
16549
|
if (value === void 0) {
|
|
16639
|
-
throw new Error(`${
|
|
16550
|
+
throw new Error(`${path33} is required`);
|
|
16640
16551
|
}
|
|
16641
16552
|
if (value !== 1 && value !== 2 && value !== 3) {
|
|
16642
|
-
throw new Error(`${
|
|
16553
|
+
throw new Error(`${path33} must be 1, 2, or 3`);
|
|
16643
16554
|
}
|
|
16644
16555
|
return value;
|
|
16645
16556
|
}
|
|
16646
|
-
function parseExpectedGraphNeighbor(value,
|
|
16557
|
+
function parseExpectedGraphNeighbor(value, path33) {
|
|
16647
16558
|
if (value === void 0) return void 0;
|
|
16648
16559
|
if (!isRecord3(value)) {
|
|
16649
|
-
throw new Error(`${
|
|
16560
|
+
throw new Error(`${path33} must be an object`);
|
|
16650
16561
|
}
|
|
16651
16562
|
if (value.direction !== "caller" && value.direction !== "callee") {
|
|
16652
|
-
throw new Error(`${
|
|
16563
|
+
throw new Error(`${path33}.direction must be one of: caller, callee`);
|
|
16653
16564
|
}
|
|
16654
|
-
const filePath = parseStringOrUndefined(value.filePath, `${
|
|
16655
|
-
const symbol = parseStringOrUndefined(value.symbol, `${
|
|
16565
|
+
const filePath = parseStringOrUndefined(value.filePath, `${path33}.filePath`);
|
|
16566
|
+
const symbol = parseStringOrUndefined(value.symbol, `${path33}.symbol`);
|
|
16656
16567
|
if (filePath === void 0 && symbol === void 0) {
|
|
16657
|
-
throw new Error(`${
|
|
16568
|
+
throw new Error(`${path33} must include filePath or symbol`);
|
|
16658
16569
|
}
|
|
16659
16570
|
return {
|
|
16660
16571
|
direction: value.direction,
|
|
@@ -16662,9 +16573,9 @@ function parseExpectedGraphNeighbor(value, path31) {
|
|
|
16662
16573
|
...symbol !== void 0 ? { symbol } : {}
|
|
16663
16574
|
};
|
|
16664
16575
|
}
|
|
16665
|
-
function parseExpected(input,
|
|
16576
|
+
function parseExpected(input, path33) {
|
|
16666
16577
|
if (!isRecord3(input)) {
|
|
16667
|
-
throw new Error(`${
|
|
16578
|
+
throw new Error(`${path33} must be an object`);
|
|
16668
16579
|
}
|
|
16669
16580
|
const filePathRaw = input.filePath;
|
|
16670
16581
|
const acceptableFilesRaw = input.acceptableFiles;
|
|
@@ -16675,29 +16586,29 @@ function parseExpected(input, path31) {
|
|
|
16675
16586
|
const recoveryExpectationRaw = input.recoveryExpectation;
|
|
16676
16587
|
const gradedEvidenceRaw = input.gradedEvidence;
|
|
16677
16588
|
const graphNeighborRaw = input.graphNeighbor;
|
|
16678
|
-
const filePath = parseStringOrUndefined(filePathRaw, `${
|
|
16589
|
+
const filePath = parseStringOrUndefined(filePathRaw, `${path33}.filePath`);
|
|
16679
16590
|
const acceptableFiles = isStringArray4(acceptableFilesRaw) ? acceptableFilesRaw : void 0;
|
|
16680
|
-
const gradedEvidence = parseGradedEvidence(gradedEvidenceRaw, `${
|
|
16681
|
-
const graphNeighbor = parseExpectedGraphNeighbor(graphNeighborRaw, `${
|
|
16682
|
-
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`);
|
|
16683
16594
|
if (expectedOutcome !== "no-results" && !filePath && (!acceptableFiles || acceptableFiles.length === 0) && gradedEvidence.length === 0) {
|
|
16684
16595
|
throw new Error(
|
|
16685
|
-
`${
|
|
16596
|
+
`${path33} must include expected.filePath, expected.acceptableFiles, or expected.gradedEvidence`
|
|
16686
16597
|
);
|
|
16687
16598
|
}
|
|
16688
16599
|
if (acceptableFilesRaw !== void 0 && !isStringArray4(acceptableFilesRaw)) {
|
|
16689
|
-
throw new Error(`${
|
|
16600
|
+
throw new Error(`${path33}.acceptableFiles must be an array of strings`);
|
|
16690
16601
|
}
|
|
16691
16602
|
if (symbolRaw !== void 0 && typeof symbolRaw !== "string") {
|
|
16692
|
-
throw new Error(`${
|
|
16603
|
+
throw new Error(`${path33}.symbol must be a string when provided`);
|
|
16693
16604
|
}
|
|
16694
16605
|
if (branchRaw !== void 0 && typeof branchRaw !== "string") {
|
|
16695
|
-
throw new Error(`${
|
|
16606
|
+
throw new Error(`${path33}.branch must be a string when provided`);
|
|
16696
16607
|
}
|
|
16697
|
-
const expectedRoute = parseExpectedRoute(expectedRouteRaw, `${
|
|
16608
|
+
const expectedRoute = parseExpectedRoute(expectedRouteRaw, `${path33}.expectedRoute`);
|
|
16698
16609
|
const recoveryExpectation = parseRecoveryExpectation(
|
|
16699
16610
|
recoveryExpectationRaw,
|
|
16700
|
-
`${
|
|
16611
|
+
`${path33}.recoveryExpectation`
|
|
16701
16612
|
);
|
|
16702
16613
|
return {
|
|
16703
16614
|
filePath,
|
|
@@ -16711,13 +16622,13 @@ function parseExpected(input, path31) {
|
|
|
16711
16622
|
...graphNeighbor !== void 0 ? { graphNeighbor } : {}
|
|
16712
16623
|
};
|
|
16713
16624
|
}
|
|
16714
|
-
function parseQueryLanguage(value,
|
|
16715
|
-
return parseStringOrUndefined(value,
|
|
16625
|
+
function parseQueryLanguage(value, path33) {
|
|
16626
|
+
return parseStringOrUndefined(value, path33);
|
|
16716
16627
|
}
|
|
16717
16628
|
function parseQuery(input, index) {
|
|
16718
|
-
const
|
|
16629
|
+
const path33 = `queries[${index}]`;
|
|
16719
16630
|
if (!isRecord3(input)) {
|
|
16720
|
-
throw new Error(`${
|
|
16631
|
+
throw new Error(`${path33} must be an object`);
|
|
16721
16632
|
}
|
|
16722
16633
|
const id = input.id;
|
|
16723
16634
|
const query = input.query;
|
|
@@ -16729,21 +16640,21 @@ function parseQuery(input, index) {
|
|
|
16729
16640
|
const tags = input.tags;
|
|
16730
16641
|
const args = input.args;
|
|
16731
16642
|
if (typeof id !== "string" || id.trim().length === 0) {
|
|
16732
|
-
throw new Error(`${
|
|
16643
|
+
throw new Error(`${path33}.id must be a non-empty string`);
|
|
16733
16644
|
}
|
|
16734
16645
|
if (typeof query !== "string" || query.trim().length === 0) {
|
|
16735
|
-
throw new Error(`${
|
|
16646
|
+
throw new Error(`${path33}.query must be a non-empty string`);
|
|
16736
16647
|
}
|
|
16737
16648
|
return {
|
|
16738
16649
|
id,
|
|
16739
16650
|
query,
|
|
16740
|
-
queryType: parseQueryType(queryType, `${
|
|
16741
|
-
retrievalMode: parseRetrievalMode(retrievalMode, `${
|
|
16742
|
-
language: parseQueryLanguage(language, `${
|
|
16743
|
-
difficulty: parseQueryDifficulty(difficulty, `${
|
|
16744
|
-
args: parseQueryArgs(args, `${
|
|
16745
|
-
tags: parseQueryTags(tags, `${
|
|
16746
|
-
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`)
|
|
16747
16658
|
};
|
|
16748
16659
|
}
|
|
16749
16660
|
function parseGoldenDataset(raw, sourceLabel) {
|
|
@@ -17709,7 +17620,7 @@ async function executeCallGraph(projectRoot, host, args) {
|
|
|
17709
17620
|
return { text: formatCallGraphResult(await getCallGraphData(projectRoot, host, args)) };
|
|
17710
17621
|
}
|
|
17711
17622
|
async function executeCallGraphPath(projectRoot, host, args) {
|
|
17712
|
-
const
|
|
17623
|
+
const path33 = await getCallGraphPath(
|
|
17713
17624
|
projectRoot,
|
|
17714
17625
|
host,
|
|
17715
17626
|
args.from,
|
|
@@ -17718,7 +17629,7 @@ async function executeCallGraphPath(projectRoot, host, args) {
|
|
|
17718
17629
|
args.fromFilePath,
|
|
17719
17630
|
args.toFilePath
|
|
17720
17631
|
);
|
|
17721
|
-
return { text: formatCallGraphPathResult(
|
|
17632
|
+
return { text: formatCallGraphPathResult(path33) };
|
|
17722
17633
|
}
|
|
17723
17634
|
async function executeCodeCommunities(projectRoot, host, args) {
|
|
17724
17635
|
const result = await getCodeCommunities(projectRoot, host, args);
|
|
@@ -18205,7 +18116,7 @@ function createMcpServer(projectRoot, config, host) {
|
|
|
18205
18116
|
}
|
|
18206
18117
|
|
|
18207
18118
|
// src/watcher/file-watcher.ts
|
|
18208
|
-
import { existsSync as existsSync15 } from "fs";
|
|
18119
|
+
import { existsSync as existsSync15, statSync as statSync6 } from "fs";
|
|
18209
18120
|
|
|
18210
18121
|
// node_modules/chokidar/index.js
|
|
18211
18122
|
import { EventEmitter as EventEmitter2 } from "events";
|
|
@@ -18297,7 +18208,7 @@ var ReaddirpStream = class extends Readable {
|
|
|
18297
18208
|
this._directoryFilter = normalizeFilter(opts.directoryFilter);
|
|
18298
18209
|
const statMethod = opts.lstat ? lstat : stat;
|
|
18299
18210
|
if (wantBigintFsStats) {
|
|
18300
|
-
this._stat = (
|
|
18211
|
+
this._stat = (path33) => statMethod(path33, { bigint: true });
|
|
18301
18212
|
} else {
|
|
18302
18213
|
this._stat = statMethod;
|
|
18303
18214
|
}
|
|
@@ -18322,8 +18233,8 @@ var ReaddirpStream = class extends Readable {
|
|
|
18322
18233
|
const par = this.parent;
|
|
18323
18234
|
const fil = par && par.files;
|
|
18324
18235
|
if (fil && fil.length > 0) {
|
|
18325
|
-
const { path:
|
|
18326
|
-
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));
|
|
18327
18238
|
const awaited = await Promise.all(slice);
|
|
18328
18239
|
for (const entry of awaited) {
|
|
18329
18240
|
if (!entry)
|
|
@@ -18363,20 +18274,20 @@ var ReaddirpStream = class extends Readable {
|
|
|
18363
18274
|
this.reading = false;
|
|
18364
18275
|
}
|
|
18365
18276
|
}
|
|
18366
|
-
async _exploreDir(
|
|
18277
|
+
async _exploreDir(path33, depth) {
|
|
18367
18278
|
let files;
|
|
18368
18279
|
try {
|
|
18369
|
-
files = await readdir(
|
|
18280
|
+
files = await readdir(path33, this._rdOptions);
|
|
18370
18281
|
} catch (error) {
|
|
18371
18282
|
this._onError(error);
|
|
18372
18283
|
}
|
|
18373
|
-
return { files, depth, path:
|
|
18284
|
+
return { files, depth, path: path33 };
|
|
18374
18285
|
}
|
|
18375
|
-
async _formatEntry(dirent,
|
|
18286
|
+
async _formatEntry(dirent, path33) {
|
|
18376
18287
|
let entry;
|
|
18377
18288
|
const basename8 = this._isDirent ? dirent.name : dirent;
|
|
18378
18289
|
try {
|
|
18379
|
-
const fullPath = presolve(pjoin(
|
|
18290
|
+
const fullPath = presolve(pjoin(path33, basename8));
|
|
18380
18291
|
entry = { path: prelative(this._root, fullPath), fullPath, basename: basename8 };
|
|
18381
18292
|
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
18382
18293
|
} catch (err) {
|
|
@@ -18776,16 +18687,16 @@ var delFromSet = (main, prop, item) => {
|
|
|
18776
18687
|
};
|
|
18777
18688
|
var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
|
|
18778
18689
|
var FsWatchInstances = /* @__PURE__ */ new Map();
|
|
18779
|
-
function createFsWatchInstance(
|
|
18690
|
+
function createFsWatchInstance(path33, options, listener, errHandler, emitRaw) {
|
|
18780
18691
|
const handleEvent = (rawEvent, evPath) => {
|
|
18781
|
-
listener(
|
|
18782
|
-
emitRaw(rawEvent, evPath, { watchedPath:
|
|
18783
|
-
if (evPath &&
|
|
18784
|
-
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));
|
|
18785
18696
|
}
|
|
18786
18697
|
};
|
|
18787
18698
|
try {
|
|
18788
|
-
return fs_watch(
|
|
18699
|
+
return fs_watch(path33, {
|
|
18789
18700
|
persistent: options.persistent
|
|
18790
18701
|
}, handleEvent);
|
|
18791
18702
|
} catch (error) {
|
|
@@ -18801,12 +18712,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
|
|
|
18801
18712
|
listener(val1, val2, val3);
|
|
18802
18713
|
});
|
|
18803
18714
|
};
|
|
18804
|
-
var setFsWatchListener = (
|
|
18715
|
+
var setFsWatchListener = (path33, fullPath, options, handlers) => {
|
|
18805
18716
|
const { listener, errHandler, rawEmitter } = handlers;
|
|
18806
18717
|
let cont = FsWatchInstances.get(fullPath);
|
|
18807
18718
|
let watcher;
|
|
18808
18719
|
if (!options.persistent) {
|
|
18809
|
-
watcher = createFsWatchInstance(
|
|
18720
|
+
watcher = createFsWatchInstance(path33, options, listener, errHandler, rawEmitter);
|
|
18810
18721
|
if (!watcher)
|
|
18811
18722
|
return;
|
|
18812
18723
|
return watcher.close.bind(watcher);
|
|
@@ -18817,7 +18728,7 @@ var setFsWatchListener = (path31, fullPath, options, handlers) => {
|
|
|
18817
18728
|
addAndConvert(cont, KEY_RAW, rawEmitter);
|
|
18818
18729
|
} else {
|
|
18819
18730
|
watcher = createFsWatchInstance(
|
|
18820
|
-
|
|
18731
|
+
path33,
|
|
18821
18732
|
options,
|
|
18822
18733
|
fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
|
|
18823
18734
|
errHandler,
|
|
@@ -18832,7 +18743,7 @@ var setFsWatchListener = (path31, fullPath, options, handlers) => {
|
|
|
18832
18743
|
cont.watcherUnusable = true;
|
|
18833
18744
|
if (isWindows && error.code === "EPERM") {
|
|
18834
18745
|
try {
|
|
18835
|
-
const fd = await open(
|
|
18746
|
+
const fd = await open(path33, "r");
|
|
18836
18747
|
await fd.close();
|
|
18837
18748
|
broadcastErr(error);
|
|
18838
18749
|
} catch (err) {
|
|
@@ -18863,7 +18774,7 @@ var setFsWatchListener = (path31, fullPath, options, handlers) => {
|
|
|
18863
18774
|
};
|
|
18864
18775
|
};
|
|
18865
18776
|
var FsWatchFileInstances = /* @__PURE__ */ new Map();
|
|
18866
|
-
var setFsWatchFileListener = (
|
|
18777
|
+
var setFsWatchFileListener = (path33, fullPath, options, handlers) => {
|
|
18867
18778
|
const { listener, rawEmitter } = handlers;
|
|
18868
18779
|
let cont = FsWatchFileInstances.get(fullPath);
|
|
18869
18780
|
const copts = cont && cont.options;
|
|
@@ -18885,7 +18796,7 @@ var setFsWatchFileListener = (path31, fullPath, options, handlers) => {
|
|
|
18885
18796
|
});
|
|
18886
18797
|
const currmtime = curr.mtimeMs;
|
|
18887
18798
|
if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
|
|
18888
|
-
foreach(cont.listeners, (listener2) => listener2(
|
|
18799
|
+
foreach(cont.listeners, (listener2) => listener2(path33, curr));
|
|
18889
18800
|
}
|
|
18890
18801
|
})
|
|
18891
18802
|
};
|
|
@@ -18915,13 +18826,13 @@ var NodeFsHandler = class {
|
|
|
18915
18826
|
* @param listener on fs change
|
|
18916
18827
|
* @returns closer for the watcher instance
|
|
18917
18828
|
*/
|
|
18918
|
-
_watchWithNodeFs(
|
|
18829
|
+
_watchWithNodeFs(path33, listener) {
|
|
18919
18830
|
const opts = this.fsw.options;
|
|
18920
|
-
const directory = sp.dirname(
|
|
18921
|
-
const basename8 = sp.basename(
|
|
18831
|
+
const directory = sp.dirname(path33);
|
|
18832
|
+
const basename8 = sp.basename(path33);
|
|
18922
18833
|
const parent = this.fsw._getWatchedDir(directory);
|
|
18923
18834
|
parent.add(basename8);
|
|
18924
|
-
const absolutePath = sp.resolve(
|
|
18835
|
+
const absolutePath = sp.resolve(path33);
|
|
18925
18836
|
const options = {
|
|
18926
18837
|
persistent: opts.persistent
|
|
18927
18838
|
};
|
|
@@ -18931,12 +18842,12 @@ var NodeFsHandler = class {
|
|
|
18931
18842
|
if (opts.usePolling) {
|
|
18932
18843
|
const enableBin = opts.interval !== opts.binaryInterval;
|
|
18933
18844
|
options.interval = enableBin && isBinaryPath(basename8) ? opts.binaryInterval : opts.interval;
|
|
18934
|
-
closer = setFsWatchFileListener(
|
|
18845
|
+
closer = setFsWatchFileListener(path33, absolutePath, options, {
|
|
18935
18846
|
listener,
|
|
18936
18847
|
rawEmitter: this.fsw._emitRaw
|
|
18937
18848
|
});
|
|
18938
18849
|
} else {
|
|
18939
|
-
closer = setFsWatchListener(
|
|
18850
|
+
closer = setFsWatchListener(path33, absolutePath, options, {
|
|
18940
18851
|
listener,
|
|
18941
18852
|
errHandler: this._boundHandleError,
|
|
18942
18853
|
rawEmitter: this.fsw._emitRaw
|
|
@@ -18958,7 +18869,7 @@ var NodeFsHandler = class {
|
|
|
18958
18869
|
let prevStats = stats;
|
|
18959
18870
|
if (parent.has(basename8))
|
|
18960
18871
|
return;
|
|
18961
|
-
const listener = async (
|
|
18872
|
+
const listener = async (path33, newStats) => {
|
|
18962
18873
|
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
|
|
18963
18874
|
return;
|
|
18964
18875
|
if (!newStats || newStats.mtimeMs === 0) {
|
|
@@ -18972,11 +18883,11 @@ var NodeFsHandler = class {
|
|
|
18972
18883
|
this.fsw._emit(EV.CHANGE, file, newStats2);
|
|
18973
18884
|
}
|
|
18974
18885
|
if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
|
|
18975
|
-
this.fsw._closeFile(
|
|
18886
|
+
this.fsw._closeFile(path33);
|
|
18976
18887
|
prevStats = newStats2;
|
|
18977
18888
|
const closer2 = this._watchWithNodeFs(file, listener);
|
|
18978
18889
|
if (closer2)
|
|
18979
|
-
this.fsw._addPathCloser(
|
|
18890
|
+
this.fsw._addPathCloser(path33, closer2);
|
|
18980
18891
|
} else {
|
|
18981
18892
|
prevStats = newStats2;
|
|
18982
18893
|
}
|
|
@@ -19008,7 +18919,7 @@ var NodeFsHandler = class {
|
|
|
19008
18919
|
* @param item basename of this item
|
|
19009
18920
|
* @returns true if no more processing is needed for this entry.
|
|
19010
18921
|
*/
|
|
19011
|
-
async _handleSymlink(entry, directory,
|
|
18922
|
+
async _handleSymlink(entry, directory, path33, item) {
|
|
19012
18923
|
if (this.fsw.closed) {
|
|
19013
18924
|
return;
|
|
19014
18925
|
}
|
|
@@ -19018,7 +18929,7 @@ var NodeFsHandler = class {
|
|
|
19018
18929
|
this.fsw._incrReadyCount();
|
|
19019
18930
|
let linkPath;
|
|
19020
18931
|
try {
|
|
19021
|
-
linkPath = await fsrealpath(
|
|
18932
|
+
linkPath = await fsrealpath(path33);
|
|
19022
18933
|
} catch (e) {
|
|
19023
18934
|
this.fsw._emitReady();
|
|
19024
18935
|
return true;
|
|
@@ -19028,12 +18939,12 @@ var NodeFsHandler = class {
|
|
|
19028
18939
|
if (dir.has(item)) {
|
|
19029
18940
|
if (this.fsw._symlinkPaths.get(full) !== linkPath) {
|
|
19030
18941
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
19031
|
-
this.fsw._emit(EV.CHANGE,
|
|
18942
|
+
this.fsw._emit(EV.CHANGE, path33, entry.stats);
|
|
19032
18943
|
}
|
|
19033
18944
|
} else {
|
|
19034
18945
|
dir.add(item);
|
|
19035
18946
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
19036
|
-
this.fsw._emit(EV.ADD,
|
|
18947
|
+
this.fsw._emit(EV.ADD, path33, entry.stats);
|
|
19037
18948
|
}
|
|
19038
18949
|
this.fsw._emitReady();
|
|
19039
18950
|
return true;
|
|
@@ -19063,9 +18974,9 @@ var NodeFsHandler = class {
|
|
|
19063
18974
|
return;
|
|
19064
18975
|
}
|
|
19065
18976
|
const item = entry.path;
|
|
19066
|
-
let
|
|
18977
|
+
let path33 = sp.join(directory, item);
|
|
19067
18978
|
current.add(item);
|
|
19068
|
-
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory,
|
|
18979
|
+
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path33, item)) {
|
|
19069
18980
|
return;
|
|
19070
18981
|
}
|
|
19071
18982
|
if (this.fsw.closed) {
|
|
@@ -19074,11 +18985,11 @@ var NodeFsHandler = class {
|
|
|
19074
18985
|
}
|
|
19075
18986
|
if (item === target || !target && !previous.has(item)) {
|
|
19076
18987
|
this.fsw._incrReadyCount();
|
|
19077
|
-
|
|
19078
|
-
this._addToNodeFs(
|
|
18988
|
+
path33 = sp.join(dir, sp.relative(dir, path33));
|
|
18989
|
+
this._addToNodeFs(path33, initialAdd, wh, depth + 1);
|
|
19079
18990
|
}
|
|
19080
18991
|
}).on(EV.ERROR, this._boundHandleError);
|
|
19081
|
-
return new Promise((
|
|
18992
|
+
return new Promise((resolve20, reject) => {
|
|
19082
18993
|
if (!stream)
|
|
19083
18994
|
return reject();
|
|
19084
18995
|
stream.once(STR_END, () => {
|
|
@@ -19087,7 +18998,7 @@ var NodeFsHandler = class {
|
|
|
19087
18998
|
return;
|
|
19088
18999
|
}
|
|
19089
19000
|
const wasThrottled = throttler ? throttler.clear() : false;
|
|
19090
|
-
|
|
19001
|
+
resolve20(void 0);
|
|
19091
19002
|
previous.getChildren().filter((item) => {
|
|
19092
19003
|
return item !== directory && !current.has(item);
|
|
19093
19004
|
}).forEach((item) => {
|
|
@@ -19144,13 +19055,13 @@ var NodeFsHandler = class {
|
|
|
19144
19055
|
* @param depth Child path actually targeted for watch
|
|
19145
19056
|
* @param target Child path actually targeted for watch
|
|
19146
19057
|
*/
|
|
19147
|
-
async _addToNodeFs(
|
|
19058
|
+
async _addToNodeFs(path33, initialAdd, priorWh, depth, target) {
|
|
19148
19059
|
const ready = this.fsw._emitReady;
|
|
19149
|
-
if (this.fsw._isIgnored(
|
|
19060
|
+
if (this.fsw._isIgnored(path33) || this.fsw.closed) {
|
|
19150
19061
|
ready();
|
|
19151
19062
|
return false;
|
|
19152
19063
|
}
|
|
19153
|
-
const wh = this.fsw._getWatchHelpers(
|
|
19064
|
+
const wh = this.fsw._getWatchHelpers(path33);
|
|
19154
19065
|
if (priorWh) {
|
|
19155
19066
|
wh.filterPath = (entry) => priorWh.filterPath(entry);
|
|
19156
19067
|
wh.filterDir = (entry) => priorWh.filterDir(entry);
|
|
@@ -19166,8 +19077,8 @@ var NodeFsHandler = class {
|
|
|
19166
19077
|
const follow = this.fsw.options.followSymlinks;
|
|
19167
19078
|
let closer;
|
|
19168
19079
|
if (stats.isDirectory()) {
|
|
19169
|
-
const absPath = sp.resolve(
|
|
19170
|
-
const targetPath = follow ? await fsrealpath(
|
|
19080
|
+
const absPath = sp.resolve(path33);
|
|
19081
|
+
const targetPath = follow ? await fsrealpath(path33) : path33;
|
|
19171
19082
|
if (this.fsw.closed)
|
|
19172
19083
|
return;
|
|
19173
19084
|
closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
|
|
@@ -19177,29 +19088,29 @@ var NodeFsHandler = class {
|
|
|
19177
19088
|
this.fsw._symlinkPaths.set(absPath, targetPath);
|
|
19178
19089
|
}
|
|
19179
19090
|
} else if (stats.isSymbolicLink()) {
|
|
19180
|
-
const targetPath = follow ? await fsrealpath(
|
|
19091
|
+
const targetPath = follow ? await fsrealpath(path33) : path33;
|
|
19181
19092
|
if (this.fsw.closed)
|
|
19182
19093
|
return;
|
|
19183
19094
|
const parent = sp.dirname(wh.watchPath);
|
|
19184
19095
|
this.fsw._getWatchedDir(parent).add(wh.watchPath);
|
|
19185
19096
|
this.fsw._emit(EV.ADD, wh.watchPath, stats);
|
|
19186
|
-
closer = await this._handleDir(parent, stats, initialAdd, depth,
|
|
19097
|
+
closer = await this._handleDir(parent, stats, initialAdd, depth, path33, wh, targetPath);
|
|
19187
19098
|
if (this.fsw.closed)
|
|
19188
19099
|
return;
|
|
19189
19100
|
if (targetPath !== void 0) {
|
|
19190
|
-
this.fsw._symlinkPaths.set(sp.resolve(
|
|
19101
|
+
this.fsw._symlinkPaths.set(sp.resolve(path33), targetPath);
|
|
19191
19102
|
}
|
|
19192
19103
|
} else {
|
|
19193
19104
|
closer = this._handleFile(wh.watchPath, stats, initialAdd);
|
|
19194
19105
|
}
|
|
19195
19106
|
ready();
|
|
19196
19107
|
if (closer)
|
|
19197
|
-
this.fsw._addPathCloser(
|
|
19108
|
+
this.fsw._addPathCloser(path33, closer);
|
|
19198
19109
|
return false;
|
|
19199
19110
|
} catch (error) {
|
|
19200
19111
|
if (this.fsw._handleError(error)) {
|
|
19201
19112
|
ready();
|
|
19202
|
-
return
|
|
19113
|
+
return path33;
|
|
19203
19114
|
}
|
|
19204
19115
|
}
|
|
19205
19116
|
}
|
|
@@ -19231,35 +19142,35 @@ function createPattern(matcher) {
|
|
|
19231
19142
|
if (matcher.path === string)
|
|
19232
19143
|
return true;
|
|
19233
19144
|
if (matcher.recursive) {
|
|
19234
|
-
const
|
|
19235
|
-
if (!
|
|
19145
|
+
const relative14 = sp2.relative(matcher.path, string);
|
|
19146
|
+
if (!relative14) {
|
|
19236
19147
|
return false;
|
|
19237
19148
|
}
|
|
19238
|
-
return !
|
|
19149
|
+
return !relative14.startsWith("..") && !sp2.isAbsolute(relative14);
|
|
19239
19150
|
}
|
|
19240
19151
|
return false;
|
|
19241
19152
|
};
|
|
19242
19153
|
}
|
|
19243
19154
|
return () => false;
|
|
19244
19155
|
}
|
|
19245
|
-
function normalizePath3(
|
|
19246
|
-
if (typeof
|
|
19156
|
+
function normalizePath3(path33) {
|
|
19157
|
+
if (typeof path33 !== "string")
|
|
19247
19158
|
throw new Error("string expected");
|
|
19248
|
-
|
|
19249
|
-
|
|
19159
|
+
path33 = sp2.normalize(path33);
|
|
19160
|
+
path33 = path33.replace(/\\/g, "/");
|
|
19250
19161
|
let prepend = false;
|
|
19251
|
-
if (
|
|
19162
|
+
if (path33.startsWith("//"))
|
|
19252
19163
|
prepend = true;
|
|
19253
|
-
|
|
19164
|
+
path33 = path33.replace(DOUBLE_SLASH_RE, "/");
|
|
19254
19165
|
if (prepend)
|
|
19255
|
-
|
|
19256
|
-
return
|
|
19166
|
+
path33 = "/" + path33;
|
|
19167
|
+
return path33;
|
|
19257
19168
|
}
|
|
19258
19169
|
function matchPatterns(patterns, testString, stats) {
|
|
19259
|
-
const
|
|
19170
|
+
const path33 = normalizePath3(testString);
|
|
19260
19171
|
for (let index = 0; index < patterns.length; index++) {
|
|
19261
19172
|
const pattern = patterns[index];
|
|
19262
|
-
if (pattern(
|
|
19173
|
+
if (pattern(path33, stats)) {
|
|
19263
19174
|
return true;
|
|
19264
19175
|
}
|
|
19265
19176
|
}
|
|
@@ -19297,19 +19208,19 @@ var toUnix = (string) => {
|
|
|
19297
19208
|
}
|
|
19298
19209
|
return str;
|
|
19299
19210
|
};
|
|
19300
|
-
var normalizePathToUnix = (
|
|
19301
|
-
var normalizeIgnored = (cwd = "") => (
|
|
19302
|
-
if (typeof
|
|
19303
|
-
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));
|
|
19304
19215
|
} else {
|
|
19305
|
-
return
|
|
19216
|
+
return path33;
|
|
19306
19217
|
}
|
|
19307
19218
|
};
|
|
19308
|
-
var getAbsolutePath = (
|
|
19309
|
-
if (sp2.isAbsolute(
|
|
19310
|
-
return
|
|
19219
|
+
var getAbsolutePath = (path33, cwd) => {
|
|
19220
|
+
if (sp2.isAbsolute(path33)) {
|
|
19221
|
+
return path33;
|
|
19311
19222
|
}
|
|
19312
|
-
return sp2.join(cwd,
|
|
19223
|
+
return sp2.join(cwd, path33);
|
|
19313
19224
|
};
|
|
19314
19225
|
var EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
|
|
19315
19226
|
var DirEntry = class {
|
|
@@ -19374,10 +19285,10 @@ var WatchHelper = class {
|
|
|
19374
19285
|
dirParts;
|
|
19375
19286
|
followSymlinks;
|
|
19376
19287
|
statMethod;
|
|
19377
|
-
constructor(
|
|
19288
|
+
constructor(path33, follow, fsw) {
|
|
19378
19289
|
this.fsw = fsw;
|
|
19379
|
-
const watchPath =
|
|
19380
|
-
this.path =
|
|
19290
|
+
const watchPath = path33;
|
|
19291
|
+
this.path = path33 = path33.replace(REPLACER_RE, "");
|
|
19381
19292
|
this.watchPath = watchPath;
|
|
19382
19293
|
this.fullWatchPath = sp2.resolve(watchPath);
|
|
19383
19294
|
this.dirParts = [];
|
|
@@ -19517,20 +19428,20 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
19517
19428
|
this._closePromise = void 0;
|
|
19518
19429
|
let paths = unifyPaths(paths_);
|
|
19519
19430
|
if (cwd) {
|
|
19520
|
-
paths = paths.map((
|
|
19521
|
-
const absPath = getAbsolutePath(
|
|
19431
|
+
paths = paths.map((path33) => {
|
|
19432
|
+
const absPath = getAbsolutePath(path33, cwd);
|
|
19522
19433
|
return absPath;
|
|
19523
19434
|
});
|
|
19524
19435
|
}
|
|
19525
|
-
paths.forEach((
|
|
19526
|
-
this._removeIgnoredPath(
|
|
19436
|
+
paths.forEach((path33) => {
|
|
19437
|
+
this._removeIgnoredPath(path33);
|
|
19527
19438
|
});
|
|
19528
19439
|
this._userIgnored = void 0;
|
|
19529
19440
|
if (!this._readyCount)
|
|
19530
19441
|
this._readyCount = 0;
|
|
19531
19442
|
this._readyCount += paths.length;
|
|
19532
|
-
Promise.all(paths.map(async (
|
|
19533
|
-
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);
|
|
19534
19445
|
if (res)
|
|
19535
19446
|
this._emitReady();
|
|
19536
19447
|
return res;
|
|
@@ -19552,17 +19463,17 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
19552
19463
|
return this;
|
|
19553
19464
|
const paths = unifyPaths(paths_);
|
|
19554
19465
|
const { cwd } = this.options;
|
|
19555
|
-
paths.forEach((
|
|
19556
|
-
if (!sp2.isAbsolute(
|
|
19466
|
+
paths.forEach((path33) => {
|
|
19467
|
+
if (!sp2.isAbsolute(path33) && !this._closers.has(path33)) {
|
|
19557
19468
|
if (cwd)
|
|
19558
|
-
|
|
19559
|
-
|
|
19469
|
+
path33 = sp2.join(cwd, path33);
|
|
19470
|
+
path33 = sp2.resolve(path33);
|
|
19560
19471
|
}
|
|
19561
|
-
this._closePath(
|
|
19562
|
-
this._addIgnoredPath(
|
|
19563
|
-
if (this._watched.has(
|
|
19472
|
+
this._closePath(path33);
|
|
19473
|
+
this._addIgnoredPath(path33);
|
|
19474
|
+
if (this._watched.has(path33)) {
|
|
19564
19475
|
this._addIgnoredPath({
|
|
19565
|
-
path:
|
|
19476
|
+
path: path33,
|
|
19566
19477
|
recursive: true
|
|
19567
19478
|
});
|
|
19568
19479
|
}
|
|
@@ -19626,38 +19537,38 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
19626
19537
|
* @param stats arguments to be passed with event
|
|
19627
19538
|
* @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
|
|
19628
19539
|
*/
|
|
19629
|
-
async _emit(event,
|
|
19540
|
+
async _emit(event, path33, stats) {
|
|
19630
19541
|
if (this.closed)
|
|
19631
19542
|
return;
|
|
19632
19543
|
const opts = this.options;
|
|
19633
19544
|
if (isWindows)
|
|
19634
|
-
|
|
19545
|
+
path33 = sp2.normalize(path33);
|
|
19635
19546
|
if (opts.cwd)
|
|
19636
|
-
|
|
19637
|
-
const args = [
|
|
19547
|
+
path33 = sp2.relative(opts.cwd, path33);
|
|
19548
|
+
const args = [path33];
|
|
19638
19549
|
if (stats != null)
|
|
19639
19550
|
args.push(stats);
|
|
19640
19551
|
const awf = opts.awaitWriteFinish;
|
|
19641
19552
|
let pw;
|
|
19642
|
-
if (awf && (pw = this._pendingWrites.get(
|
|
19553
|
+
if (awf && (pw = this._pendingWrites.get(path33))) {
|
|
19643
19554
|
pw.lastChange = /* @__PURE__ */ new Date();
|
|
19644
19555
|
return this;
|
|
19645
19556
|
}
|
|
19646
19557
|
if (opts.atomic) {
|
|
19647
19558
|
if (event === EVENTS.UNLINK) {
|
|
19648
|
-
this._pendingUnlinks.set(
|
|
19559
|
+
this._pendingUnlinks.set(path33, [event, ...args]);
|
|
19649
19560
|
setTimeout(() => {
|
|
19650
|
-
this._pendingUnlinks.forEach((entry,
|
|
19561
|
+
this._pendingUnlinks.forEach((entry, path34) => {
|
|
19651
19562
|
this.emit(...entry);
|
|
19652
19563
|
this.emit(EVENTS.ALL, ...entry);
|
|
19653
|
-
this._pendingUnlinks.delete(
|
|
19564
|
+
this._pendingUnlinks.delete(path34);
|
|
19654
19565
|
});
|
|
19655
19566
|
}, typeof opts.atomic === "number" ? opts.atomic : 100);
|
|
19656
19567
|
return this;
|
|
19657
19568
|
}
|
|
19658
|
-
if (event === EVENTS.ADD && this._pendingUnlinks.has(
|
|
19569
|
+
if (event === EVENTS.ADD && this._pendingUnlinks.has(path33)) {
|
|
19659
19570
|
event = EVENTS.CHANGE;
|
|
19660
|
-
this._pendingUnlinks.delete(
|
|
19571
|
+
this._pendingUnlinks.delete(path33);
|
|
19661
19572
|
}
|
|
19662
19573
|
}
|
|
19663
19574
|
if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
|
|
@@ -19675,16 +19586,16 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
19675
19586
|
this.emitWithAll(event, args);
|
|
19676
19587
|
}
|
|
19677
19588
|
};
|
|
19678
|
-
this._awaitWriteFinish(
|
|
19589
|
+
this._awaitWriteFinish(path33, awf.stabilityThreshold, event, awfEmit);
|
|
19679
19590
|
return this;
|
|
19680
19591
|
}
|
|
19681
19592
|
if (event === EVENTS.CHANGE) {
|
|
19682
|
-
const isThrottled = !this._throttle(EVENTS.CHANGE,
|
|
19593
|
+
const isThrottled = !this._throttle(EVENTS.CHANGE, path33, 50);
|
|
19683
19594
|
if (isThrottled)
|
|
19684
19595
|
return this;
|
|
19685
19596
|
}
|
|
19686
19597
|
if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
|
|
19687
|
-
const fullPath = opts.cwd ? sp2.join(opts.cwd,
|
|
19598
|
+
const fullPath = opts.cwd ? sp2.join(opts.cwd, path33) : path33;
|
|
19688
19599
|
let stats2;
|
|
19689
19600
|
try {
|
|
19690
19601
|
stats2 = await stat3(fullPath);
|
|
@@ -19715,23 +19626,23 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
19715
19626
|
* @param timeout duration of time to suppress duplicate actions
|
|
19716
19627
|
* @returns tracking object or false if action should be suppressed
|
|
19717
19628
|
*/
|
|
19718
|
-
_throttle(actionType,
|
|
19629
|
+
_throttle(actionType, path33, timeout) {
|
|
19719
19630
|
if (!this._throttled.has(actionType)) {
|
|
19720
19631
|
this._throttled.set(actionType, /* @__PURE__ */ new Map());
|
|
19721
19632
|
}
|
|
19722
19633
|
const action = this._throttled.get(actionType);
|
|
19723
19634
|
if (!action)
|
|
19724
19635
|
throw new Error("invalid throttle");
|
|
19725
|
-
const actionPath = action.get(
|
|
19636
|
+
const actionPath = action.get(path33);
|
|
19726
19637
|
if (actionPath) {
|
|
19727
19638
|
actionPath.count++;
|
|
19728
19639
|
return false;
|
|
19729
19640
|
}
|
|
19730
19641
|
let timeoutObject;
|
|
19731
19642
|
const clear = () => {
|
|
19732
|
-
const item = action.get(
|
|
19643
|
+
const item = action.get(path33);
|
|
19733
19644
|
const count = item ? item.count : 0;
|
|
19734
|
-
action.delete(
|
|
19645
|
+
action.delete(path33);
|
|
19735
19646
|
clearTimeout(timeoutObject);
|
|
19736
19647
|
if (item)
|
|
19737
19648
|
clearTimeout(item.timeoutObject);
|
|
@@ -19739,7 +19650,7 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
19739
19650
|
};
|
|
19740
19651
|
timeoutObject = setTimeout(clear, timeout);
|
|
19741
19652
|
const thr = { timeoutObject, clear, count: 0 };
|
|
19742
|
-
action.set(
|
|
19653
|
+
action.set(path33, thr);
|
|
19743
19654
|
return thr;
|
|
19744
19655
|
}
|
|
19745
19656
|
_incrReadyCount() {
|
|
@@ -19753,44 +19664,44 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
19753
19664
|
* @param event
|
|
19754
19665
|
* @param awfEmit Callback to be called when ready for event to be emitted.
|
|
19755
19666
|
*/
|
|
19756
|
-
_awaitWriteFinish(
|
|
19667
|
+
_awaitWriteFinish(path33, threshold, event, awfEmit) {
|
|
19757
19668
|
const awf = this.options.awaitWriteFinish;
|
|
19758
19669
|
if (typeof awf !== "object")
|
|
19759
19670
|
return;
|
|
19760
19671
|
const pollInterval = awf.pollInterval;
|
|
19761
19672
|
let timeoutHandler;
|
|
19762
|
-
let fullPath =
|
|
19763
|
-
if (this.options.cwd && !sp2.isAbsolute(
|
|
19764
|
-
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);
|
|
19765
19676
|
}
|
|
19766
19677
|
const now2 = /* @__PURE__ */ new Date();
|
|
19767
19678
|
const writes = this._pendingWrites;
|
|
19768
19679
|
function awaitWriteFinishFn(prevStat) {
|
|
19769
19680
|
statcb(fullPath, (err, curStat) => {
|
|
19770
|
-
if (err || !writes.has(
|
|
19681
|
+
if (err || !writes.has(path33)) {
|
|
19771
19682
|
if (err && err.code !== "ENOENT")
|
|
19772
19683
|
awfEmit(err);
|
|
19773
19684
|
return;
|
|
19774
19685
|
}
|
|
19775
19686
|
const now3 = Number(/* @__PURE__ */ new Date());
|
|
19776
19687
|
if (prevStat && curStat.size !== prevStat.size) {
|
|
19777
|
-
writes.get(
|
|
19688
|
+
writes.get(path33).lastChange = now3;
|
|
19778
19689
|
}
|
|
19779
|
-
const pw = writes.get(
|
|
19690
|
+
const pw = writes.get(path33);
|
|
19780
19691
|
const df = now3 - pw.lastChange;
|
|
19781
19692
|
if (df >= threshold) {
|
|
19782
|
-
writes.delete(
|
|
19693
|
+
writes.delete(path33);
|
|
19783
19694
|
awfEmit(void 0, curStat);
|
|
19784
19695
|
} else {
|
|
19785
19696
|
timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
|
|
19786
19697
|
}
|
|
19787
19698
|
});
|
|
19788
19699
|
}
|
|
19789
|
-
if (!writes.has(
|
|
19790
|
-
writes.set(
|
|
19700
|
+
if (!writes.has(path33)) {
|
|
19701
|
+
writes.set(path33, {
|
|
19791
19702
|
lastChange: now2,
|
|
19792
19703
|
cancelWait: () => {
|
|
19793
|
-
writes.delete(
|
|
19704
|
+
writes.delete(path33);
|
|
19794
19705
|
clearTimeout(timeoutHandler);
|
|
19795
19706
|
return event;
|
|
19796
19707
|
}
|
|
@@ -19801,8 +19712,8 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
19801
19712
|
/**
|
|
19802
19713
|
* Determines whether user has asked to ignore this path.
|
|
19803
19714
|
*/
|
|
19804
|
-
_isIgnored(
|
|
19805
|
-
if (this.options.atomic && DOT_RE.test(
|
|
19715
|
+
_isIgnored(path33, stats) {
|
|
19716
|
+
if (this.options.atomic && DOT_RE.test(path33))
|
|
19806
19717
|
return true;
|
|
19807
19718
|
if (!this._userIgnored) {
|
|
19808
19719
|
const { cwd } = this.options;
|
|
@@ -19812,17 +19723,17 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
19812
19723
|
const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
|
|
19813
19724
|
this._userIgnored = anymatch(list, void 0);
|
|
19814
19725
|
}
|
|
19815
|
-
return this._userIgnored(
|
|
19726
|
+
return this._userIgnored(path33, stats);
|
|
19816
19727
|
}
|
|
19817
|
-
_isntIgnored(
|
|
19818
|
-
return !this._isIgnored(
|
|
19728
|
+
_isntIgnored(path33, stat5) {
|
|
19729
|
+
return !this._isIgnored(path33, stat5);
|
|
19819
19730
|
}
|
|
19820
19731
|
/**
|
|
19821
19732
|
* Provides a set of common helpers and properties relating to symlink handling.
|
|
19822
19733
|
* @param path file or directory pattern being watched
|
|
19823
19734
|
*/
|
|
19824
|
-
_getWatchHelpers(
|
|
19825
|
-
return new WatchHelper(
|
|
19735
|
+
_getWatchHelpers(path33) {
|
|
19736
|
+
return new WatchHelper(path33, this.options.followSymlinks, this);
|
|
19826
19737
|
}
|
|
19827
19738
|
// Directory helpers
|
|
19828
19739
|
// -----------------
|
|
@@ -19854,63 +19765,63 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
19854
19765
|
* @param item base path of item/directory
|
|
19855
19766
|
*/
|
|
19856
19767
|
_remove(directory, item, isDirectory) {
|
|
19857
|
-
const
|
|
19858
|
-
const fullPath = sp2.resolve(
|
|
19859
|
-
isDirectory = isDirectory != null ? isDirectory : this._watched.has(
|
|
19860
|
-
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))
|
|
19861
19772
|
return;
|
|
19862
19773
|
if (!isDirectory && this._watched.size === 1) {
|
|
19863
19774
|
this.add(directory, item, true);
|
|
19864
19775
|
}
|
|
19865
|
-
const wp = this._getWatchedDir(
|
|
19776
|
+
const wp = this._getWatchedDir(path33);
|
|
19866
19777
|
const nestedDirectoryChildren = wp.getChildren();
|
|
19867
|
-
nestedDirectoryChildren.forEach((nested) => this._remove(
|
|
19778
|
+
nestedDirectoryChildren.forEach((nested) => this._remove(path33, nested));
|
|
19868
19779
|
const parent = this._getWatchedDir(directory);
|
|
19869
19780
|
const wasTracked = parent.has(item);
|
|
19870
19781
|
parent.remove(item);
|
|
19871
19782
|
if (this._symlinkPaths.has(fullPath)) {
|
|
19872
19783
|
this._symlinkPaths.delete(fullPath);
|
|
19873
19784
|
}
|
|
19874
|
-
let relPath =
|
|
19785
|
+
let relPath = path33;
|
|
19875
19786
|
if (this.options.cwd)
|
|
19876
|
-
relPath = sp2.relative(this.options.cwd,
|
|
19787
|
+
relPath = sp2.relative(this.options.cwd, path33);
|
|
19877
19788
|
if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
|
|
19878
19789
|
const event = this._pendingWrites.get(relPath).cancelWait();
|
|
19879
19790
|
if (event === EVENTS.ADD)
|
|
19880
19791
|
return;
|
|
19881
19792
|
}
|
|
19882
|
-
this._watched.delete(
|
|
19793
|
+
this._watched.delete(path33);
|
|
19883
19794
|
this._watched.delete(fullPath);
|
|
19884
19795
|
const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
|
|
19885
|
-
if (wasTracked && !this._isIgnored(
|
|
19886
|
-
this._emit(eventName,
|
|
19887
|
-
this._closePath(
|
|
19796
|
+
if (wasTracked && !this._isIgnored(path33))
|
|
19797
|
+
this._emit(eventName, path33);
|
|
19798
|
+
this._closePath(path33);
|
|
19888
19799
|
}
|
|
19889
19800
|
/**
|
|
19890
19801
|
* Closes all watchers for a path
|
|
19891
19802
|
*/
|
|
19892
|
-
_closePath(
|
|
19893
|
-
this._closeFile(
|
|
19894
|
-
const dir = sp2.dirname(
|
|
19895
|
-
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));
|
|
19896
19807
|
}
|
|
19897
19808
|
/**
|
|
19898
19809
|
* Closes only file-specific watchers
|
|
19899
19810
|
*/
|
|
19900
|
-
_closeFile(
|
|
19901
|
-
const closers = this._closers.get(
|
|
19811
|
+
_closeFile(path33) {
|
|
19812
|
+
const closers = this._closers.get(path33);
|
|
19902
19813
|
if (!closers)
|
|
19903
19814
|
return;
|
|
19904
19815
|
closers.forEach((closer) => closer());
|
|
19905
|
-
this._closers.delete(
|
|
19816
|
+
this._closers.delete(path33);
|
|
19906
19817
|
}
|
|
19907
|
-
_addPathCloser(
|
|
19818
|
+
_addPathCloser(path33, closer) {
|
|
19908
19819
|
if (!closer)
|
|
19909
19820
|
return;
|
|
19910
|
-
let list = this._closers.get(
|
|
19821
|
+
let list = this._closers.get(path33);
|
|
19911
19822
|
if (!list) {
|
|
19912
19823
|
list = [];
|
|
19913
|
-
this._closers.set(
|
|
19824
|
+
this._closers.set(path33, list);
|
|
19914
19825
|
}
|
|
19915
19826
|
list.push(closer);
|
|
19916
19827
|
}
|
|
@@ -19940,12 +19851,291 @@ function watch(paths, options = {}) {
|
|
|
19940
19851
|
var chokidar_default = { watch, FSWatcher };
|
|
19941
19852
|
|
|
19942
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";
|
|
19943
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
|
|
19944
20133
|
var FileWatcher = class {
|
|
19945
20134
|
watcher = null;
|
|
19946
20135
|
projectRoot;
|
|
19947
20136
|
config;
|
|
19948
20137
|
configPath;
|
|
20138
|
+
backend;
|
|
19949
20139
|
projectConfigPaths;
|
|
19950
20140
|
pendingChanges = /* @__PURE__ */ new Map();
|
|
19951
20141
|
debounceTimer = null;
|
|
@@ -19955,44 +20145,74 @@ var FileWatcher = class {
|
|
|
19955
20145
|
resolveReady = null;
|
|
19956
20146
|
pollingFallbackAttempted = false;
|
|
19957
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();
|
|
19958
20157
|
constructor(projectRoot, config, host, options = {}) {
|
|
19959
20158
|
this.projectRoot = projectRoot;
|
|
19960
20159
|
this.config = config;
|
|
20160
|
+
this.backend = options.backend ?? "auto";
|
|
19961
20161
|
this.configPath = options.configPath;
|
|
19962
20162
|
this.projectConfigPaths = options.configPath ? [options.configPath] : getProjectConfigCandidatePaths(projectRoot, host);
|
|
19963
20163
|
}
|
|
19964
20164
|
start(handler) {
|
|
19965
|
-
if (this.watcher) {
|
|
20165
|
+
if (this.watcher || this.nativeWatcher || this.nativeStarting) {
|
|
19966
20166
|
return;
|
|
19967
20167
|
}
|
|
19968
20168
|
this.onChanges = handler;
|
|
19969
20169
|
this.pollingFallbackAttempted = false;
|
|
19970
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
|
+
}
|
|
19971
20180
|
this.createWatcher();
|
|
19972
20181
|
}
|
|
19973
20182
|
resetReady() {
|
|
19974
|
-
this.readyPromise = new Promise((
|
|
19975
|
-
this.resolveReady =
|
|
20183
|
+
this.readyPromise = new Promise((resolve20) => {
|
|
20184
|
+
this.resolveReady = resolve20;
|
|
19976
20185
|
});
|
|
20186
|
+
this.startupReadySignals = 1;
|
|
19977
20187
|
}
|
|
19978
|
-
|
|
19979
|
-
|
|
19980
|
-
|
|
19981
|
-
|
|
19982
|
-
|
|
19983
|
-
|
|
19984
|
-
|
|
19985
|
-
|
|
19986
|
-
|
|
19987
|
-
|
|
19988
|
-
|
|
19989
|
-
|
|
19990
|
-
watchTargets = [this.projectRoot, ...uniqueExternalConfigTargets];
|
|
19991
|
-
}
|
|
20188
|
+
setStartupReadySignals(expectedSignals) {
|
|
20189
|
+
if (!this.readyPromise) {
|
|
20190
|
+
return;
|
|
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;
|
|
19992
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();
|
|
19993
20213
|
const watcherOptions = {
|
|
19994
20214
|
ignored: (filePath) => {
|
|
19995
|
-
const relativePath =
|
|
20215
|
+
const relativePath = path28.relative(this.projectRoot, filePath);
|
|
19996
20216
|
if (!relativePath) return false;
|
|
19997
20217
|
if (this.isProjectConfigPathOrAncestor(relativePath)) {
|
|
19998
20218
|
return false;
|
|
@@ -20000,10 +20220,10 @@ var FileWatcher = class {
|
|
|
20000
20220
|
if (this.isOutsideProjectPath(relativePath)) {
|
|
20001
20221
|
return true;
|
|
20002
20222
|
}
|
|
20003
|
-
if (hasFilteredPathSegment(relativePath,
|
|
20223
|
+
if (hasFilteredPathSegment(relativePath, path28.sep)) {
|
|
20004
20224
|
return true;
|
|
20005
20225
|
}
|
|
20006
|
-
if (isRestrictedDirectory(relativePath,
|
|
20226
|
+
if (isRestrictedDirectory(relativePath, path28.sep)) {
|
|
20007
20227
|
return true;
|
|
20008
20228
|
}
|
|
20009
20229
|
if (ignoreFilter.ignores(relativePath)) {
|
|
@@ -20036,10 +20256,13 @@ var FileWatcher = class {
|
|
|
20036
20256
|
watcher = new FSWatcher(watcherOptions);
|
|
20037
20257
|
}
|
|
20038
20258
|
this.watcher = watcher;
|
|
20039
|
-
watcher.
|
|
20259
|
+
watcher.on("ready", () => {
|
|
20040
20260
|
if (this.watcher !== watcher) return;
|
|
20041
|
-
this.
|
|
20042
|
-
|
|
20261
|
+
this.reconcileConfigPathStates();
|
|
20262
|
+
if (reportsStartupReady) {
|
|
20263
|
+
this.reportStartupReadySignal();
|
|
20264
|
+
reportedStartupReady = true;
|
|
20265
|
+
}
|
|
20043
20266
|
});
|
|
20044
20267
|
watcher.on("error", (error) => {
|
|
20045
20268
|
const err = error instanceof Error ? error : null;
|
|
@@ -20053,10 +20276,13 @@ var FileWatcher = class {
|
|
|
20053
20276
|
console.error("[codebase-index] Failed to close exhausted file watcher:", closeError);
|
|
20054
20277
|
});
|
|
20055
20278
|
if (this.onChanges) {
|
|
20279
|
+
const replacementReportsStartupReady = reportsStartupReady || reportedStartupReady;
|
|
20056
20280
|
if (!this.resolveReady) {
|
|
20057
20281
|
this.resetReady();
|
|
20282
|
+
} else if (reportedStartupReady) {
|
|
20283
|
+
this.startupReadySignals += 1;
|
|
20058
20284
|
}
|
|
20059
|
-
this.createWatcher(true);
|
|
20285
|
+
this.createWatcher(resolvedWatchTargets, true, replacementReportsStartupReady);
|
|
20060
20286
|
} else {
|
|
20061
20287
|
this.watcher = null;
|
|
20062
20288
|
}
|
|
@@ -20067,13 +20293,166 @@ var FileWatcher = class {
|
|
|
20067
20293
|
watcher.on("add", (filePath) => this.handleChange(watcher, "add", filePath));
|
|
20068
20294
|
watcher.on("change", (filePath) => this.handleChange(watcher, "change", filePath));
|
|
20069
20295
|
watcher.on("unlink", (filePath) => this.handleChange(watcher, "unlink", filePath));
|
|
20070
|
-
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
|
+
}
|
|
20071
20449
|
}
|
|
20072
20450
|
handleChange(watcher, type, filePath) {
|
|
20073
20451
|
if (this.watcher !== watcher) {
|
|
20074
20452
|
return;
|
|
20075
20453
|
}
|
|
20076
20454
|
if (this.isProjectConfigPath(filePath)) {
|
|
20455
|
+
this.updateConfigPathState(filePath);
|
|
20077
20456
|
this.pendingChanges.set(filePath, type);
|
|
20078
20457
|
this.scheduleFlush();
|
|
20079
20458
|
return;
|
|
@@ -20088,27 +20467,33 @@ var FileWatcher = class {
|
|
|
20088
20467
|
)) {
|
|
20089
20468
|
return;
|
|
20090
20469
|
}
|
|
20091
|
-
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
|
+
}
|
|
20092
20477
|
this.scheduleFlush();
|
|
20093
20478
|
}
|
|
20094
20479
|
isProjectConfigPath(filePath) {
|
|
20095
|
-
const relativePath =
|
|
20096
|
-
const normalizedRelativePath =
|
|
20480
|
+
const relativePath = path28.relative(this.projectRoot, filePath);
|
|
20481
|
+
const normalizedRelativePath = path28.normalize(relativePath);
|
|
20097
20482
|
return this.getProjectConfigRelativePaths().some((configPath) => configPath === normalizedRelativePath);
|
|
20098
20483
|
}
|
|
20099
20484
|
isProjectConfigPathOrAncestor(relativePath) {
|
|
20100
|
-
const normalizedRelativePath =
|
|
20485
|
+
const normalizedRelativePath = path28.normalize(relativePath);
|
|
20101
20486
|
return this.getProjectConfigRelativePaths().some(
|
|
20102
|
-
(configPath) => configPath === normalizedRelativePath || configPath.startsWith(`${normalizedRelativePath}${
|
|
20487
|
+
(configPath) => configPath === normalizedRelativePath || configPath.startsWith(`${normalizedRelativePath}${path28.sep}`)
|
|
20103
20488
|
);
|
|
20104
20489
|
}
|
|
20105
20490
|
isOutsideProjectPath(relativePath) {
|
|
20106
|
-
return relativePath === ".." || relativePath.startsWith(`..${
|
|
20491
|
+
return relativePath === ".." || relativePath.startsWith(`..${path28.sep}`) || path28.isAbsolute(relativePath);
|
|
20107
20492
|
}
|
|
20108
20493
|
getNearestExistingDirectory(directoryPath) {
|
|
20109
20494
|
let candidate = directoryPath;
|
|
20110
20495
|
while (!existsSync15(candidate)) {
|
|
20111
|
-
const parent =
|
|
20496
|
+
const parent = path28.dirname(candidate);
|
|
20112
20497
|
if (parent === candidate) break;
|
|
20113
20498
|
candidate = parent;
|
|
20114
20499
|
}
|
|
@@ -20116,9 +20501,51 @@ var FileWatcher = class {
|
|
|
20116
20501
|
}
|
|
20117
20502
|
getProjectConfigRelativePaths() {
|
|
20118
20503
|
return this.projectConfigPaths.map(
|
|
20119
|
-
(configPath) =>
|
|
20504
|
+
(configPath) => path28.normalize(path28.relative(this.projectRoot, configPath))
|
|
20120
20505
|
);
|
|
20121
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
|
+
}
|
|
20122
20549
|
scheduleFlush() {
|
|
20123
20550
|
if (this.debounceTimer) {
|
|
20124
20551
|
clearTimeout(this.debounceTimer);
|
|
@@ -20132,7 +20559,7 @@ var FileWatcher = class {
|
|
|
20132
20559
|
return;
|
|
20133
20560
|
}
|
|
20134
20561
|
const changes = Array.from(this.pendingChanges.entries()).map(
|
|
20135
|
-
([
|
|
20562
|
+
([path33, type]) => ({ path: path33, type })
|
|
20136
20563
|
);
|
|
20137
20564
|
this.pendingChanges.clear();
|
|
20138
20565
|
try {
|
|
@@ -20146,20 +20573,31 @@ var FileWatcher = class {
|
|
|
20146
20573
|
clearTimeout(this.debounceTimer);
|
|
20147
20574
|
this.debounceTimer = null;
|
|
20148
20575
|
}
|
|
20576
|
+
if (this.nativeReconcileTimer) {
|
|
20577
|
+
clearTimeout(this.nativeReconcileTimer);
|
|
20578
|
+
this.nativeReconcileTimer = null;
|
|
20579
|
+
}
|
|
20580
|
+
this.nativeInvalidatedPaths.clear();
|
|
20149
20581
|
const watcher = this.watcher;
|
|
20582
|
+
const nativeWatcher = this.nativeWatcher;
|
|
20150
20583
|
const pendingClose = this.pendingClose;
|
|
20151
20584
|
const resolveReady = this.resolveReady;
|
|
20152
20585
|
this.watcher = null;
|
|
20586
|
+
this.nativeWatcher = null;
|
|
20587
|
+
this.nativeReconciler = null;
|
|
20588
|
+
this.nativeStarting = false;
|
|
20589
|
+
this.nativeInitializing = false;
|
|
20590
|
+
this.nativeSetupGeneration += 1;
|
|
20153
20591
|
this.pendingClose = null;
|
|
20154
20592
|
this.resolveReady = null;
|
|
20155
20593
|
this.readyPromise = null;
|
|
20156
20594
|
this.pendingChanges.clear();
|
|
20157
20595
|
this.onChanges = null;
|
|
20158
|
-
await Promise.all([watcher?.close(), pendingClose]);
|
|
20596
|
+
await Promise.all([watcher?.close(), nativeWatcher?.stop(), pendingClose]);
|
|
20159
20597
|
resolveReady?.();
|
|
20160
20598
|
}
|
|
20161
20599
|
isRunning() {
|
|
20162
|
-
return this.watcher !== null;
|
|
20600
|
+
return this.watcher !== null || this.nativeWatcher !== null || this.nativeStarting;
|
|
20163
20601
|
}
|
|
20164
20602
|
async waitUntilReady() {
|
|
20165
20603
|
await (this.readyPromise ?? Promise.resolve());
|
|
@@ -20167,7 +20605,7 @@ var FileWatcher = class {
|
|
|
20167
20605
|
};
|
|
20168
20606
|
|
|
20169
20607
|
// src/watcher/git-head-watcher.ts
|
|
20170
|
-
import * as
|
|
20608
|
+
import * as path29 from "path";
|
|
20171
20609
|
var GitHeadWatcher = class {
|
|
20172
20610
|
watcher = null;
|
|
20173
20611
|
projectRoot;
|
|
@@ -20189,13 +20627,13 @@ var GitHeadWatcher = class {
|
|
|
20189
20627
|
this.readyPromise = Promise.resolve();
|
|
20190
20628
|
return;
|
|
20191
20629
|
}
|
|
20192
|
-
this.readyPromise = new Promise((
|
|
20193
|
-
this.resolveReady =
|
|
20630
|
+
this.readyPromise = new Promise((resolve20) => {
|
|
20631
|
+
this.resolveReady = resolve20;
|
|
20194
20632
|
});
|
|
20195
20633
|
this.onBranchChange = handler;
|
|
20196
20634
|
this.currentBranch = getCurrentBranch(this.projectRoot);
|
|
20197
20635
|
const headPath = getHeadPath(this.projectRoot);
|
|
20198
|
-
const refsPath =
|
|
20636
|
+
const refsPath = path29.join(this.projectRoot, ".git", "refs", "heads");
|
|
20199
20637
|
this.watcher = chokidar_default.watch([headPath, refsPath], {
|
|
20200
20638
|
persistent: true,
|
|
20201
20639
|
ignoreInitial: true,
|
|
@@ -20331,7 +20769,7 @@ function getConfigPaths(projectRoot, host, options) {
|
|
|
20331
20769
|
|
|
20332
20770
|
// src/tools/visualize/activity.ts
|
|
20333
20771
|
import { execFileSync } from "child_process";
|
|
20334
|
-
import * as
|
|
20772
|
+
import * as path30 from "path";
|
|
20335
20773
|
function attachRecentActivity(data, projectRoot) {
|
|
20336
20774
|
const activity = readGitActivity(projectRoot);
|
|
20337
20775
|
const changes = activity.size > 0 ? buildGitChanges(data, activity, projectRoot) : buildGraphChanges(data);
|
|
@@ -20493,7 +20931,7 @@ function normalizePath4(filePath) {
|
|
|
20493
20931
|
return filePath.replace(/\\/g, "/");
|
|
20494
20932
|
}
|
|
20495
20933
|
function toGitRelativePath(projectRoot, filePath) {
|
|
20496
|
-
const relativePath =
|
|
20934
|
+
const relativePath = path30.isAbsolute(filePath) ? path30.relative(projectRoot, filePath) : filePath;
|
|
20497
20935
|
return normalizePath4(relativePath);
|
|
20498
20936
|
}
|
|
20499
20937
|
|
|
@@ -20751,7 +21189,7 @@ render();
|
|
|
20751
21189
|
}
|
|
20752
21190
|
|
|
20753
21191
|
// src/tools/visualize/transform.ts
|
|
20754
|
-
import * as
|
|
21192
|
+
import * as path31 from "path";
|
|
20755
21193
|
|
|
20756
21194
|
// src/tools/visualize/modules.ts
|
|
20757
21195
|
var MAX_MODULES = 18;
|
|
@@ -20884,8 +21322,8 @@ function compactModules(prefixToNodes) {
|
|
|
20884
21322
|
function deriveModules(nodes) {
|
|
20885
21323
|
const initial = /* @__PURE__ */ new Map();
|
|
20886
21324
|
for (const node of nodes) {
|
|
20887
|
-
const
|
|
20888
|
-
const prefix = modulePrefixFromRelativePath(
|
|
21325
|
+
const relative14 = stripToProjectRelative(node.filePath);
|
|
21326
|
+
const prefix = modulePrefixFromRelativePath(relative14);
|
|
20889
21327
|
if (!initial.has(prefix)) initial.set(prefix, []);
|
|
20890
21328
|
initial.get(prefix)?.push(node);
|
|
20891
21329
|
}
|
|
@@ -21011,7 +21449,7 @@ function transformForVisualization(symbols, edges, options = {}) {
|
|
|
21011
21449
|
filePath: s.filePath,
|
|
21012
21450
|
kind: s.kind,
|
|
21013
21451
|
line: s.startLine,
|
|
21014
|
-
directory:
|
|
21452
|
+
directory: path31.dirname(s.filePath),
|
|
21015
21453
|
moduleId: "",
|
|
21016
21454
|
moduleLabel: ""
|
|
21017
21455
|
}));
|
|
@@ -21039,9 +21477,9 @@ function parseArgs(argv) {
|
|
|
21039
21477
|
let host = "opencode";
|
|
21040
21478
|
for (let i = 2; i < argv.length; i++) {
|
|
21041
21479
|
if (argv[i] === "--project" && argv[i + 1]) {
|
|
21042
|
-
project =
|
|
21480
|
+
project = path32.resolve(argv[++i]);
|
|
21043
21481
|
} else if (argv[i] === "--config" && argv[i + 1]) {
|
|
21044
|
-
config =
|
|
21482
|
+
config = path32.resolve(argv[++i]);
|
|
21045
21483
|
} else if (argv[i] === "--host" && argv[i + 1]) {
|
|
21046
21484
|
host = parseHostMode(argv[++i]);
|
|
21047
21485
|
} else if (argv[i] === "--host") {
|
|
@@ -21068,7 +21506,7 @@ function parseIndexArgs(argv, cwd) {
|
|
|
21068
21506
|
if (!arg.startsWith("--project=")) {
|
|
21069
21507
|
i += 1;
|
|
21070
21508
|
}
|
|
21071
|
-
project =
|
|
21509
|
+
project = path32.resolve(cwd, value);
|
|
21072
21510
|
continue;
|
|
21073
21511
|
}
|
|
21074
21512
|
if (arg === "--config" || arg.startsWith("--config=")) {
|
|
@@ -21079,7 +21517,7 @@ function parseIndexArgs(argv, cwd) {
|
|
|
21079
21517
|
if (!arg.startsWith("--config=")) {
|
|
21080
21518
|
i += 1;
|
|
21081
21519
|
}
|
|
21082
|
-
config =
|
|
21520
|
+
config = path32.resolve(cwd, value);
|
|
21083
21521
|
continue;
|
|
21084
21522
|
}
|
|
21085
21523
|
if (arg === "--host" || arg.startsWith("--host=")) {
|
|
@@ -21145,7 +21583,7 @@ function parseVisualizeArgs(argv, cwd) {
|
|
|
21145
21583
|
for (let i = 0; i < argv.length; i++) {
|
|
21146
21584
|
const arg = argv[i];
|
|
21147
21585
|
if (arg === "--project" && argv[i + 1]) {
|
|
21148
|
-
project =
|
|
21586
|
+
project = path32.resolve(argv[++i]);
|
|
21149
21587
|
} else if (arg === "--max" && argv[i + 1]) {
|
|
21150
21588
|
maxNodes = Number(argv[++i]);
|
|
21151
21589
|
} else if (arg.startsWith("--max=") || arg.startsWith("max=")) {
|
|
@@ -21182,7 +21620,7 @@ async function handleVisualizeCommand(argv, cwd) {
|
|
|
21182
21620
|
console.error("No connected symbols found. Retry with: npm run visualize -- orphans");
|
|
21183
21621
|
return 1;
|
|
21184
21622
|
}
|
|
21185
|
-
const outputPath =
|
|
21623
|
+
const outputPath = path32.join(os8.tmpdir(), `call-graph-${Date.now()}.html`);
|
|
21186
21624
|
writeFileSync6(outputPath, generateVisualizationHtml(vizData), "utf-8");
|
|
21187
21625
|
console.log(`Temporal call graph visualization generated: ${outputPath}`);
|
|
21188
21626
|
console.log(`Nodes: ${vizData.nodes.length} | Edges: ${vizData.edges.length}`);
|
|
@@ -21214,8 +21652,60 @@ async function runMcpCli(argv) {
|
|
|
21214
21652
|
const config = parseConfig(rawConfig);
|
|
21215
21653
|
const server = createMcpServer(args.project, config, args.host);
|
|
21216
21654
|
const transport = new StdioServerTransport();
|
|
21217
|
-
await server.connect(transport);
|
|
21218
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;
|
|
21219
21709
|
const isHomeDir = isHomeDirectory(args.project);
|
|
21220
21710
|
const isValidProject = !isHomeDir && (!config.indexing.requireProjectMarker || hasProjectMarker(args.project));
|
|
21221
21711
|
if (config.indexing.watchFiles && isValidProject) {
|
|
@@ -21227,26 +21717,6 @@ async function runMcpCli(argv) {
|
|
|
21227
21717
|
args.config ? { configPath: args.config } : {}
|
|
21228
21718
|
);
|
|
21229
21719
|
}
|
|
21230
|
-
let shuttingDown = false;
|
|
21231
|
-
const shutdown = async () => {
|
|
21232
|
-
if (shuttingDown) return;
|
|
21233
|
-
shuttingDown = true;
|
|
21234
|
-
try {
|
|
21235
|
-
await watcher?.stop();
|
|
21236
|
-
await stopAutoIndex(args.project, args.host);
|
|
21237
|
-
await server.close();
|
|
21238
|
-
process.exit(0);
|
|
21239
|
-
} catch (error) {
|
|
21240
|
-
console.error("Failed to stop MCP server cleanly:", error);
|
|
21241
|
-
process.exit(1);
|
|
21242
|
-
}
|
|
21243
|
-
};
|
|
21244
|
-
process.on("SIGINT", () => {
|
|
21245
|
-
void shutdown();
|
|
21246
|
-
});
|
|
21247
|
-
process.on("SIGTERM", () => {
|
|
21248
|
-
void shutdown();
|
|
21249
|
-
});
|
|
21250
21720
|
}
|
|
21251
21721
|
function printIndexProgress(onProgress, title, metadata) {
|
|
21252
21722
|
const details = Object.entries(metadata).filter(([, value]) => value !== void 0 && value !== null).map(([key, value]) => `${key}=${isSensitiveKey(key) ? "[REDACTED]" : String(value)}`).join(" ");
|