opencode-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/index.cjs
CHANGED
|
@@ -333,7 +333,7 @@ var require_ignore = __commonJS({
|
|
|
333
333
|
// path matching.
|
|
334
334
|
// - check `string` either `MODE_IGNORE` or `MODE_CHECK_IGNORE`
|
|
335
335
|
// @returns {TestResult} true if a file is ignored
|
|
336
|
-
test(
|
|
336
|
+
test(path30, checkUnignored, mode) {
|
|
337
337
|
let ignored = false;
|
|
338
338
|
let unignored = false;
|
|
339
339
|
let matchedRule;
|
|
@@ -342,7 +342,7 @@ var require_ignore = __commonJS({
|
|
|
342
342
|
if (unignored === negative && ignored !== unignored || negative && !ignored && !unignored && !checkUnignored) {
|
|
343
343
|
return;
|
|
344
344
|
}
|
|
345
|
-
const matched = rule[mode].test(
|
|
345
|
+
const matched = rule[mode].test(path30);
|
|
346
346
|
if (!matched) {
|
|
347
347
|
return;
|
|
348
348
|
}
|
|
@@ -363,17 +363,17 @@ var require_ignore = __commonJS({
|
|
|
363
363
|
var throwError = (message, Ctor) => {
|
|
364
364
|
throw new Ctor(message);
|
|
365
365
|
};
|
|
366
|
-
var checkPath = (
|
|
367
|
-
if (!isString(
|
|
366
|
+
var checkPath = (path30, originalPath, doThrow) => {
|
|
367
|
+
if (!isString(path30)) {
|
|
368
368
|
return doThrow(
|
|
369
369
|
`path must be a string, but got \`${originalPath}\``,
|
|
370
370
|
TypeError
|
|
371
371
|
);
|
|
372
372
|
}
|
|
373
|
-
if (!
|
|
373
|
+
if (!path30) {
|
|
374
374
|
return doThrow(`path must not be empty`, TypeError);
|
|
375
375
|
}
|
|
376
|
-
if (checkPath.isNotRelative(
|
|
376
|
+
if (checkPath.isNotRelative(path30)) {
|
|
377
377
|
const r = "`path.relative()`d";
|
|
378
378
|
return doThrow(
|
|
379
379
|
`path should be a ${r} string, but got "${originalPath}"`,
|
|
@@ -382,7 +382,7 @@ var require_ignore = __commonJS({
|
|
|
382
382
|
}
|
|
383
383
|
return true;
|
|
384
384
|
};
|
|
385
|
-
var isNotRelative = (
|
|
385
|
+
var isNotRelative = (path30) => REGEX_TEST_INVALID_PATH.test(path30);
|
|
386
386
|
checkPath.isNotRelative = isNotRelative;
|
|
387
387
|
checkPath.convert = (p) => p;
|
|
388
388
|
var Ignore2 = class {
|
|
@@ -412,19 +412,19 @@ var require_ignore = __commonJS({
|
|
|
412
412
|
}
|
|
413
413
|
// @returns {TestResult}
|
|
414
414
|
_test(originalPath, cache, checkUnignored, slices) {
|
|
415
|
-
const
|
|
415
|
+
const path30 = originalPath && checkPath.convert(originalPath);
|
|
416
416
|
checkPath(
|
|
417
|
-
|
|
417
|
+
path30,
|
|
418
418
|
originalPath,
|
|
419
419
|
this._strictPathCheck ? throwError : RETURN_FALSE
|
|
420
420
|
);
|
|
421
|
-
return this._t(
|
|
421
|
+
return this._t(path30, cache, checkUnignored, slices);
|
|
422
422
|
}
|
|
423
|
-
checkIgnore(
|
|
424
|
-
if (!REGEX_TEST_TRAILING_SLASH.test(
|
|
425
|
-
return this.test(
|
|
423
|
+
checkIgnore(path30) {
|
|
424
|
+
if (!REGEX_TEST_TRAILING_SLASH.test(path30)) {
|
|
425
|
+
return this.test(path30);
|
|
426
426
|
}
|
|
427
|
-
const slices =
|
|
427
|
+
const slices = path30.split(SLASH2).filter(Boolean);
|
|
428
428
|
slices.pop();
|
|
429
429
|
if (slices.length) {
|
|
430
430
|
const parent = this._t(
|
|
@@ -437,18 +437,18 @@ var require_ignore = __commonJS({
|
|
|
437
437
|
return parent;
|
|
438
438
|
}
|
|
439
439
|
}
|
|
440
|
-
return this._rules.test(
|
|
440
|
+
return this._rules.test(path30, false, MODE_CHECK_IGNORE);
|
|
441
441
|
}
|
|
442
|
-
_t(
|
|
443
|
-
if (
|
|
444
|
-
return cache[
|
|
442
|
+
_t(path30, cache, checkUnignored, slices) {
|
|
443
|
+
if (path30 in cache) {
|
|
444
|
+
return cache[path30];
|
|
445
445
|
}
|
|
446
446
|
if (!slices) {
|
|
447
|
-
slices =
|
|
447
|
+
slices = path30.split(SLASH2).filter(Boolean);
|
|
448
448
|
}
|
|
449
449
|
slices.pop();
|
|
450
450
|
if (!slices.length) {
|
|
451
|
-
return cache[
|
|
451
|
+
return cache[path30] = this._rules.test(path30, checkUnignored, MODE_IGNORE);
|
|
452
452
|
}
|
|
453
453
|
const parent = this._t(
|
|
454
454
|
slices.join(SLASH2) + SLASH2,
|
|
@@ -456,29 +456,29 @@ var require_ignore = __commonJS({
|
|
|
456
456
|
checkUnignored,
|
|
457
457
|
slices
|
|
458
458
|
);
|
|
459
|
-
return cache[
|
|
459
|
+
return cache[path30] = parent.ignored ? parent : this._rules.test(path30, checkUnignored, MODE_IGNORE);
|
|
460
460
|
}
|
|
461
|
-
ignores(
|
|
462
|
-
return this._test(
|
|
461
|
+
ignores(path30) {
|
|
462
|
+
return this._test(path30, this._ignoreCache, false).ignored;
|
|
463
463
|
}
|
|
464
464
|
createFilter() {
|
|
465
|
-
return (
|
|
465
|
+
return (path30) => !this.ignores(path30);
|
|
466
466
|
}
|
|
467
467
|
filter(paths) {
|
|
468
468
|
return makeArray(paths).filter(this.createFilter());
|
|
469
469
|
}
|
|
470
470
|
// @returns {TestResult}
|
|
471
|
-
test(
|
|
472
|
-
return this._test(
|
|
471
|
+
test(path30) {
|
|
472
|
+
return this._test(path30, this._testCache, true);
|
|
473
473
|
}
|
|
474
474
|
};
|
|
475
475
|
var factory = (options) => new Ignore2(options);
|
|
476
|
-
var isPathValid = (
|
|
476
|
+
var isPathValid = (path30) => checkPath(path30 && checkPath.convert(path30), path30, RETURN_FALSE);
|
|
477
477
|
var setupWindows = () => {
|
|
478
478
|
const makePosix = (str) => /^\\\\\?\\/.test(str) || /["<>|\u0000-\u001F]+/u.test(str) ? str : str.replace(/\\/g, "/");
|
|
479
479
|
checkPath.convert = makePosix;
|
|
480
480
|
const REGEX_TEST_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i;
|
|
481
|
-
checkPath.isNotRelative = (
|
|
481
|
+
checkPath.isNotRelative = (path30) => REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path30) || isNotRelative(path30);
|
|
482
482
|
};
|
|
483
483
|
if (
|
|
484
484
|
// Detect `process` so that it can run in browsers.
|
|
@@ -663,7 +663,7 @@ __export(index_exports, {
|
|
|
663
663
|
module.exports = __toCommonJS(index_exports);
|
|
664
664
|
|
|
665
665
|
// src/adapters/opencode.ts
|
|
666
|
-
var
|
|
666
|
+
var path29 = __toESM(require("path"), 1);
|
|
667
667
|
var import_url = require("url");
|
|
668
668
|
|
|
669
669
|
// src/config/constants.ts
|
|
@@ -1141,11 +1141,11 @@ function resolveGitDir(repoRoot) {
|
|
|
1141
1141
|
return null;
|
|
1142
1142
|
}
|
|
1143
1143
|
try {
|
|
1144
|
-
const
|
|
1145
|
-
if (
|
|
1144
|
+
const stat5 = (0, import_fs2.statSync)(gitPath);
|
|
1145
|
+
if (stat5.isDirectory()) {
|
|
1146
1146
|
return gitPath;
|
|
1147
1147
|
}
|
|
1148
|
-
if (
|
|
1148
|
+
if (stat5.isFile()) {
|
|
1149
1149
|
const content = (0, import_fs2.readFileSync)(gitPath, "utf-8").trim();
|
|
1150
1150
|
const match = content.match(/^gitdir:\s*(.+)$/);
|
|
1151
1151
|
if (match) {
|
|
@@ -2214,7 +2214,7 @@ function analyzeQueryIntent(query) {
|
|
|
2214
2214
|
}
|
|
2215
2215
|
function isTestPath(filePath) {
|
|
2216
2216
|
const normalized = normalizePath(filePath);
|
|
2217
|
-
return /(?:^|\/)(?:test|tests|__tests__|spec|specs)(?:\/|$)/u.test(normalized) ||
|
|
2217
|
+
return /(?:^|\/)(?:test|tests|__tests__|spec|specs)(?:\/|$)/u.test(normalized) || /(?:\.(?:test|spec)|_(?:test|spec))\.[^/]+$/u.test(normalized) || /(?:^|\/)(?:test|spec)_[^/]+\.[^/]+$/u.test(normalized);
|
|
2218
2218
|
}
|
|
2219
2219
|
function isFixturePath(filePath) {
|
|
2220
2220
|
const normalized = normalizePath(filePath);
|
|
@@ -2589,8 +2589,8 @@ function formatExactSearchHandoff(results) {
|
|
|
2589
2589
|
}
|
|
2590
2590
|
function formatContextEvidence(result, index) {
|
|
2591
2591
|
const symbol = result.name ? ` ${JSON.stringify(compactEvidenceValue(result.name, 80))}` : "";
|
|
2592
|
-
const
|
|
2593
|
-
return `[${index}] ${result.chunkType}${symbol} in ${
|
|
2592
|
+
const path30 = compactEvidenceValue(result.filePath, 120);
|
|
2593
|
+
return `[${index}] ${result.chunkType}${symbol} in ${path30}:${result.startLine}-${result.endLine} (score ${result.score.toFixed(2)})`;
|
|
2594
2594
|
}
|
|
2595
2595
|
function formatContextPack(heading, selected, candidateCount, duplicateCount, limitOmittedCount, budgetOmittedCount, includeExactSearchHandoff) {
|
|
2596
2596
|
const lines = selected.map((result, index) => formatContextEvidence(result, index + 1));
|
|
@@ -3743,8 +3743,8 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
|
|
|
3743
3743
|
if (entry.isDirectory()) {
|
|
3744
3744
|
subdirs.push({ fullPath, relativePath });
|
|
3745
3745
|
} else if (entry.isFile()) {
|
|
3746
|
-
const
|
|
3747
|
-
if (
|
|
3746
|
+
const stat5 = await import_fs6.promises.stat(fullPath);
|
|
3747
|
+
if (stat5.size > maxFileSize) {
|
|
3748
3748
|
skipped.push({ path: relativePath, reason: "too_large" });
|
|
3749
3749
|
continue;
|
|
3750
3750
|
}
|
|
@@ -3762,7 +3762,7 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
|
|
|
3762
3762
|
}
|
|
3763
3763
|
}
|
|
3764
3764
|
if (matched) {
|
|
3765
|
-
filesInDir.push({ path: fullPath, size:
|
|
3765
|
+
filesInDir.push({ path: fullPath, size: stat5.size });
|
|
3766
3766
|
}
|
|
3767
3767
|
}
|
|
3768
3768
|
}
|
|
@@ -3819,8 +3819,8 @@ async function collectFiles(projectRoot, includePatterns, excludePatterns, maxFi
|
|
|
3819
3819
|
}
|
|
3820
3820
|
for (const resolvedKbRoot of normalizedRoots) {
|
|
3821
3821
|
try {
|
|
3822
|
-
const
|
|
3823
|
-
if (!
|
|
3822
|
+
const stat5 = await import_fs6.promises.stat(resolvedKbRoot);
|
|
3823
|
+
if (!stat5.isDirectory()) {
|
|
3824
3824
|
skipped.push({ path: resolvedKbRoot, reason: "excluded" });
|
|
3825
3825
|
continue;
|
|
3826
3826
|
}
|
|
@@ -3854,7 +3854,7 @@ function getErrorMessage(error) {
|
|
|
3854
3854
|
return error instanceof Error ? error.message : String(error);
|
|
3855
3855
|
}
|
|
3856
3856
|
function runCommand(file, args, options) {
|
|
3857
|
-
return new Promise((
|
|
3857
|
+
return new Promise((resolve17, reject) => {
|
|
3858
3858
|
childProcess.execFile(
|
|
3859
3859
|
file,
|
|
3860
3860
|
args,
|
|
@@ -3864,7 +3864,7 @@ function runCommand(file, args, options) {
|
|
|
3864
3864
|
reject(error);
|
|
3865
3865
|
return;
|
|
3866
3866
|
}
|
|
3867
|
-
|
|
3867
|
+
resolve17(stdout);
|
|
3868
3868
|
}
|
|
3869
3869
|
);
|
|
3870
3870
|
});
|
|
@@ -4009,10 +4009,10 @@ function safeFailureMessage(error) {
|
|
|
4009
4009
|
}
|
|
4010
4010
|
function cancellableDelay(delayMs, signal) {
|
|
4011
4011
|
if (signal.aborted) return Promise.reject(new AutoIndexCancelledError());
|
|
4012
|
-
return new Promise((
|
|
4012
|
+
return new Promise((resolve17, reject) => {
|
|
4013
4013
|
const timer = setTimeout(() => {
|
|
4014
4014
|
signal.removeEventListener("abort", onAbort);
|
|
4015
|
-
|
|
4015
|
+
resolve17();
|
|
4016
4016
|
}, delayMs);
|
|
4017
4017
|
timer.unref?.();
|
|
4018
4018
|
const onAbort = () => {
|
|
@@ -4024,15 +4024,15 @@ function cancellableDelay(delayMs, signal) {
|
|
|
4024
4024
|
}
|
|
4025
4025
|
function withTimeout(promise, timeoutMs) {
|
|
4026
4026
|
if (timeoutMs <= 0) return Promise.resolve(void 0);
|
|
4027
|
-
return new Promise((
|
|
4028
|
-
const timer = setTimeout(() =>
|
|
4027
|
+
return new Promise((resolve17) => {
|
|
4028
|
+
const timer = setTimeout(() => resolve17(void 0), timeoutMs);
|
|
4029
4029
|
timer.unref?.();
|
|
4030
4030
|
void promise.then((value) => {
|
|
4031
4031
|
clearTimeout(timer);
|
|
4032
|
-
|
|
4032
|
+
resolve17(value);
|
|
4033
4033
|
}, () => {
|
|
4034
4034
|
clearTimeout(timer);
|
|
4035
|
-
|
|
4035
|
+
resolve17(void 0);
|
|
4036
4036
|
});
|
|
4037
4037
|
});
|
|
4038
4038
|
}
|
|
@@ -4414,17 +4414,17 @@ var AutoIndexCoordinator = class {
|
|
|
4414
4414
|
}
|
|
4415
4415
|
}
|
|
4416
4416
|
waitForBatteryRetry(delayMs) {
|
|
4417
|
-
return new Promise((
|
|
4417
|
+
return new Promise((resolve17) => {
|
|
4418
4418
|
const timer = setTimeout(() => {
|
|
4419
4419
|
if (this.batteryRetryTimer === timer) {
|
|
4420
4420
|
this.batteryRetryTimer = null;
|
|
4421
4421
|
this.resolveBatteryRetry = null;
|
|
4422
4422
|
}
|
|
4423
|
-
|
|
4423
|
+
resolve17();
|
|
4424
4424
|
}, delayMs);
|
|
4425
4425
|
timer.unref?.();
|
|
4426
4426
|
this.batteryRetryTimer = timer;
|
|
4427
|
-
this.resolveBatteryRetry =
|
|
4427
|
+
this.resolveBatteryRetry = resolve17;
|
|
4428
4428
|
});
|
|
4429
4429
|
}
|
|
4430
4430
|
cancelBatteryRetry() {
|
|
@@ -4432,9 +4432,9 @@ var AutoIndexCoordinator = class {
|
|
|
4432
4432
|
clearTimeout(this.batteryRetryTimer);
|
|
4433
4433
|
this.batteryRetryTimer = null;
|
|
4434
4434
|
}
|
|
4435
|
-
const
|
|
4435
|
+
const resolve17 = this.resolveBatteryRetry;
|
|
4436
4436
|
this.resolveBatteryRetry = null;
|
|
4437
|
-
|
|
4437
|
+
resolve17?.();
|
|
4438
4438
|
}
|
|
4439
4439
|
finishBatteryCheck(batteryCheck) {
|
|
4440
4440
|
if (this.batteryCheck !== batteryCheck) return;
|
|
@@ -4639,7 +4639,7 @@ function pTimeout(promise, options) {
|
|
|
4639
4639
|
} = options;
|
|
4640
4640
|
let timer;
|
|
4641
4641
|
let abortHandler;
|
|
4642
|
-
const wrappedPromise = new Promise((
|
|
4642
|
+
const wrappedPromise = new Promise((resolve17, reject) => {
|
|
4643
4643
|
if (typeof milliseconds !== "number" || Math.sign(milliseconds) !== 1) {
|
|
4644
4644
|
throw new TypeError(`Expected \`milliseconds\` to be a positive number, got \`${milliseconds}\``);
|
|
4645
4645
|
}
|
|
@@ -4653,7 +4653,7 @@ function pTimeout(promise, options) {
|
|
|
4653
4653
|
};
|
|
4654
4654
|
signal.addEventListener("abort", abortHandler, { once: true });
|
|
4655
4655
|
}
|
|
4656
|
-
promise.then(
|
|
4656
|
+
promise.then(resolve17, reject);
|
|
4657
4657
|
if (milliseconds === Number.POSITIVE_INFINITY) {
|
|
4658
4658
|
return;
|
|
4659
4659
|
}
|
|
@@ -4661,7 +4661,7 @@ function pTimeout(promise, options) {
|
|
|
4661
4661
|
timer = customTimers.setTimeout.call(void 0, () => {
|
|
4662
4662
|
if (fallback) {
|
|
4663
4663
|
try {
|
|
4664
|
-
|
|
4664
|
+
resolve17(fallback());
|
|
4665
4665
|
} catch (error) {
|
|
4666
4666
|
reject(error);
|
|
4667
4667
|
}
|
|
@@ -4671,7 +4671,7 @@ function pTimeout(promise, options) {
|
|
|
4671
4671
|
promise.cancel();
|
|
4672
4672
|
}
|
|
4673
4673
|
if (message === false) {
|
|
4674
|
-
|
|
4674
|
+
resolve17();
|
|
4675
4675
|
} else if (message instanceof Error) {
|
|
4676
4676
|
reject(message);
|
|
4677
4677
|
} else {
|
|
@@ -5073,7 +5073,7 @@ var PQueue = class extends import_index.default {
|
|
|
5073
5073
|
// Assign unique ID if not provided
|
|
5074
5074
|
id: options.id ?? (this.#idAssigner++).toString()
|
|
5075
5075
|
};
|
|
5076
|
-
return new Promise((
|
|
5076
|
+
return new Promise((resolve17, reject) => {
|
|
5077
5077
|
const taskSymbol = /* @__PURE__ */ Symbol(`task-${options.id}`);
|
|
5078
5078
|
let cleanupQueueAbortHandler = () => void 0;
|
|
5079
5079
|
const run = async () => {
|
|
@@ -5113,7 +5113,7 @@ var PQueue = class extends import_index.default {
|
|
|
5113
5113
|
})]);
|
|
5114
5114
|
}
|
|
5115
5115
|
const result = await operation;
|
|
5116
|
-
|
|
5116
|
+
resolve17(result);
|
|
5117
5117
|
this.emit("completed", result);
|
|
5118
5118
|
} catch (error) {
|
|
5119
5119
|
reject(error);
|
|
@@ -5301,13 +5301,13 @@ var PQueue = class extends import_index.default {
|
|
|
5301
5301
|
});
|
|
5302
5302
|
}
|
|
5303
5303
|
async #onEvent(event, filter) {
|
|
5304
|
-
return new Promise((
|
|
5304
|
+
return new Promise((resolve17) => {
|
|
5305
5305
|
const listener = () => {
|
|
5306
5306
|
if (filter && !filter()) {
|
|
5307
5307
|
return;
|
|
5308
5308
|
}
|
|
5309
5309
|
this.off(event, listener);
|
|
5310
|
-
|
|
5310
|
+
resolve17();
|
|
5311
5311
|
};
|
|
5312
5312
|
this.on(event, listener);
|
|
5313
5313
|
});
|
|
@@ -5593,7 +5593,7 @@ async function onAttemptFailure({ error, attemptNumber, retriesConsumed, startTi
|
|
|
5593
5593
|
const finalDelay = Math.min(delayTime, remainingTime);
|
|
5594
5594
|
options.signal?.throwIfAborted();
|
|
5595
5595
|
if (finalDelay > 0) {
|
|
5596
|
-
await new Promise((
|
|
5596
|
+
await new Promise((resolve17, reject) => {
|
|
5597
5597
|
const onAbort = () => {
|
|
5598
5598
|
clearTimeout(timeoutToken);
|
|
5599
5599
|
options.signal?.removeEventListener("abort", onAbort);
|
|
@@ -5601,7 +5601,7 @@ async function onAttemptFailure({ error, attemptNumber, retriesConsumed, startTi
|
|
|
5601
5601
|
};
|
|
5602
5602
|
const timeoutToken = setTimeout(() => {
|
|
5603
5603
|
options.signal?.removeEventListener("abort", onAbort);
|
|
5604
|
-
|
|
5604
|
+
resolve17();
|
|
5605
5605
|
}, finalDelay);
|
|
5606
5606
|
if (options.unref) {
|
|
5607
5607
|
timeoutToken.unref?.();
|
|
@@ -6407,85 +6407,6 @@ function createEmbeddingProvider(configuredProviderInfo) {
|
|
|
6407
6407
|
}
|
|
6408
6408
|
}
|
|
6409
6409
|
|
|
6410
|
-
// src/rerank/index.ts
|
|
6411
|
-
function createReranker(config) {
|
|
6412
|
-
if (!config.enabled) {
|
|
6413
|
-
return new NoOpReranker();
|
|
6414
|
-
}
|
|
6415
|
-
return new SiliconFlowReranker(config);
|
|
6416
|
-
}
|
|
6417
|
-
var NoOpReranker = class {
|
|
6418
|
-
isAvailable() {
|
|
6419
|
-
return false;
|
|
6420
|
-
}
|
|
6421
|
-
async rerank(_query, documents, _topN) {
|
|
6422
|
-
return {
|
|
6423
|
-
results: documents.map((_, index) => ({ index, relevanceScore: 0 }))
|
|
6424
|
-
};
|
|
6425
|
-
}
|
|
6426
|
-
};
|
|
6427
|
-
var SiliconFlowReranker = class {
|
|
6428
|
-
config;
|
|
6429
|
-
constructor(config) {
|
|
6430
|
-
this.config = config;
|
|
6431
|
-
}
|
|
6432
|
-
isAvailable() {
|
|
6433
|
-
return this.config.enabled && !!this.config.baseUrl && !!this.config.model;
|
|
6434
|
-
}
|
|
6435
|
-
async rerank(query, documents, topN) {
|
|
6436
|
-
if (documents.length === 0) {
|
|
6437
|
-
return { results: [] };
|
|
6438
|
-
}
|
|
6439
|
-
const headers = {
|
|
6440
|
-
"Content-Type": "application/json"
|
|
6441
|
-
};
|
|
6442
|
-
if (this.config.apiKey) {
|
|
6443
|
-
headers["Authorization"] = `Bearer ${this.config.apiKey}`;
|
|
6444
|
-
}
|
|
6445
|
-
const baseUrl = this.config.baseUrl;
|
|
6446
|
-
if (!baseUrl) {
|
|
6447
|
-
throw new Error("Reranker baseUrl is required. Configure reranker.baseUrl in your codebase-index.json.");
|
|
6448
|
-
}
|
|
6449
|
-
const timeoutMs = this.config.timeoutMs ?? 3e4;
|
|
6450
|
-
const controller = new AbortController();
|
|
6451
|
-
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
6452
|
-
try {
|
|
6453
|
-
const response = await fetch(`${baseUrl}/rerank`, {
|
|
6454
|
-
method: "POST",
|
|
6455
|
-
headers,
|
|
6456
|
-
body: JSON.stringify({
|
|
6457
|
-
model: this.config.model,
|
|
6458
|
-
query,
|
|
6459
|
-
documents,
|
|
6460
|
-
top_n: topN ?? this.config.topN ?? 20,
|
|
6461
|
-
return_documents: false
|
|
6462
|
-
}),
|
|
6463
|
-
signal: controller.signal
|
|
6464
|
-
});
|
|
6465
|
-
clearTimeout(timeout);
|
|
6466
|
-
if (!response.ok) {
|
|
6467
|
-
const errorText = await response.text();
|
|
6468
|
-
throw new Error(`Rerank API error: ${response.status} - ${errorText}`);
|
|
6469
|
-
}
|
|
6470
|
-
const data = await response.json();
|
|
6471
|
-
return {
|
|
6472
|
-
results: data.results.map((r) => ({
|
|
6473
|
-
index: r.index,
|
|
6474
|
-
relevanceScore: r.relevance_score,
|
|
6475
|
-
document: r.document?.text
|
|
6476
|
-
})),
|
|
6477
|
-
tokensUsed: data.meta?.tokens?.input_tokens
|
|
6478
|
-
};
|
|
6479
|
-
} catch (error) {
|
|
6480
|
-
clearTimeout(timeout);
|
|
6481
|
-
if (error instanceof Error && error.name === "AbortError") {
|
|
6482
|
-
throw new Error(`Rerank API request timed out after ${timeoutMs}ms`);
|
|
6483
|
-
}
|
|
6484
|
-
throw error;
|
|
6485
|
-
}
|
|
6486
|
-
}
|
|
6487
|
-
};
|
|
6488
|
-
|
|
6489
6410
|
// src/utils/cost.ts
|
|
6490
6411
|
function estimateChunksFromFiles(files) {
|
|
6491
6412
|
let totalChunks = 0;
|
|
@@ -8046,8 +7967,8 @@ async function isWorktreeRegistered(projectRoot, worktreePath) {
|
|
|
8046
7967
|
return false;
|
|
8047
7968
|
}
|
|
8048
7969
|
function isPathWithinRoot(filePath, rootPath) {
|
|
8049
|
-
const
|
|
8050
|
-
return
|
|
7970
|
+
const relative14 = path15.relative(path15.resolve(rootPath), path15.resolve(filePath));
|
|
7971
|
+
return relative14 === "" || !relative14.startsWith(`..${path15.sep}`) && relative14 !== ".." && !path15.isAbsolute(relative14);
|
|
8051
7972
|
}
|
|
8052
7973
|
async function pruneExactMissingWorktreeRegistration(projectRoot, worktreePath) {
|
|
8053
7974
|
if (await pathExists(worktreePath)) return false;
|
|
@@ -8424,11 +8345,11 @@ function normalizeFiles(rawFiles, projectRoot) {
|
|
|
8424
8345
|
for (const raw of rawFiles) {
|
|
8425
8346
|
if (raw.length === 0) continue;
|
|
8426
8347
|
const absolute = path16.resolve(root, raw);
|
|
8427
|
-
const
|
|
8428
|
-
if (path16.isAbsolute(raw) ||
|
|
8348
|
+
const relative14 = path16.relative(root, absolute);
|
|
8349
|
+
if (path16.isAbsolute(raw) || relative14 === ".." || relative14.startsWith(`..${path16.sep}`) || path16.isAbsolute(relative14)) {
|
|
8429
8350
|
throw new Error(`Changed file escapes the project root: ${JSON.stringify(raw)}`);
|
|
8430
8351
|
}
|
|
8431
|
-
const cleaned =
|
|
8352
|
+
const cleaned = relative14.startsWith(`.${path16.sep}`) ? relative14.slice(2) : relative14;
|
|
8432
8353
|
if (!seen.has(cleaned)) {
|
|
8433
8354
|
seen.add(cleaned);
|
|
8434
8355
|
result.push(cleaned);
|
|
@@ -8660,7 +8581,8 @@ function rankHybridResults(query, semanticResults, keywordResults, options) {
|
|
|
8660
8581
|
return cached;
|
|
8661
8582
|
}
|
|
8662
8583
|
}
|
|
8663
|
-
const
|
|
8584
|
+
const overfetchFactor = prioritizeSourcePaths ? 12 : 4;
|
|
8585
|
+
const overfetchLimit = Math.max(options.limit * overfetchFactor, options.limit);
|
|
8664
8586
|
const fused = options.fusionStrategy === "rrf" ? fuseResultsRrf(semanticResults, keywordResults, options.rrfK, overfetchLimit) : fuseResultsWeighted(semanticResults, keywordResults, options.hybridWeight, overfetchLimit);
|
|
8665
8587
|
const rerankPoolLimit = Math.max(overfetchLimit, options.rerankTopN * 3, options.limit * 6);
|
|
8666
8588
|
const rerankPool = fused.slice(0, rerankPoolLimit);
|
|
@@ -10171,7 +10093,6 @@ var Indexer = class _Indexer {
|
|
|
10171
10093
|
database = null;
|
|
10172
10094
|
provider = null;
|
|
10173
10095
|
configuredProviderInfo = null;
|
|
10174
|
-
reranker = null;
|
|
10175
10096
|
fileHashCache = /* @__PURE__ */ new Map();
|
|
10176
10097
|
fileHashCachePath = "";
|
|
10177
10098
|
failedBatchesPath = "";
|
|
@@ -10331,7 +10252,6 @@ var Indexer = class _Indexer {
|
|
|
10331
10252
|
this.database = null;
|
|
10332
10253
|
this.provider = null;
|
|
10333
10254
|
this.configuredProviderInfo = null;
|
|
10334
|
-
this.reranker = null;
|
|
10335
10255
|
this.indexCompatibility = null;
|
|
10336
10256
|
this.initializationMode = "none";
|
|
10337
10257
|
this.readIssues = [];
|
|
@@ -11061,7 +10981,7 @@ var Indexer = class _Indexer {
|
|
|
11061
10981
|
await options.queue.onSizeLessThan(Math.max(1, options.providerRateLimits.concurrency));
|
|
11062
10982
|
const task = options.queue.add(async () => {
|
|
11063
10983
|
if (options.rateLimitState.backoffMs > 0) {
|
|
11064
|
-
await new Promise((
|
|
10984
|
+
await new Promise((resolve17) => setTimeout(resolve17, options.rateLimitState.backoffMs));
|
|
11065
10985
|
}
|
|
11066
10986
|
try {
|
|
11067
10987
|
const embeddingResult = await pRetry(
|
|
@@ -11628,15 +11548,6 @@ var Indexer = class _Indexer {
|
|
|
11628
11548
|
rerankerEnabled: this.config.reranker?.enabled ?? false
|
|
11629
11549
|
});
|
|
11630
11550
|
this.provider = createEmbeddingProvider(this.configuredProviderInfo);
|
|
11631
|
-
if (this.config.reranker?.enabled) {
|
|
11632
|
-
this.reranker = createReranker(this.config.reranker);
|
|
11633
|
-
if (this.reranker.isAvailable()) {
|
|
11634
|
-
this.logger.info("Reranker initialized", {
|
|
11635
|
-
model: this.config.reranker.model,
|
|
11636
|
-
baseUrl: this.config.reranker.baseUrl
|
|
11637
|
-
});
|
|
11638
|
-
}
|
|
11639
|
-
}
|
|
11640
11551
|
const dimensions = this.configuredProviderInfo.modelInfo.dimensions;
|
|
11641
11552
|
const storePath = path19.join(this.indexPath, "vectors");
|
|
11642
11553
|
const vectorMetadataPath = `${storePath}.meta.json`;
|
|
@@ -13041,6 +12952,7 @@ var Indexer = class _Indexer {
|
|
|
13041
12952
|
const filterByBranch = options?.filterByBranch ?? true;
|
|
13042
12953
|
const sourceIntent = options?.definitionIntent === true || classifyQueryIntentRaw(query) === "source";
|
|
13043
12954
|
const identifierHints = extractIdentifierHints(query);
|
|
12955
|
+
const candidateLimit = maxResults * (sourceIntent ? 12 : 4);
|
|
13044
12956
|
this.logger.search("debug", "Starting search", {
|
|
13045
12957
|
query,
|
|
13046
12958
|
maxResults,
|
|
@@ -13077,7 +12989,7 @@ var Indexer = class _Indexer {
|
|
|
13077
12989
|
const semanticCandidates = embedding ? this.searchSemanticCandidates(
|
|
13078
12990
|
store,
|
|
13079
12991
|
embedding,
|
|
13080
|
-
|
|
12992
|
+
candidateLimit,
|
|
13081
12993
|
branchChunkIds,
|
|
13082
12994
|
shouldPrefilterByBranch
|
|
13083
12995
|
) : [];
|
|
@@ -13085,7 +12997,7 @@ var Indexer = class _Indexer {
|
|
|
13085
12997
|
const keywordStartTime = import_perf_hooks.performance.now();
|
|
13086
12998
|
const keywordCandidates = await this.keywordSearch(
|
|
13087
12999
|
query,
|
|
13088
|
-
|
|
13000
|
+
candidateLimit,
|
|
13089
13001
|
store,
|
|
13090
13002
|
invertedIndex,
|
|
13091
13003
|
branchChunkIds,
|
|
@@ -13843,9 +13755,9 @@ var Indexer = class _Indexer {
|
|
|
13843
13755
|
this.requireReadableComponents(readIssues, "database");
|
|
13844
13756
|
let shortest = [];
|
|
13845
13757
|
for (const branchKey of this.getBranchCatalogKeys()) {
|
|
13846
|
-
const
|
|
13847
|
-
if (
|
|
13848
|
-
shortest =
|
|
13758
|
+
const path30 = database.findShortestPath(fromName, toName, branchKey, maxDepth);
|
|
13759
|
+
if (path30.length > 0 && (shortest.length === 0 || path30.length < shortest.length)) {
|
|
13760
|
+
shortest = path30;
|
|
13849
13761
|
}
|
|
13850
13762
|
}
|
|
13851
13763
|
return shortest.map((hop) => this.resolveFilePathRecord(hop));
|
|
@@ -13893,13 +13805,13 @@ var Indexer = class _Indexer {
|
|
|
13893
13805
|
}
|
|
13894
13806
|
}
|
|
13895
13807
|
if (!found) continue;
|
|
13896
|
-
const
|
|
13808
|
+
const path30 = [];
|
|
13897
13809
|
let currentSymbolId = toSymbolId;
|
|
13898
13810
|
while (true) {
|
|
13899
13811
|
const symbol = symbolsById.get(currentSymbolId);
|
|
13900
13812
|
if (!symbol) break;
|
|
13901
13813
|
const parent = parentBySymbolId.get(currentSymbolId);
|
|
13902
|
-
|
|
13814
|
+
path30.push({
|
|
13903
13815
|
symbolId: symbol.id,
|
|
13904
13816
|
symbolName: symbol.name,
|
|
13905
13817
|
filePath: symbol.filePath,
|
|
@@ -13909,9 +13821,9 @@ var Indexer = class _Indexer {
|
|
|
13909
13821
|
if (!parent) break;
|
|
13910
13822
|
currentSymbolId = parent.parentId;
|
|
13911
13823
|
}
|
|
13912
|
-
|
|
13913
|
-
if (
|
|
13914
|
-
shortest =
|
|
13824
|
+
path30.reverse();
|
|
13825
|
+
if (path30.length > 0 && (shortest.length === 0 || path30.length < shortest.length)) {
|
|
13826
|
+
shortest = path30;
|
|
13915
13827
|
}
|
|
13916
13828
|
}
|
|
13917
13829
|
return shortest.map((hop) => this.resolveFilePathRecord(hop));
|
|
@@ -14247,7 +14159,6 @@ var Indexer = class _Indexer {
|
|
|
14247
14159
|
this.store = null;
|
|
14248
14160
|
this.invertedIndex = null;
|
|
14249
14161
|
this.provider = null;
|
|
14250
|
-
this.reranker = null;
|
|
14251
14162
|
this.configuredProviderInfo = null;
|
|
14252
14163
|
this.indexCompatibility = null;
|
|
14253
14164
|
this.initializationMode = "none";
|
|
@@ -14572,12 +14483,12 @@ async function getCallGraphPath(projectRoot, host, from, to, maxDepth, fromFileP
|
|
|
14572
14483
|
if (fromResolution.status !== "resolved" || toResolution.status !== "resolved") {
|
|
14573
14484
|
return { from: fromResolution, to: toResolution, path: [] };
|
|
14574
14485
|
}
|
|
14575
|
-
const
|
|
14486
|
+
const path30 = await indexer.findCallPathBySymbolIds(
|
|
14576
14487
|
fromResolution.symbolId,
|
|
14577
14488
|
toResolution.symbolId,
|
|
14578
14489
|
maxDepth
|
|
14579
14490
|
);
|
|
14580
|
-
return { from: fromResolution, to: toResolution, path:
|
|
14491
|
+
return { from: fromResolution, to: toResolution, path: path30 };
|
|
14581
14492
|
}
|
|
14582
14493
|
async function runIndexCodebase(projectRoot, host, args, onProgress) {
|
|
14583
14494
|
const root = getProjectRoot(projectRoot, host);
|
|
@@ -14803,8 +14714,8 @@ function addKnowledgeBase(projectRoot, host, knowledgeBasePath) {
|
|
|
14803
14714
|
}
|
|
14804
14715
|
}
|
|
14805
14716
|
try {
|
|
14806
|
-
const
|
|
14807
|
-
if (!
|
|
14717
|
+
const stat5 = (0, import_fs13.statSync)(normalizedPath2);
|
|
14718
|
+
if (!stat5.isDirectory()) {
|
|
14808
14719
|
return `Error: Path is not a directory: ${normalizedPath2}`;
|
|
14809
14720
|
}
|
|
14810
14721
|
} catch (error) {
|
|
@@ -14852,8 +14763,8 @@ function listKnowledgeBases(projectRoot, host) {
|
|
|
14852
14763
|
`;
|
|
14853
14764
|
if (exists) {
|
|
14854
14765
|
try {
|
|
14855
|
-
const
|
|
14856
|
-
result += ` Type: ${
|
|
14766
|
+
const stat5 = (0, import_fs13.statSync)(resolvedPath);
|
|
14767
|
+
result += ` Type: ${stat5.isDirectory() ? "Directory" : "File"}
|
|
14857
14768
|
`;
|
|
14858
14769
|
} catch {
|
|
14859
14770
|
}
|
|
@@ -14986,7 +14897,7 @@ var ReaddirpStream = class extends import_node_stream.Readable {
|
|
|
14986
14897
|
this._directoryFilter = normalizeFilter(opts.directoryFilter);
|
|
14987
14898
|
const statMethod = opts.lstat ? import_promises.lstat : import_promises.stat;
|
|
14988
14899
|
if (wantBigintFsStats) {
|
|
14989
|
-
this._stat = (
|
|
14900
|
+
this._stat = (path30) => statMethod(path30, { bigint: true });
|
|
14990
14901
|
} else {
|
|
14991
14902
|
this._stat = statMethod;
|
|
14992
14903
|
}
|
|
@@ -15011,8 +14922,8 @@ var ReaddirpStream = class extends import_node_stream.Readable {
|
|
|
15011
14922
|
const par = this.parent;
|
|
15012
14923
|
const fil = par && par.files;
|
|
15013
14924
|
if (fil && fil.length > 0) {
|
|
15014
|
-
const { path:
|
|
15015
|
-
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent,
|
|
14925
|
+
const { path: path30, depth } = par;
|
|
14926
|
+
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path30));
|
|
15016
14927
|
const awaited = await Promise.all(slice);
|
|
15017
14928
|
for (const entry of awaited) {
|
|
15018
14929
|
if (!entry)
|
|
@@ -15052,20 +14963,20 @@ var ReaddirpStream = class extends import_node_stream.Readable {
|
|
|
15052
14963
|
this.reading = false;
|
|
15053
14964
|
}
|
|
15054
14965
|
}
|
|
15055
|
-
async _exploreDir(
|
|
14966
|
+
async _exploreDir(path30, depth) {
|
|
15056
14967
|
let files;
|
|
15057
14968
|
try {
|
|
15058
|
-
files = await (0, import_promises.readdir)(
|
|
14969
|
+
files = await (0, import_promises.readdir)(path30, this._rdOptions);
|
|
15059
14970
|
} catch (error) {
|
|
15060
14971
|
this._onError(error);
|
|
15061
14972
|
}
|
|
15062
|
-
return { files, depth, path:
|
|
14973
|
+
return { files, depth, path: path30 };
|
|
15063
14974
|
}
|
|
15064
|
-
async _formatEntry(dirent,
|
|
14975
|
+
async _formatEntry(dirent, path30) {
|
|
15065
14976
|
let entry;
|
|
15066
14977
|
const basename9 = this._isDirent ? dirent.name : dirent;
|
|
15067
14978
|
try {
|
|
15068
|
-
const fullPath = (0, import_node_path.resolve)((0, import_node_path.join)(
|
|
14979
|
+
const fullPath = (0, import_node_path.resolve)((0, import_node_path.join)(path30, basename9));
|
|
15069
14980
|
entry = { path: (0, import_node_path.relative)(this._root, fullPath), fullPath, basename: basename9 };
|
|
15070
14981
|
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
15071
14982
|
} catch (err) {
|
|
@@ -15465,16 +15376,16 @@ var delFromSet = (main, prop, item) => {
|
|
|
15465
15376
|
};
|
|
15466
15377
|
var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
|
|
15467
15378
|
var FsWatchInstances = /* @__PURE__ */ new Map();
|
|
15468
|
-
function createFsWatchInstance(
|
|
15379
|
+
function createFsWatchInstance(path30, options, listener, errHandler, emitRaw) {
|
|
15469
15380
|
const handleEvent = (rawEvent, evPath) => {
|
|
15470
|
-
listener(
|
|
15471
|
-
emitRaw(rawEvent, evPath, { watchedPath:
|
|
15472
|
-
if (evPath &&
|
|
15473
|
-
fsWatchBroadcast(sp.resolve(
|
|
15381
|
+
listener(path30);
|
|
15382
|
+
emitRaw(rawEvent, evPath, { watchedPath: path30 });
|
|
15383
|
+
if (evPath && path30 !== evPath) {
|
|
15384
|
+
fsWatchBroadcast(sp.resolve(path30, evPath), KEY_LISTENERS, sp.join(path30, evPath));
|
|
15474
15385
|
}
|
|
15475
15386
|
};
|
|
15476
15387
|
try {
|
|
15477
|
-
return (0, import_node_fs.watch)(
|
|
15388
|
+
return (0, import_node_fs.watch)(path30, {
|
|
15478
15389
|
persistent: options.persistent
|
|
15479
15390
|
}, handleEvent);
|
|
15480
15391
|
} catch (error) {
|
|
@@ -15490,12 +15401,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
|
|
|
15490
15401
|
listener(val1, val2, val3);
|
|
15491
15402
|
});
|
|
15492
15403
|
};
|
|
15493
|
-
var setFsWatchListener = (
|
|
15404
|
+
var setFsWatchListener = (path30, fullPath, options, handlers) => {
|
|
15494
15405
|
const { listener, errHandler, rawEmitter } = handlers;
|
|
15495
15406
|
let cont = FsWatchInstances.get(fullPath);
|
|
15496
15407
|
let watcher;
|
|
15497
15408
|
if (!options.persistent) {
|
|
15498
|
-
watcher = createFsWatchInstance(
|
|
15409
|
+
watcher = createFsWatchInstance(path30, options, listener, errHandler, rawEmitter);
|
|
15499
15410
|
if (!watcher)
|
|
15500
15411
|
return;
|
|
15501
15412
|
return watcher.close.bind(watcher);
|
|
@@ -15506,7 +15417,7 @@ var setFsWatchListener = (path28, fullPath, options, handlers) => {
|
|
|
15506
15417
|
addAndConvert(cont, KEY_RAW, rawEmitter);
|
|
15507
15418
|
} else {
|
|
15508
15419
|
watcher = createFsWatchInstance(
|
|
15509
|
-
|
|
15420
|
+
path30,
|
|
15510
15421
|
options,
|
|
15511
15422
|
fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
|
|
15512
15423
|
errHandler,
|
|
@@ -15521,7 +15432,7 @@ var setFsWatchListener = (path28, fullPath, options, handlers) => {
|
|
|
15521
15432
|
cont.watcherUnusable = true;
|
|
15522
15433
|
if (isWindows && error.code === "EPERM") {
|
|
15523
15434
|
try {
|
|
15524
|
-
const fd = await (0, import_promises2.open)(
|
|
15435
|
+
const fd = await (0, import_promises2.open)(path30, "r");
|
|
15525
15436
|
await fd.close();
|
|
15526
15437
|
broadcastErr(error);
|
|
15527
15438
|
} catch (err) {
|
|
@@ -15552,7 +15463,7 @@ var setFsWatchListener = (path28, fullPath, options, handlers) => {
|
|
|
15552
15463
|
};
|
|
15553
15464
|
};
|
|
15554
15465
|
var FsWatchFileInstances = /* @__PURE__ */ new Map();
|
|
15555
|
-
var setFsWatchFileListener = (
|
|
15466
|
+
var setFsWatchFileListener = (path30, fullPath, options, handlers) => {
|
|
15556
15467
|
const { listener, rawEmitter } = handlers;
|
|
15557
15468
|
let cont = FsWatchFileInstances.get(fullPath);
|
|
15558
15469
|
const copts = cont && cont.options;
|
|
@@ -15574,7 +15485,7 @@ var setFsWatchFileListener = (path28, fullPath, options, handlers) => {
|
|
|
15574
15485
|
});
|
|
15575
15486
|
const currmtime = curr.mtimeMs;
|
|
15576
15487
|
if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
|
|
15577
|
-
foreach(cont.listeners, (listener2) => listener2(
|
|
15488
|
+
foreach(cont.listeners, (listener2) => listener2(path30, curr));
|
|
15578
15489
|
}
|
|
15579
15490
|
})
|
|
15580
15491
|
};
|
|
@@ -15604,13 +15515,13 @@ var NodeFsHandler = class {
|
|
|
15604
15515
|
* @param listener on fs change
|
|
15605
15516
|
* @returns closer for the watcher instance
|
|
15606
15517
|
*/
|
|
15607
|
-
_watchWithNodeFs(
|
|
15518
|
+
_watchWithNodeFs(path30, listener) {
|
|
15608
15519
|
const opts = this.fsw.options;
|
|
15609
|
-
const directory = sp.dirname(
|
|
15610
|
-
const basename9 = sp.basename(
|
|
15520
|
+
const directory = sp.dirname(path30);
|
|
15521
|
+
const basename9 = sp.basename(path30);
|
|
15611
15522
|
const parent = this.fsw._getWatchedDir(directory);
|
|
15612
15523
|
parent.add(basename9);
|
|
15613
|
-
const absolutePath = sp.resolve(
|
|
15524
|
+
const absolutePath = sp.resolve(path30);
|
|
15614
15525
|
const options = {
|
|
15615
15526
|
persistent: opts.persistent
|
|
15616
15527
|
};
|
|
@@ -15620,12 +15531,12 @@ var NodeFsHandler = class {
|
|
|
15620
15531
|
if (opts.usePolling) {
|
|
15621
15532
|
const enableBin = opts.interval !== opts.binaryInterval;
|
|
15622
15533
|
options.interval = enableBin && isBinaryPath(basename9) ? opts.binaryInterval : opts.interval;
|
|
15623
|
-
closer = setFsWatchFileListener(
|
|
15534
|
+
closer = setFsWatchFileListener(path30, absolutePath, options, {
|
|
15624
15535
|
listener,
|
|
15625
15536
|
rawEmitter: this.fsw._emitRaw
|
|
15626
15537
|
});
|
|
15627
15538
|
} else {
|
|
15628
|
-
closer = setFsWatchListener(
|
|
15539
|
+
closer = setFsWatchListener(path30, absolutePath, options, {
|
|
15629
15540
|
listener,
|
|
15630
15541
|
errHandler: this._boundHandleError,
|
|
15631
15542
|
rawEmitter: this.fsw._emitRaw
|
|
@@ -15647,7 +15558,7 @@ var NodeFsHandler = class {
|
|
|
15647
15558
|
let prevStats = stats;
|
|
15648
15559
|
if (parent.has(basename9))
|
|
15649
15560
|
return;
|
|
15650
|
-
const listener = async (
|
|
15561
|
+
const listener = async (path30, newStats) => {
|
|
15651
15562
|
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
|
|
15652
15563
|
return;
|
|
15653
15564
|
if (!newStats || newStats.mtimeMs === 0) {
|
|
@@ -15661,11 +15572,11 @@ var NodeFsHandler = class {
|
|
|
15661
15572
|
this.fsw._emit(EV.CHANGE, file, newStats2);
|
|
15662
15573
|
}
|
|
15663
15574
|
if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
|
|
15664
|
-
this.fsw._closeFile(
|
|
15575
|
+
this.fsw._closeFile(path30);
|
|
15665
15576
|
prevStats = newStats2;
|
|
15666
15577
|
const closer2 = this._watchWithNodeFs(file, listener);
|
|
15667
15578
|
if (closer2)
|
|
15668
|
-
this.fsw._addPathCloser(
|
|
15579
|
+
this.fsw._addPathCloser(path30, closer2);
|
|
15669
15580
|
} else {
|
|
15670
15581
|
prevStats = newStats2;
|
|
15671
15582
|
}
|
|
@@ -15697,7 +15608,7 @@ var NodeFsHandler = class {
|
|
|
15697
15608
|
* @param item basename of this item
|
|
15698
15609
|
* @returns true if no more processing is needed for this entry.
|
|
15699
15610
|
*/
|
|
15700
|
-
async _handleSymlink(entry, directory,
|
|
15611
|
+
async _handleSymlink(entry, directory, path30, item) {
|
|
15701
15612
|
if (this.fsw.closed) {
|
|
15702
15613
|
return;
|
|
15703
15614
|
}
|
|
@@ -15707,7 +15618,7 @@ var NodeFsHandler = class {
|
|
|
15707
15618
|
this.fsw._incrReadyCount();
|
|
15708
15619
|
let linkPath;
|
|
15709
15620
|
try {
|
|
15710
|
-
linkPath = await (0, import_promises2.realpath)(
|
|
15621
|
+
linkPath = await (0, import_promises2.realpath)(path30);
|
|
15711
15622
|
} catch (e) {
|
|
15712
15623
|
this.fsw._emitReady();
|
|
15713
15624
|
return true;
|
|
@@ -15717,12 +15628,12 @@ var NodeFsHandler = class {
|
|
|
15717
15628
|
if (dir.has(item)) {
|
|
15718
15629
|
if (this.fsw._symlinkPaths.get(full) !== linkPath) {
|
|
15719
15630
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
15720
|
-
this.fsw._emit(EV.CHANGE,
|
|
15631
|
+
this.fsw._emit(EV.CHANGE, path30, entry.stats);
|
|
15721
15632
|
}
|
|
15722
15633
|
} else {
|
|
15723
15634
|
dir.add(item);
|
|
15724
15635
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
15725
|
-
this.fsw._emit(EV.ADD,
|
|
15636
|
+
this.fsw._emit(EV.ADD, path30, entry.stats);
|
|
15726
15637
|
}
|
|
15727
15638
|
this.fsw._emitReady();
|
|
15728
15639
|
return true;
|
|
@@ -15752,9 +15663,9 @@ var NodeFsHandler = class {
|
|
|
15752
15663
|
return;
|
|
15753
15664
|
}
|
|
15754
15665
|
const item = entry.path;
|
|
15755
|
-
let
|
|
15666
|
+
let path30 = sp.join(directory, item);
|
|
15756
15667
|
current.add(item);
|
|
15757
|
-
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory,
|
|
15668
|
+
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path30, item)) {
|
|
15758
15669
|
return;
|
|
15759
15670
|
}
|
|
15760
15671
|
if (this.fsw.closed) {
|
|
@@ -15763,11 +15674,11 @@ var NodeFsHandler = class {
|
|
|
15763
15674
|
}
|
|
15764
15675
|
if (item === target || !target && !previous.has(item)) {
|
|
15765
15676
|
this.fsw._incrReadyCount();
|
|
15766
|
-
|
|
15767
|
-
this._addToNodeFs(
|
|
15677
|
+
path30 = sp.join(dir, sp.relative(dir, path30));
|
|
15678
|
+
this._addToNodeFs(path30, initialAdd, wh, depth + 1);
|
|
15768
15679
|
}
|
|
15769
15680
|
}).on(EV.ERROR, this._boundHandleError);
|
|
15770
|
-
return new Promise((
|
|
15681
|
+
return new Promise((resolve17, reject) => {
|
|
15771
15682
|
if (!stream)
|
|
15772
15683
|
return reject();
|
|
15773
15684
|
stream.once(STR_END, () => {
|
|
@@ -15776,7 +15687,7 @@ var NodeFsHandler = class {
|
|
|
15776
15687
|
return;
|
|
15777
15688
|
}
|
|
15778
15689
|
const wasThrottled = throttler ? throttler.clear() : false;
|
|
15779
|
-
|
|
15690
|
+
resolve17(void 0);
|
|
15780
15691
|
previous.getChildren().filter((item) => {
|
|
15781
15692
|
return item !== directory && !current.has(item);
|
|
15782
15693
|
}).forEach((item) => {
|
|
@@ -15833,13 +15744,13 @@ var NodeFsHandler = class {
|
|
|
15833
15744
|
* @param depth Child path actually targeted for watch
|
|
15834
15745
|
* @param target Child path actually targeted for watch
|
|
15835
15746
|
*/
|
|
15836
|
-
async _addToNodeFs(
|
|
15747
|
+
async _addToNodeFs(path30, initialAdd, priorWh, depth, target) {
|
|
15837
15748
|
const ready = this.fsw._emitReady;
|
|
15838
|
-
if (this.fsw._isIgnored(
|
|
15749
|
+
if (this.fsw._isIgnored(path30) || this.fsw.closed) {
|
|
15839
15750
|
ready();
|
|
15840
15751
|
return false;
|
|
15841
15752
|
}
|
|
15842
|
-
const wh = this.fsw._getWatchHelpers(
|
|
15753
|
+
const wh = this.fsw._getWatchHelpers(path30);
|
|
15843
15754
|
if (priorWh) {
|
|
15844
15755
|
wh.filterPath = (entry) => priorWh.filterPath(entry);
|
|
15845
15756
|
wh.filterDir = (entry) => priorWh.filterDir(entry);
|
|
@@ -15855,8 +15766,8 @@ var NodeFsHandler = class {
|
|
|
15855
15766
|
const follow = this.fsw.options.followSymlinks;
|
|
15856
15767
|
let closer;
|
|
15857
15768
|
if (stats.isDirectory()) {
|
|
15858
|
-
const absPath = sp.resolve(
|
|
15859
|
-
const targetPath = follow ? await (0, import_promises2.realpath)(
|
|
15769
|
+
const absPath = sp.resolve(path30);
|
|
15770
|
+
const targetPath = follow ? await (0, import_promises2.realpath)(path30) : path30;
|
|
15860
15771
|
if (this.fsw.closed)
|
|
15861
15772
|
return;
|
|
15862
15773
|
closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
|
|
@@ -15866,29 +15777,29 @@ var NodeFsHandler = class {
|
|
|
15866
15777
|
this.fsw._symlinkPaths.set(absPath, targetPath);
|
|
15867
15778
|
}
|
|
15868
15779
|
} else if (stats.isSymbolicLink()) {
|
|
15869
|
-
const targetPath = follow ? await (0, import_promises2.realpath)(
|
|
15780
|
+
const targetPath = follow ? await (0, import_promises2.realpath)(path30) : path30;
|
|
15870
15781
|
if (this.fsw.closed)
|
|
15871
15782
|
return;
|
|
15872
15783
|
const parent = sp.dirname(wh.watchPath);
|
|
15873
15784
|
this.fsw._getWatchedDir(parent).add(wh.watchPath);
|
|
15874
15785
|
this.fsw._emit(EV.ADD, wh.watchPath, stats);
|
|
15875
|
-
closer = await this._handleDir(parent, stats, initialAdd, depth,
|
|
15786
|
+
closer = await this._handleDir(parent, stats, initialAdd, depth, path30, wh, targetPath);
|
|
15876
15787
|
if (this.fsw.closed)
|
|
15877
15788
|
return;
|
|
15878
15789
|
if (targetPath !== void 0) {
|
|
15879
|
-
this.fsw._symlinkPaths.set(sp.resolve(
|
|
15790
|
+
this.fsw._symlinkPaths.set(sp.resolve(path30), targetPath);
|
|
15880
15791
|
}
|
|
15881
15792
|
} else {
|
|
15882
15793
|
closer = this._handleFile(wh.watchPath, stats, initialAdd);
|
|
15883
15794
|
}
|
|
15884
15795
|
ready();
|
|
15885
15796
|
if (closer)
|
|
15886
|
-
this.fsw._addPathCloser(
|
|
15797
|
+
this.fsw._addPathCloser(path30, closer);
|
|
15887
15798
|
return false;
|
|
15888
15799
|
} catch (error) {
|
|
15889
15800
|
if (this.fsw._handleError(error)) {
|
|
15890
15801
|
ready();
|
|
15891
|
-
return
|
|
15802
|
+
return path30;
|
|
15892
15803
|
}
|
|
15893
15804
|
}
|
|
15894
15805
|
}
|
|
@@ -15920,35 +15831,35 @@ function createPattern(matcher) {
|
|
|
15920
15831
|
if (matcher.path === string)
|
|
15921
15832
|
return true;
|
|
15922
15833
|
if (matcher.recursive) {
|
|
15923
|
-
const
|
|
15924
|
-
if (!
|
|
15834
|
+
const relative14 = sp2.relative(matcher.path, string);
|
|
15835
|
+
if (!relative14) {
|
|
15925
15836
|
return false;
|
|
15926
15837
|
}
|
|
15927
|
-
return !
|
|
15838
|
+
return !relative14.startsWith("..") && !sp2.isAbsolute(relative14);
|
|
15928
15839
|
}
|
|
15929
15840
|
return false;
|
|
15930
15841
|
};
|
|
15931
15842
|
}
|
|
15932
15843
|
return () => false;
|
|
15933
15844
|
}
|
|
15934
|
-
function normalizePath2(
|
|
15935
|
-
if (typeof
|
|
15845
|
+
function normalizePath2(path30) {
|
|
15846
|
+
if (typeof path30 !== "string")
|
|
15936
15847
|
throw new Error("string expected");
|
|
15937
|
-
|
|
15938
|
-
|
|
15848
|
+
path30 = sp2.normalize(path30);
|
|
15849
|
+
path30 = path30.replace(/\\/g, "/");
|
|
15939
15850
|
let prepend = false;
|
|
15940
|
-
if (
|
|
15851
|
+
if (path30.startsWith("//"))
|
|
15941
15852
|
prepend = true;
|
|
15942
|
-
|
|
15853
|
+
path30 = path30.replace(DOUBLE_SLASH_RE, "/");
|
|
15943
15854
|
if (prepend)
|
|
15944
|
-
|
|
15945
|
-
return
|
|
15855
|
+
path30 = "/" + path30;
|
|
15856
|
+
return path30;
|
|
15946
15857
|
}
|
|
15947
15858
|
function matchPatterns(patterns, testString, stats) {
|
|
15948
|
-
const
|
|
15859
|
+
const path30 = normalizePath2(testString);
|
|
15949
15860
|
for (let index = 0; index < patterns.length; index++) {
|
|
15950
15861
|
const pattern = patterns[index];
|
|
15951
|
-
if (pattern(
|
|
15862
|
+
if (pattern(path30, stats)) {
|
|
15952
15863
|
return true;
|
|
15953
15864
|
}
|
|
15954
15865
|
}
|
|
@@ -15986,19 +15897,19 @@ var toUnix = (string) => {
|
|
|
15986
15897
|
}
|
|
15987
15898
|
return str;
|
|
15988
15899
|
};
|
|
15989
|
-
var normalizePathToUnix = (
|
|
15990
|
-
var normalizeIgnored = (cwd = "") => (
|
|
15991
|
-
if (typeof
|
|
15992
|
-
return normalizePathToUnix(sp2.isAbsolute(
|
|
15900
|
+
var normalizePathToUnix = (path30) => toUnix(sp2.normalize(toUnix(path30)));
|
|
15901
|
+
var normalizeIgnored = (cwd = "") => (path30) => {
|
|
15902
|
+
if (typeof path30 === "string") {
|
|
15903
|
+
return normalizePathToUnix(sp2.isAbsolute(path30) ? path30 : sp2.join(cwd, path30));
|
|
15993
15904
|
} else {
|
|
15994
|
-
return
|
|
15905
|
+
return path30;
|
|
15995
15906
|
}
|
|
15996
15907
|
};
|
|
15997
|
-
var getAbsolutePath = (
|
|
15998
|
-
if (sp2.isAbsolute(
|
|
15999
|
-
return
|
|
15908
|
+
var getAbsolutePath = (path30, cwd) => {
|
|
15909
|
+
if (sp2.isAbsolute(path30)) {
|
|
15910
|
+
return path30;
|
|
16000
15911
|
}
|
|
16001
|
-
return sp2.join(cwd,
|
|
15912
|
+
return sp2.join(cwd, path30);
|
|
16002
15913
|
};
|
|
16003
15914
|
var EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
|
|
16004
15915
|
var DirEntry = class {
|
|
@@ -16063,10 +15974,10 @@ var WatchHelper = class {
|
|
|
16063
15974
|
dirParts;
|
|
16064
15975
|
followSymlinks;
|
|
16065
15976
|
statMethod;
|
|
16066
|
-
constructor(
|
|
15977
|
+
constructor(path30, follow, fsw) {
|
|
16067
15978
|
this.fsw = fsw;
|
|
16068
|
-
const watchPath =
|
|
16069
|
-
this.path =
|
|
15979
|
+
const watchPath = path30;
|
|
15980
|
+
this.path = path30 = path30.replace(REPLACER_RE, "");
|
|
16070
15981
|
this.watchPath = watchPath;
|
|
16071
15982
|
this.fullWatchPath = sp2.resolve(watchPath);
|
|
16072
15983
|
this.dirParts = [];
|
|
@@ -16206,20 +16117,20 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
16206
16117
|
this._closePromise = void 0;
|
|
16207
16118
|
let paths = unifyPaths(paths_);
|
|
16208
16119
|
if (cwd) {
|
|
16209
|
-
paths = paths.map((
|
|
16210
|
-
const absPath = getAbsolutePath(
|
|
16120
|
+
paths = paths.map((path30) => {
|
|
16121
|
+
const absPath = getAbsolutePath(path30, cwd);
|
|
16211
16122
|
return absPath;
|
|
16212
16123
|
});
|
|
16213
16124
|
}
|
|
16214
|
-
paths.forEach((
|
|
16215
|
-
this._removeIgnoredPath(
|
|
16125
|
+
paths.forEach((path30) => {
|
|
16126
|
+
this._removeIgnoredPath(path30);
|
|
16216
16127
|
});
|
|
16217
16128
|
this._userIgnored = void 0;
|
|
16218
16129
|
if (!this._readyCount)
|
|
16219
16130
|
this._readyCount = 0;
|
|
16220
16131
|
this._readyCount += paths.length;
|
|
16221
|
-
Promise.all(paths.map(async (
|
|
16222
|
-
const res = await this._nodeFsHandler._addToNodeFs(
|
|
16132
|
+
Promise.all(paths.map(async (path30) => {
|
|
16133
|
+
const res = await this._nodeFsHandler._addToNodeFs(path30, !_internal, void 0, 0, _origAdd);
|
|
16223
16134
|
if (res)
|
|
16224
16135
|
this._emitReady();
|
|
16225
16136
|
return res;
|
|
@@ -16241,17 +16152,17 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
16241
16152
|
return this;
|
|
16242
16153
|
const paths = unifyPaths(paths_);
|
|
16243
16154
|
const { cwd } = this.options;
|
|
16244
|
-
paths.forEach((
|
|
16245
|
-
if (!sp2.isAbsolute(
|
|
16155
|
+
paths.forEach((path30) => {
|
|
16156
|
+
if (!sp2.isAbsolute(path30) && !this._closers.has(path30)) {
|
|
16246
16157
|
if (cwd)
|
|
16247
|
-
|
|
16248
|
-
|
|
16158
|
+
path30 = sp2.join(cwd, path30);
|
|
16159
|
+
path30 = sp2.resolve(path30);
|
|
16249
16160
|
}
|
|
16250
|
-
this._closePath(
|
|
16251
|
-
this._addIgnoredPath(
|
|
16252
|
-
if (this._watched.has(
|
|
16161
|
+
this._closePath(path30);
|
|
16162
|
+
this._addIgnoredPath(path30);
|
|
16163
|
+
if (this._watched.has(path30)) {
|
|
16253
16164
|
this._addIgnoredPath({
|
|
16254
|
-
path:
|
|
16165
|
+
path: path30,
|
|
16255
16166
|
recursive: true
|
|
16256
16167
|
});
|
|
16257
16168
|
}
|
|
@@ -16315,38 +16226,38 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
16315
16226
|
* @param stats arguments to be passed with event
|
|
16316
16227
|
* @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
|
|
16317
16228
|
*/
|
|
16318
|
-
async _emit(event,
|
|
16229
|
+
async _emit(event, path30, stats) {
|
|
16319
16230
|
if (this.closed)
|
|
16320
16231
|
return;
|
|
16321
16232
|
const opts = this.options;
|
|
16322
16233
|
if (isWindows)
|
|
16323
|
-
|
|
16234
|
+
path30 = sp2.normalize(path30);
|
|
16324
16235
|
if (opts.cwd)
|
|
16325
|
-
|
|
16326
|
-
const args = [
|
|
16236
|
+
path30 = sp2.relative(opts.cwd, path30);
|
|
16237
|
+
const args = [path30];
|
|
16327
16238
|
if (stats != null)
|
|
16328
16239
|
args.push(stats);
|
|
16329
16240
|
const awf = opts.awaitWriteFinish;
|
|
16330
16241
|
let pw;
|
|
16331
|
-
if (awf && (pw = this._pendingWrites.get(
|
|
16242
|
+
if (awf && (pw = this._pendingWrites.get(path30))) {
|
|
16332
16243
|
pw.lastChange = /* @__PURE__ */ new Date();
|
|
16333
16244
|
return this;
|
|
16334
16245
|
}
|
|
16335
16246
|
if (opts.atomic) {
|
|
16336
16247
|
if (event === EVENTS.UNLINK) {
|
|
16337
|
-
this._pendingUnlinks.set(
|
|
16248
|
+
this._pendingUnlinks.set(path30, [event, ...args]);
|
|
16338
16249
|
setTimeout(() => {
|
|
16339
|
-
this._pendingUnlinks.forEach((entry,
|
|
16250
|
+
this._pendingUnlinks.forEach((entry, path31) => {
|
|
16340
16251
|
this.emit(...entry);
|
|
16341
16252
|
this.emit(EVENTS.ALL, ...entry);
|
|
16342
|
-
this._pendingUnlinks.delete(
|
|
16253
|
+
this._pendingUnlinks.delete(path31);
|
|
16343
16254
|
});
|
|
16344
16255
|
}, typeof opts.atomic === "number" ? opts.atomic : 100);
|
|
16345
16256
|
return this;
|
|
16346
16257
|
}
|
|
16347
|
-
if (event === EVENTS.ADD && this._pendingUnlinks.has(
|
|
16258
|
+
if (event === EVENTS.ADD && this._pendingUnlinks.has(path30)) {
|
|
16348
16259
|
event = EVENTS.CHANGE;
|
|
16349
|
-
this._pendingUnlinks.delete(
|
|
16260
|
+
this._pendingUnlinks.delete(path30);
|
|
16350
16261
|
}
|
|
16351
16262
|
}
|
|
16352
16263
|
if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
|
|
@@ -16364,16 +16275,16 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
16364
16275
|
this.emitWithAll(event, args);
|
|
16365
16276
|
}
|
|
16366
16277
|
};
|
|
16367
|
-
this._awaitWriteFinish(
|
|
16278
|
+
this._awaitWriteFinish(path30, awf.stabilityThreshold, event, awfEmit);
|
|
16368
16279
|
return this;
|
|
16369
16280
|
}
|
|
16370
16281
|
if (event === EVENTS.CHANGE) {
|
|
16371
|
-
const isThrottled = !this._throttle(EVENTS.CHANGE,
|
|
16282
|
+
const isThrottled = !this._throttle(EVENTS.CHANGE, path30, 50);
|
|
16372
16283
|
if (isThrottled)
|
|
16373
16284
|
return this;
|
|
16374
16285
|
}
|
|
16375
16286
|
if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
|
|
16376
|
-
const fullPath = opts.cwd ? sp2.join(opts.cwd,
|
|
16287
|
+
const fullPath = opts.cwd ? sp2.join(opts.cwd, path30) : path30;
|
|
16377
16288
|
let stats2;
|
|
16378
16289
|
try {
|
|
16379
16290
|
stats2 = await (0, import_promises3.stat)(fullPath);
|
|
@@ -16404,23 +16315,23 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
16404
16315
|
* @param timeout duration of time to suppress duplicate actions
|
|
16405
16316
|
* @returns tracking object or false if action should be suppressed
|
|
16406
16317
|
*/
|
|
16407
|
-
_throttle(actionType,
|
|
16318
|
+
_throttle(actionType, path30, timeout) {
|
|
16408
16319
|
if (!this._throttled.has(actionType)) {
|
|
16409
16320
|
this._throttled.set(actionType, /* @__PURE__ */ new Map());
|
|
16410
16321
|
}
|
|
16411
16322
|
const action = this._throttled.get(actionType);
|
|
16412
16323
|
if (!action)
|
|
16413
16324
|
throw new Error("invalid throttle");
|
|
16414
|
-
const actionPath = action.get(
|
|
16325
|
+
const actionPath = action.get(path30);
|
|
16415
16326
|
if (actionPath) {
|
|
16416
16327
|
actionPath.count++;
|
|
16417
16328
|
return false;
|
|
16418
16329
|
}
|
|
16419
16330
|
let timeoutObject;
|
|
16420
16331
|
const clear = () => {
|
|
16421
|
-
const item = action.get(
|
|
16332
|
+
const item = action.get(path30);
|
|
16422
16333
|
const count = item ? item.count : 0;
|
|
16423
|
-
action.delete(
|
|
16334
|
+
action.delete(path30);
|
|
16424
16335
|
clearTimeout(timeoutObject);
|
|
16425
16336
|
if (item)
|
|
16426
16337
|
clearTimeout(item.timeoutObject);
|
|
@@ -16428,7 +16339,7 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
16428
16339
|
};
|
|
16429
16340
|
timeoutObject = setTimeout(clear, timeout);
|
|
16430
16341
|
const thr = { timeoutObject, clear, count: 0 };
|
|
16431
|
-
action.set(
|
|
16342
|
+
action.set(path30, thr);
|
|
16432
16343
|
return thr;
|
|
16433
16344
|
}
|
|
16434
16345
|
_incrReadyCount() {
|
|
@@ -16442,44 +16353,44 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
16442
16353
|
* @param event
|
|
16443
16354
|
* @param awfEmit Callback to be called when ready for event to be emitted.
|
|
16444
16355
|
*/
|
|
16445
|
-
_awaitWriteFinish(
|
|
16356
|
+
_awaitWriteFinish(path30, threshold, event, awfEmit) {
|
|
16446
16357
|
const awf = this.options.awaitWriteFinish;
|
|
16447
16358
|
if (typeof awf !== "object")
|
|
16448
16359
|
return;
|
|
16449
16360
|
const pollInterval = awf.pollInterval;
|
|
16450
16361
|
let timeoutHandler;
|
|
16451
|
-
let fullPath =
|
|
16452
|
-
if (this.options.cwd && !sp2.isAbsolute(
|
|
16453
|
-
fullPath = sp2.join(this.options.cwd,
|
|
16362
|
+
let fullPath = path30;
|
|
16363
|
+
if (this.options.cwd && !sp2.isAbsolute(path30)) {
|
|
16364
|
+
fullPath = sp2.join(this.options.cwd, path30);
|
|
16454
16365
|
}
|
|
16455
16366
|
const now2 = /* @__PURE__ */ new Date();
|
|
16456
16367
|
const writes = this._pendingWrites;
|
|
16457
16368
|
function awaitWriteFinishFn(prevStat) {
|
|
16458
16369
|
(0, import_node_fs2.stat)(fullPath, (err, curStat) => {
|
|
16459
|
-
if (err || !writes.has(
|
|
16370
|
+
if (err || !writes.has(path30)) {
|
|
16460
16371
|
if (err && err.code !== "ENOENT")
|
|
16461
16372
|
awfEmit(err);
|
|
16462
16373
|
return;
|
|
16463
16374
|
}
|
|
16464
16375
|
const now3 = Number(/* @__PURE__ */ new Date());
|
|
16465
16376
|
if (prevStat && curStat.size !== prevStat.size) {
|
|
16466
|
-
writes.get(
|
|
16377
|
+
writes.get(path30).lastChange = now3;
|
|
16467
16378
|
}
|
|
16468
|
-
const pw = writes.get(
|
|
16379
|
+
const pw = writes.get(path30);
|
|
16469
16380
|
const df = now3 - pw.lastChange;
|
|
16470
16381
|
if (df >= threshold) {
|
|
16471
|
-
writes.delete(
|
|
16382
|
+
writes.delete(path30);
|
|
16472
16383
|
awfEmit(void 0, curStat);
|
|
16473
16384
|
} else {
|
|
16474
16385
|
timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
|
|
16475
16386
|
}
|
|
16476
16387
|
});
|
|
16477
16388
|
}
|
|
16478
|
-
if (!writes.has(
|
|
16479
|
-
writes.set(
|
|
16389
|
+
if (!writes.has(path30)) {
|
|
16390
|
+
writes.set(path30, {
|
|
16480
16391
|
lastChange: now2,
|
|
16481
16392
|
cancelWait: () => {
|
|
16482
|
-
writes.delete(
|
|
16393
|
+
writes.delete(path30);
|
|
16483
16394
|
clearTimeout(timeoutHandler);
|
|
16484
16395
|
return event;
|
|
16485
16396
|
}
|
|
@@ -16490,8 +16401,8 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
16490
16401
|
/**
|
|
16491
16402
|
* Determines whether user has asked to ignore this path.
|
|
16492
16403
|
*/
|
|
16493
|
-
_isIgnored(
|
|
16494
|
-
if (this.options.atomic && DOT_RE.test(
|
|
16404
|
+
_isIgnored(path30, stats) {
|
|
16405
|
+
if (this.options.atomic && DOT_RE.test(path30))
|
|
16495
16406
|
return true;
|
|
16496
16407
|
if (!this._userIgnored) {
|
|
16497
16408
|
const { cwd } = this.options;
|
|
@@ -16501,17 +16412,17 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
16501
16412
|
const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
|
|
16502
16413
|
this._userIgnored = anymatch(list, void 0);
|
|
16503
16414
|
}
|
|
16504
|
-
return this._userIgnored(
|
|
16415
|
+
return this._userIgnored(path30, stats);
|
|
16505
16416
|
}
|
|
16506
|
-
_isntIgnored(
|
|
16507
|
-
return !this._isIgnored(
|
|
16417
|
+
_isntIgnored(path30, stat5) {
|
|
16418
|
+
return !this._isIgnored(path30, stat5);
|
|
16508
16419
|
}
|
|
16509
16420
|
/**
|
|
16510
16421
|
* Provides a set of common helpers and properties relating to symlink handling.
|
|
16511
16422
|
* @param path file or directory pattern being watched
|
|
16512
16423
|
*/
|
|
16513
|
-
_getWatchHelpers(
|
|
16514
|
-
return new WatchHelper(
|
|
16424
|
+
_getWatchHelpers(path30) {
|
|
16425
|
+
return new WatchHelper(path30, this.options.followSymlinks, this);
|
|
16515
16426
|
}
|
|
16516
16427
|
// Directory helpers
|
|
16517
16428
|
// -----------------
|
|
@@ -16543,63 +16454,63 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
16543
16454
|
* @param item base path of item/directory
|
|
16544
16455
|
*/
|
|
16545
16456
|
_remove(directory, item, isDirectory) {
|
|
16546
|
-
const
|
|
16547
|
-
const fullPath = sp2.resolve(
|
|
16548
|
-
isDirectory = isDirectory != null ? isDirectory : this._watched.has(
|
|
16549
|
-
if (!this._throttle("remove",
|
|
16457
|
+
const path30 = sp2.join(directory, item);
|
|
16458
|
+
const fullPath = sp2.resolve(path30);
|
|
16459
|
+
isDirectory = isDirectory != null ? isDirectory : this._watched.has(path30) || this._watched.has(fullPath);
|
|
16460
|
+
if (!this._throttle("remove", path30, 100))
|
|
16550
16461
|
return;
|
|
16551
16462
|
if (!isDirectory && this._watched.size === 1) {
|
|
16552
16463
|
this.add(directory, item, true);
|
|
16553
16464
|
}
|
|
16554
|
-
const wp = this._getWatchedDir(
|
|
16465
|
+
const wp = this._getWatchedDir(path30);
|
|
16555
16466
|
const nestedDirectoryChildren = wp.getChildren();
|
|
16556
|
-
nestedDirectoryChildren.forEach((nested) => this._remove(
|
|
16467
|
+
nestedDirectoryChildren.forEach((nested) => this._remove(path30, nested));
|
|
16557
16468
|
const parent = this._getWatchedDir(directory);
|
|
16558
16469
|
const wasTracked = parent.has(item);
|
|
16559
16470
|
parent.remove(item);
|
|
16560
16471
|
if (this._symlinkPaths.has(fullPath)) {
|
|
16561
16472
|
this._symlinkPaths.delete(fullPath);
|
|
16562
16473
|
}
|
|
16563
|
-
let relPath =
|
|
16474
|
+
let relPath = path30;
|
|
16564
16475
|
if (this.options.cwd)
|
|
16565
|
-
relPath = sp2.relative(this.options.cwd,
|
|
16476
|
+
relPath = sp2.relative(this.options.cwd, path30);
|
|
16566
16477
|
if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
|
|
16567
16478
|
const event = this._pendingWrites.get(relPath).cancelWait();
|
|
16568
16479
|
if (event === EVENTS.ADD)
|
|
16569
16480
|
return;
|
|
16570
16481
|
}
|
|
16571
|
-
this._watched.delete(
|
|
16482
|
+
this._watched.delete(path30);
|
|
16572
16483
|
this._watched.delete(fullPath);
|
|
16573
16484
|
const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
|
|
16574
|
-
if (wasTracked && !this._isIgnored(
|
|
16575
|
-
this._emit(eventName,
|
|
16576
|
-
this._closePath(
|
|
16485
|
+
if (wasTracked && !this._isIgnored(path30))
|
|
16486
|
+
this._emit(eventName, path30);
|
|
16487
|
+
this._closePath(path30);
|
|
16577
16488
|
}
|
|
16578
16489
|
/**
|
|
16579
16490
|
* Closes all watchers for a path
|
|
16580
16491
|
*/
|
|
16581
|
-
_closePath(
|
|
16582
|
-
this._closeFile(
|
|
16583
|
-
const dir = sp2.dirname(
|
|
16584
|
-
this._getWatchedDir(dir).remove(sp2.basename(
|
|
16492
|
+
_closePath(path30) {
|
|
16493
|
+
this._closeFile(path30);
|
|
16494
|
+
const dir = sp2.dirname(path30);
|
|
16495
|
+
this._getWatchedDir(dir).remove(sp2.basename(path30));
|
|
16585
16496
|
}
|
|
16586
16497
|
/**
|
|
16587
16498
|
* Closes only file-specific watchers
|
|
16588
16499
|
*/
|
|
16589
|
-
_closeFile(
|
|
16590
|
-
const closers = this._closers.get(
|
|
16500
|
+
_closeFile(path30) {
|
|
16501
|
+
const closers = this._closers.get(path30);
|
|
16591
16502
|
if (!closers)
|
|
16592
16503
|
return;
|
|
16593
16504
|
closers.forEach((closer) => closer());
|
|
16594
|
-
this._closers.delete(
|
|
16505
|
+
this._closers.delete(path30);
|
|
16595
16506
|
}
|
|
16596
|
-
_addPathCloser(
|
|
16507
|
+
_addPathCloser(path30, closer) {
|
|
16597
16508
|
if (!closer)
|
|
16598
16509
|
return;
|
|
16599
|
-
let list = this._closers.get(
|
|
16510
|
+
let list = this._closers.get(path30);
|
|
16600
16511
|
if (!list) {
|
|
16601
16512
|
list = [];
|
|
16602
|
-
this._closers.set(
|
|
16513
|
+
this._closers.set(path30, list);
|
|
16603
16514
|
}
|
|
16604
16515
|
list.push(closer);
|
|
16605
16516
|
}
|
|
@@ -16629,12 +16540,291 @@ function watch(paths, options = {}) {
|
|
|
16629
16540
|
var chokidar_default = { watch, FSWatcher };
|
|
16630
16541
|
|
|
16631
16542
|
// src/watcher/file-watcher.ts
|
|
16543
|
+
var path23 = __toESM(require("path"), 1);
|
|
16544
|
+
|
|
16545
|
+
// src/watcher/native-recursive-watcher.ts
|
|
16546
|
+
var import_node_fs3 = require("fs");
|
|
16632
16547
|
var path21 = __toESM(require("path"), 1);
|
|
16548
|
+
var NativeRecursiveWatcher = class {
|
|
16549
|
+
constructor(root, onChange, options = {}) {
|
|
16550
|
+
this.root = root;
|
|
16551
|
+
this.onChange = onChange;
|
|
16552
|
+
this.watchFactory = options.watchFactory ?? this.defaultWatchFactory;
|
|
16553
|
+
this.onError = options.onError;
|
|
16554
|
+
}
|
|
16555
|
+
root;
|
|
16556
|
+
onChange;
|
|
16557
|
+
watcher = null;
|
|
16558
|
+
listenerToken = 0;
|
|
16559
|
+
watchFactory;
|
|
16560
|
+
onError;
|
|
16561
|
+
start() {
|
|
16562
|
+
if (this.watcher) return;
|
|
16563
|
+
const token = ++this.listenerToken;
|
|
16564
|
+
const listener = (_eventType, filename) => {
|
|
16565
|
+
if (this.watcher === null || this.listenerToken !== token) return;
|
|
16566
|
+
const absolutePath = this.toAbsolutePath(filename);
|
|
16567
|
+
const nextResult = this.onChange(absolutePath);
|
|
16568
|
+
if (nextResult instanceof Promise) {
|
|
16569
|
+
void nextResult.catch((error) => {
|
|
16570
|
+
console.error("[codebase-index] Error handling native watcher event:", error);
|
|
16571
|
+
});
|
|
16572
|
+
}
|
|
16573
|
+
};
|
|
16574
|
+
const watcher = this.watchFactory(this.root, listener, {
|
|
16575
|
+
persistent: true,
|
|
16576
|
+
recursive: true
|
|
16577
|
+
});
|
|
16578
|
+
watcher.on?.("error", (error) => {
|
|
16579
|
+
if (this.watcher === watcher && this.listenerToken === token) {
|
|
16580
|
+
this.onError?.(error);
|
|
16581
|
+
}
|
|
16582
|
+
});
|
|
16583
|
+
this.watcher = watcher;
|
|
16584
|
+
}
|
|
16585
|
+
async stop() {
|
|
16586
|
+
const watcher = this.watcher;
|
|
16587
|
+
this.watcher = null;
|
|
16588
|
+
this.listenerToken += 1;
|
|
16589
|
+
if (!watcher) return;
|
|
16590
|
+
await watcher.close();
|
|
16591
|
+
}
|
|
16592
|
+
toAbsolutePath(filename) {
|
|
16593
|
+
if (filename == null) return null;
|
|
16594
|
+
const normalizedFilename = typeof filename === "string" ? filename : filename.toString();
|
|
16595
|
+
const absolutePath = path21.resolve(this.root, normalizedFilename);
|
|
16596
|
+
const relativePath = path21.relative(this.root, absolutePath);
|
|
16597
|
+
const outsideRoot = relativePath === ".." || relativePath.startsWith(`..${path21.sep}`) || path21.isAbsolute(relativePath);
|
|
16598
|
+
return outsideRoot ? null : absolutePath;
|
|
16599
|
+
}
|
|
16600
|
+
defaultWatchFactory = (root, listener, options) => (0, import_node_fs3.watch)(root, options, listener);
|
|
16601
|
+
};
|
|
16602
|
+
|
|
16603
|
+
// src/watcher/snapshot.ts
|
|
16604
|
+
var fsPromises4 = __toESM(require("fs/promises"), 1);
|
|
16605
|
+
var path22 = __toESM(require("path"), 1);
|
|
16606
|
+
async function buildFileSnapshotScan(projectRoot, config, configPaths = []) {
|
|
16607
|
+
const normalizedProjectRoot = path22.resolve(projectRoot);
|
|
16608
|
+
const ignoreFilter = createIgnoreFilter(normalizedProjectRoot);
|
|
16609
|
+
const includePatterns = [...config.include, ...config.additionalInclude ?? []];
|
|
16610
|
+
const maxDepth = config.indexing?.maxDepth ?? -1;
|
|
16611
|
+
const snapshot = /* @__PURE__ */ new Map();
|
|
16612
|
+
const unreadablePrefixes = /* @__PURE__ */ new Set();
|
|
16613
|
+
const includeFile = async (filePath) => {
|
|
16614
|
+
const normalizedPath2 = path22.resolve(filePath);
|
|
16615
|
+
if (!shouldIncludeFile(normalizedPath2, normalizedProjectRoot, includePatterns, config.exclude, ignoreFilter)) return;
|
|
16616
|
+
const stat5 = await readStatIfFile(normalizedPath2, unreadablePrefixes);
|
|
16617
|
+
if (stat5) snapshot.set(normalizedPath2, { size: stat5.size, mtimeMs: stat5.mtimeMs });
|
|
16618
|
+
};
|
|
16619
|
+
const walk = async (directoryPath, depth) => {
|
|
16620
|
+
let entries;
|
|
16621
|
+
try {
|
|
16622
|
+
entries = await fsPromises4.readdir(directoryPath, { withFileTypes: true });
|
|
16623
|
+
} catch (error) {
|
|
16624
|
+
if (isMissingFsError(error)) return;
|
|
16625
|
+
if (isPermissionFsError(error)) {
|
|
16626
|
+
unreadablePrefixes.add(path22.resolve(directoryPath));
|
|
16627
|
+
return;
|
|
16628
|
+
}
|
|
16629
|
+
throw error;
|
|
16630
|
+
}
|
|
16631
|
+
for (const entry of entries) {
|
|
16632
|
+
const fullPath = path22.join(directoryPath, entry.name);
|
|
16633
|
+
const relativePath = path22.relative(normalizedProjectRoot, fullPath);
|
|
16634
|
+
if (entry.isDirectory()) {
|
|
16635
|
+
if (hasFilteredPathSegment(relativePath, path22.sep) || isRestrictedDirectory(relativePath, path22.sep)) continue;
|
|
16636
|
+
if (ignoreFilter.ignores(relativePath)) continue;
|
|
16637
|
+
if (maxDepth === -1 || depth < maxDepth) await walk(fullPath, depth + 1);
|
|
16638
|
+
} else if (entry.isFile()) {
|
|
16639
|
+
await includeFile(fullPath);
|
|
16640
|
+
}
|
|
16641
|
+
}
|
|
16642
|
+
};
|
|
16643
|
+
await walk(normalizedProjectRoot, 0);
|
|
16644
|
+
await includeExplicitConfigPaths(snapshot, unreadablePrefixes, configPaths);
|
|
16645
|
+
return { entries: snapshot, unreadablePrefixes };
|
|
16646
|
+
}
|
|
16647
|
+
async function buildFileSnapshotForPathScan(projectRoot, config, configPaths, targetPath) {
|
|
16648
|
+
const normalizedProjectRoot = path22.resolve(projectRoot);
|
|
16649
|
+
const normalizedTargetPath = path22.resolve(targetPath);
|
|
16650
|
+
if (!isWithinPath(normalizedProjectRoot, normalizedTargetPath)) {
|
|
16651
|
+
return { entries: /* @__PURE__ */ new Map(), unreadablePrefixes: /* @__PURE__ */ new Set() };
|
|
16652
|
+
}
|
|
16653
|
+
const ignoreFilter = createIgnoreFilter(normalizedProjectRoot);
|
|
16654
|
+
const includePatterns = [...config.include, ...config.additionalInclude ?? []];
|
|
16655
|
+
const maxDepth = config.indexing?.maxDepth ?? -1;
|
|
16656
|
+
const explicitConfigPaths = new Set(configPaths.map((configPath) => path22.resolve(configPath)));
|
|
16657
|
+
const snapshot = /* @__PURE__ */ new Map();
|
|
16658
|
+
const unreadablePrefixes = /* @__PURE__ */ new Set();
|
|
16659
|
+
const includeFile = async (filePath) => {
|
|
16660
|
+
const normalizedPath2 = path22.resolve(filePath);
|
|
16661
|
+
if (!explicitConfigPaths.has(normalizedPath2) && !shouldIncludeFile(
|
|
16662
|
+
normalizedPath2,
|
|
16663
|
+
normalizedProjectRoot,
|
|
16664
|
+
includePatterns,
|
|
16665
|
+
config.exclude,
|
|
16666
|
+
ignoreFilter
|
|
16667
|
+
)) return;
|
|
16668
|
+
const stat5 = await readStatIfFile(normalizedPath2, unreadablePrefixes);
|
|
16669
|
+
if (stat5) snapshot.set(normalizedPath2, { size: stat5.size, mtimeMs: stat5.mtimeMs });
|
|
16670
|
+
};
|
|
16671
|
+
const walk = async (directoryPath, depth) => {
|
|
16672
|
+
let entries;
|
|
16673
|
+
try {
|
|
16674
|
+
entries = await fsPromises4.readdir(directoryPath, { withFileTypes: true });
|
|
16675
|
+
} catch (error) {
|
|
16676
|
+
if (isMissingFsError(error)) return;
|
|
16677
|
+
if (isPermissionFsError(error)) {
|
|
16678
|
+
unreadablePrefixes.add(path22.resolve(directoryPath));
|
|
16679
|
+
return;
|
|
16680
|
+
}
|
|
16681
|
+
throw error;
|
|
16682
|
+
}
|
|
16683
|
+
for (const entry of entries) {
|
|
16684
|
+
const fullPath = path22.join(directoryPath, entry.name);
|
|
16685
|
+
const relativePath = path22.relative(normalizedProjectRoot, fullPath);
|
|
16686
|
+
if (entry.isDirectory()) {
|
|
16687
|
+
if (hasFilteredPathSegment(relativePath, path22.sep) || isRestrictedDirectory(relativePath, path22.sep)) continue;
|
|
16688
|
+
if (ignoreFilter.ignores(relativePath)) continue;
|
|
16689
|
+
if (maxDepth === -1 || depth < maxDepth) await walk(fullPath, depth + 1);
|
|
16690
|
+
} else if (entry.isFile()) {
|
|
16691
|
+
await includeFile(fullPath);
|
|
16692
|
+
}
|
|
16693
|
+
}
|
|
16694
|
+
};
|
|
16695
|
+
const targetStat = await readStatIfFile(normalizedTargetPath, unreadablePrefixes);
|
|
16696
|
+
if (targetStat) await includeFile(normalizedTargetPath);
|
|
16697
|
+
else await walk(normalizedTargetPath, 0);
|
|
16698
|
+
await includeExplicitConfigPathsInPath(snapshot, unreadablePrefixes, configPaths, normalizedTargetPath);
|
|
16699
|
+
return { entries: snapshot, unreadablePrefixes };
|
|
16700
|
+
}
|
|
16701
|
+
function completeFileSnapshot(previous, scan) {
|
|
16702
|
+
const completed = new Map(scan.entries);
|
|
16703
|
+
for (const unreadablePrefix of scan.unreadablePrefixes) {
|
|
16704
|
+
for (const [entryPath, entry] of previous) {
|
|
16705
|
+
if (isWithinPath(unreadablePrefix, entryPath) && !completed.has(entryPath)) completed.set(entryPath, entry);
|
|
16706
|
+
}
|
|
16707
|
+
}
|
|
16708
|
+
return completed;
|
|
16709
|
+
}
|
|
16710
|
+
async function includeExplicitConfigPaths(snapshot, unreadablePrefixes, configPaths) {
|
|
16711
|
+
for (const configPath of [...new Set(configPaths.map((value) => path22.resolve(value)))]) {
|
|
16712
|
+
if (snapshot.has(configPath)) continue;
|
|
16713
|
+
const stat5 = await readStatIfFile(configPath, unreadablePrefixes);
|
|
16714
|
+
if (stat5) snapshot.set(configPath, { size: stat5.size, mtimeMs: stat5.mtimeMs });
|
|
16715
|
+
}
|
|
16716
|
+
}
|
|
16717
|
+
async function includeExplicitConfigPathsInPath(snapshot, unreadablePrefixes, configPaths, targetPath) {
|
|
16718
|
+
await includeExplicitConfigPaths(
|
|
16719
|
+
snapshot,
|
|
16720
|
+
unreadablePrefixes,
|
|
16721
|
+
configPaths.filter((configPath) => isWithinPath(targetPath, path22.resolve(configPath)))
|
|
16722
|
+
);
|
|
16723
|
+
}
|
|
16724
|
+
function isWithinPath(parentPath, childPath) {
|
|
16725
|
+
const relativePath = path22.relative(parentPath, childPath);
|
|
16726
|
+
return relativePath === "" || !relativePath.startsWith(`..${path22.sep}`) && relativePath !== ".." && !path22.isAbsolute(relativePath);
|
|
16727
|
+
}
|
|
16728
|
+
async function readStatIfFile(filePath, unreadablePrefixes) {
|
|
16729
|
+
try {
|
|
16730
|
+
const stat5 = await fsPromises4.stat(filePath);
|
|
16731
|
+
return stat5.isFile() ? stat5 : null;
|
|
16732
|
+
} catch (error) {
|
|
16733
|
+
if (isMissingFsError(error)) return null;
|
|
16734
|
+
if (isPermissionFsError(error)) {
|
|
16735
|
+
unreadablePrefixes.add(path22.resolve(filePath));
|
|
16736
|
+
return null;
|
|
16737
|
+
}
|
|
16738
|
+
throw error;
|
|
16739
|
+
}
|
|
16740
|
+
}
|
|
16741
|
+
function isMissingFsError(error) {
|
|
16742
|
+
return error instanceof Error && ["ENOENT", "ENOTDIR"].includes(error.code ?? "");
|
|
16743
|
+
}
|
|
16744
|
+
function isPermissionFsError(error) {
|
|
16745
|
+
return error instanceof Error && ["EACCES", "EPERM"].includes(error.code ?? "");
|
|
16746
|
+
}
|
|
16747
|
+
var diffTypeOrder = { add: 0, change: 1, unlink: 2 };
|
|
16748
|
+
function diffFileSnapshots(previous, current, forcedChanges = /* @__PURE__ */ new Set()) {
|
|
16749
|
+
const changes = [];
|
|
16750
|
+
for (const [filePath, previousEntry] of previous) {
|
|
16751
|
+
const currentEntry = current.get(filePath);
|
|
16752
|
+
if (!currentEntry) changes.push({ type: "unlink", path: filePath });
|
|
16753
|
+
else if (forcedChanges.has(filePath) || currentEntry.size !== previousEntry.size || currentEntry.mtimeMs !== previousEntry.mtimeMs) {
|
|
16754
|
+
changes.push({ type: "change", path: filePath });
|
|
16755
|
+
}
|
|
16756
|
+
}
|
|
16757
|
+
for (const [filePath] of current) {
|
|
16758
|
+
if (!previous.has(filePath)) changes.push({ type: "add", path: filePath });
|
|
16759
|
+
}
|
|
16760
|
+
return changes.sort((left, right) => left.path.localeCompare(right.path) || diffTypeOrder[left.type] - diffTypeOrder[right.type]);
|
|
16761
|
+
}
|
|
16762
|
+
|
|
16763
|
+
// src/watcher/snapshot-reconciler.ts
|
|
16764
|
+
var FileSnapshotReconciler = class {
|
|
16765
|
+
constructor(projectRoot, config, configPaths) {
|
|
16766
|
+
this.projectRoot = projectRoot;
|
|
16767
|
+
this.config = config;
|
|
16768
|
+
this.configPaths = configPaths;
|
|
16769
|
+
}
|
|
16770
|
+
projectRoot;
|
|
16771
|
+
config;
|
|
16772
|
+
configPaths;
|
|
16773
|
+
snapshot = null;
|
|
16774
|
+
reconciliationTail = Promise.resolve();
|
|
16775
|
+
async initialize() {
|
|
16776
|
+
this.snapshot = (await buildFileSnapshotScan(this.projectRoot, this.config, this.configPaths)).entries;
|
|
16777
|
+
}
|
|
16778
|
+
async reconcile(invalidations = []) {
|
|
16779
|
+
if (this.snapshot === null) {
|
|
16780
|
+
throw new Error("FileSnapshotReconciler is not initialized. Call initialize() before reconcile().");
|
|
16781
|
+
}
|
|
16782
|
+
const reconciliation = this.reconciliationTail.then(async () => {
|
|
16783
|
+
const previousSnapshot = this.snapshot;
|
|
16784
|
+
if (previousSnapshot === null) {
|
|
16785
|
+
throw new Error("FileSnapshotReconciler is not initialized. Call initialize() before reconcile().");
|
|
16786
|
+
}
|
|
16787
|
+
const normalizedInvalidations = invalidations.map((invalidation) => typeof invalidation === "string" || invalidation === null ? { path: invalidation, forceChange: false } : { path: invalidation.path, forceChange: invalidation.forceChange === true });
|
|
16788
|
+
const scopedPaths = normalizedInvalidations.map((invalidation) => invalidation.path).filter((filePath) => filePath !== null);
|
|
16789
|
+
const scan = scopedPaths.length === 0 || scopedPaths.length !== normalizedInvalidations.length ? await buildFileSnapshotScan(this.projectRoot, this.config, this.configPaths) : await this.reconcilePaths(previousSnapshot, scopedPaths);
|
|
16790
|
+
const nextSnapshot = completeFileSnapshot(previousSnapshot, scan);
|
|
16791
|
+
const forcedChanges = new Set(normalizedInvalidations.filter((invalidation) => invalidation.path !== null && invalidation.forceChange).map((invalidation) => invalidation.path));
|
|
16792
|
+
const changes = diffFileSnapshots(previousSnapshot, nextSnapshot, forcedChanges);
|
|
16793
|
+
this.snapshot = nextSnapshot;
|
|
16794
|
+
return changes;
|
|
16795
|
+
});
|
|
16796
|
+
this.reconciliationTail = reconciliation.then(() => void 0, () => void 0);
|
|
16797
|
+
return reconciliation;
|
|
16798
|
+
}
|
|
16799
|
+
async reconcilePaths(previousSnapshot, invalidatedPaths) {
|
|
16800
|
+
const scopes = this.getScopes(invalidatedPaths);
|
|
16801
|
+
const entries = new Map(previousSnapshot);
|
|
16802
|
+
const unreadablePrefixes = /* @__PURE__ */ new Set();
|
|
16803
|
+
for (const scope of scopes) {
|
|
16804
|
+
for (const previousPath of entries.keys()) {
|
|
16805
|
+
if (isWithinPath(scope, previousPath)) entries.delete(previousPath);
|
|
16806
|
+
}
|
|
16807
|
+
const scopedScan = await buildFileSnapshotForPathScan(this.projectRoot, this.config, this.configPaths, scope);
|
|
16808
|
+
for (const [filePath, entry] of scopedScan.entries) entries.set(filePath, entry);
|
|
16809
|
+
for (const unreadablePrefix of scopedScan.unreadablePrefixes) unreadablePrefixes.add(unreadablePrefix);
|
|
16810
|
+
}
|
|
16811
|
+
return { entries, unreadablePrefixes };
|
|
16812
|
+
}
|
|
16813
|
+
getScopes(invalidatedPaths) {
|
|
16814
|
+
const uniquePaths = [...new Set(invalidatedPaths)].sort((left, right) => left.length - right.length);
|
|
16815
|
+
return uniquePaths.filter((candidate, index) => !uniquePaths.slice(0, index).some(
|
|
16816
|
+
(ancestor) => isWithinPath(ancestor, candidate)
|
|
16817
|
+
));
|
|
16818
|
+
}
|
|
16819
|
+
};
|
|
16820
|
+
|
|
16821
|
+
// src/watcher/file-watcher.ts
|
|
16633
16822
|
var FileWatcher = class {
|
|
16634
16823
|
watcher = null;
|
|
16635
16824
|
projectRoot;
|
|
16636
16825
|
config;
|
|
16637
16826
|
configPath;
|
|
16827
|
+
backend;
|
|
16638
16828
|
projectConfigPaths;
|
|
16639
16829
|
pendingChanges = /* @__PURE__ */ new Map();
|
|
16640
16830
|
debounceTimer = null;
|
|
@@ -16644,44 +16834,74 @@ var FileWatcher = class {
|
|
|
16644
16834
|
resolveReady = null;
|
|
16645
16835
|
pollingFallbackAttempted = false;
|
|
16646
16836
|
pendingClose = null;
|
|
16837
|
+
startupReadySignals = 1;
|
|
16838
|
+
nativeWatcher = null;
|
|
16839
|
+
nativeReconciler = null;
|
|
16840
|
+
nativeSetupGeneration = 0;
|
|
16841
|
+
nativeStarting = false;
|
|
16842
|
+
nativeInitializing = false;
|
|
16843
|
+
nativeReconcileTimer = null;
|
|
16844
|
+
nativeInvalidatedPaths = /* @__PURE__ */ new Map();
|
|
16845
|
+
configPathStates = /* @__PURE__ */ new Map();
|
|
16647
16846
|
constructor(projectRoot, config, host, options = {}) {
|
|
16648
16847
|
this.projectRoot = projectRoot;
|
|
16649
16848
|
this.config = config;
|
|
16849
|
+
this.backend = options.backend ?? "auto";
|
|
16650
16850
|
this.configPath = options.configPath;
|
|
16651
16851
|
this.projectConfigPaths = options.configPath ? [options.configPath] : getProjectConfigCandidatePaths(projectRoot, host);
|
|
16652
16852
|
}
|
|
16653
16853
|
start(handler) {
|
|
16654
|
-
if (this.watcher) {
|
|
16854
|
+
if (this.watcher || this.nativeWatcher || this.nativeStarting) {
|
|
16655
16855
|
return;
|
|
16656
16856
|
}
|
|
16657
16857
|
this.onChanges = handler;
|
|
16658
16858
|
this.pollingFallbackAttempted = false;
|
|
16659
16859
|
this.resetReady();
|
|
16860
|
+
if (this.shouldUseNativeWatcher()) {
|
|
16861
|
+
if (this.hasExternalConfigWatchTarget()) {
|
|
16862
|
+
this.setStartupReadySignals(2);
|
|
16863
|
+
this.startExternalConfigWatcher();
|
|
16864
|
+
}
|
|
16865
|
+
this.nativeStarting = true;
|
|
16866
|
+
void this.createNativeWatcher();
|
|
16867
|
+
return;
|
|
16868
|
+
}
|
|
16660
16869
|
this.createWatcher();
|
|
16661
16870
|
}
|
|
16662
16871
|
resetReady() {
|
|
16663
|
-
this.readyPromise = new Promise((
|
|
16664
|
-
this.resolveReady =
|
|
16872
|
+
this.readyPromise = new Promise((resolve17) => {
|
|
16873
|
+
this.resolveReady = resolve17;
|
|
16665
16874
|
});
|
|
16875
|
+
this.startupReadySignals = 1;
|
|
16666
16876
|
}
|
|
16667
|
-
|
|
16668
|
-
|
|
16669
|
-
|
|
16670
|
-
|
|
16671
|
-
|
|
16672
|
-
|
|
16673
|
-
|
|
16674
|
-
|
|
16675
|
-
|
|
16676
|
-
}).map((projectConfigPath) => (0, import_fs14.existsSync)(projectConfigPath) ? projectConfigPath : this.getNearestExistingDirectory(path21.dirname(projectConfigPath)));
|
|
16677
|
-
const uniqueExternalConfigTargets = [...new Set(externalConfigTargets)];
|
|
16678
|
-
if (uniqueExternalConfigTargets.length > 0) {
|
|
16679
|
-
watchTargets = [this.projectRoot, ...uniqueExternalConfigTargets];
|
|
16680
|
-
}
|
|
16877
|
+
setStartupReadySignals(expectedSignals) {
|
|
16878
|
+
if (!this.readyPromise) {
|
|
16879
|
+
return;
|
|
16880
|
+
}
|
|
16881
|
+
this.startupReadySignals = Math.max(0, expectedSignals);
|
|
16882
|
+
}
|
|
16883
|
+
reportStartupReadySignal() {
|
|
16884
|
+
if (!this.readyPromise || !this.resolveReady) {
|
|
16885
|
+
return;
|
|
16681
16886
|
}
|
|
16887
|
+
if (this.startupReadySignals <= 0) {
|
|
16888
|
+
return;
|
|
16889
|
+
}
|
|
16890
|
+
this.startupReadySignals -= 1;
|
|
16891
|
+
if (this.startupReadySignals !== 0) {
|
|
16892
|
+
return;
|
|
16893
|
+
}
|
|
16894
|
+
this.resolveReady();
|
|
16895
|
+
this.resolveReady = null;
|
|
16896
|
+
}
|
|
16897
|
+
createWatcher(watchTargets, usePolling = false, reportsStartupReady = true) {
|
|
16898
|
+
let reportedStartupReady = false;
|
|
16899
|
+
this.configPathStates = this.getConfigPathStates();
|
|
16900
|
+
const ignoreFilter = createIgnoreFilter(this.projectRoot);
|
|
16901
|
+
const resolvedWatchTargets = watchTargets ?? this.getFullChokidarWatchTargets();
|
|
16682
16902
|
const watcherOptions = {
|
|
16683
16903
|
ignored: (filePath) => {
|
|
16684
|
-
const relativePath =
|
|
16904
|
+
const relativePath = path23.relative(this.projectRoot, filePath);
|
|
16685
16905
|
if (!relativePath) return false;
|
|
16686
16906
|
if (this.isProjectConfigPathOrAncestor(relativePath)) {
|
|
16687
16907
|
return false;
|
|
@@ -16689,10 +16909,10 @@ var FileWatcher = class {
|
|
|
16689
16909
|
if (this.isOutsideProjectPath(relativePath)) {
|
|
16690
16910
|
return true;
|
|
16691
16911
|
}
|
|
16692
|
-
if (hasFilteredPathSegment(relativePath,
|
|
16912
|
+
if (hasFilteredPathSegment(relativePath, path23.sep)) {
|
|
16693
16913
|
return true;
|
|
16694
16914
|
}
|
|
16695
|
-
if (isRestrictedDirectory(relativePath,
|
|
16915
|
+
if (isRestrictedDirectory(relativePath, path23.sep)) {
|
|
16696
16916
|
return true;
|
|
16697
16917
|
}
|
|
16698
16918
|
if (ignoreFilter.ignores(relativePath)) {
|
|
@@ -16725,10 +16945,13 @@ var FileWatcher = class {
|
|
|
16725
16945
|
watcher = new FSWatcher(watcherOptions);
|
|
16726
16946
|
}
|
|
16727
16947
|
this.watcher = watcher;
|
|
16728
|
-
watcher.
|
|
16948
|
+
watcher.on("ready", () => {
|
|
16729
16949
|
if (this.watcher !== watcher) return;
|
|
16730
|
-
this.
|
|
16731
|
-
|
|
16950
|
+
this.reconcileConfigPathStates();
|
|
16951
|
+
if (reportsStartupReady) {
|
|
16952
|
+
this.reportStartupReadySignal();
|
|
16953
|
+
reportedStartupReady = true;
|
|
16954
|
+
}
|
|
16732
16955
|
});
|
|
16733
16956
|
watcher.on("error", (error) => {
|
|
16734
16957
|
const err = error instanceof Error ? error : null;
|
|
@@ -16742,10 +16965,13 @@ var FileWatcher = class {
|
|
|
16742
16965
|
console.error("[codebase-index] Failed to close exhausted file watcher:", closeError);
|
|
16743
16966
|
});
|
|
16744
16967
|
if (this.onChanges) {
|
|
16968
|
+
const replacementReportsStartupReady = reportsStartupReady || reportedStartupReady;
|
|
16745
16969
|
if (!this.resolveReady) {
|
|
16746
16970
|
this.resetReady();
|
|
16971
|
+
} else if (reportedStartupReady) {
|
|
16972
|
+
this.startupReadySignals += 1;
|
|
16747
16973
|
}
|
|
16748
|
-
this.createWatcher(true);
|
|
16974
|
+
this.createWatcher(resolvedWatchTargets, true, replacementReportsStartupReady);
|
|
16749
16975
|
} else {
|
|
16750
16976
|
this.watcher = null;
|
|
16751
16977
|
}
|
|
@@ -16756,13 +16982,166 @@ var FileWatcher = class {
|
|
|
16756
16982
|
watcher.on("add", (filePath) => this.handleChange(watcher, "add", filePath));
|
|
16757
16983
|
watcher.on("change", (filePath) => this.handleChange(watcher, "change", filePath));
|
|
16758
16984
|
watcher.on("unlink", (filePath) => this.handleChange(watcher, "unlink", filePath));
|
|
16759
|
-
watcher.add(
|
|
16985
|
+
watcher.add(resolvedWatchTargets);
|
|
16986
|
+
}
|
|
16987
|
+
shouldUseNativeWatcher() {
|
|
16988
|
+
if (this.backend === "chokidar") {
|
|
16989
|
+
return false;
|
|
16990
|
+
}
|
|
16991
|
+
return true;
|
|
16992
|
+
}
|
|
16993
|
+
getFullChokidarWatchTargets() {
|
|
16994
|
+
if (this.configPath) {
|
|
16995
|
+
return [this.projectRoot, this.configPath];
|
|
16996
|
+
}
|
|
16997
|
+
const externalConfigTargets = this.getExternalConfigWatchTargets();
|
|
16998
|
+
if (externalConfigTargets.length === 0) {
|
|
16999
|
+
return this.projectRoot;
|
|
17000
|
+
}
|
|
17001
|
+
return [this.projectRoot, ...externalConfigTargets];
|
|
17002
|
+
}
|
|
17003
|
+
getExternalConfigWatchTargets() {
|
|
17004
|
+
return [...new Set(
|
|
17005
|
+
this.projectConfigPaths.filter((projectConfigPath) => {
|
|
17006
|
+
const relativeConfigPath = path23.relative(this.projectRoot, projectConfigPath);
|
|
17007
|
+
return this.isOutsideProjectPath(relativeConfigPath);
|
|
17008
|
+
}).map((projectConfigPath) => {
|
|
17009
|
+
if ((0, import_fs14.existsSync)(projectConfigPath)) {
|
|
17010
|
+
return projectConfigPath;
|
|
17011
|
+
}
|
|
17012
|
+
return this.getNearestExistingDirectory(path23.dirname(projectConfigPath));
|
|
17013
|
+
})
|
|
17014
|
+
)];
|
|
17015
|
+
}
|
|
17016
|
+
hasExternalConfigWatchTarget() {
|
|
17017
|
+
return this.getExternalConfigWatchTargets().length > 0;
|
|
17018
|
+
}
|
|
17019
|
+
startExternalConfigWatcher(usePolling = false) {
|
|
17020
|
+
const externalTargets = this.getExternalConfigWatchTargets();
|
|
17021
|
+
if (externalTargets.length === 0) {
|
|
17022
|
+
return;
|
|
17023
|
+
}
|
|
17024
|
+
this.createWatcher(externalTargets, usePolling);
|
|
17025
|
+
}
|
|
17026
|
+
async createNativeWatcher() {
|
|
17027
|
+
const generation = ++this.nativeSetupGeneration;
|
|
17028
|
+
const reconciler = new FileSnapshotReconciler(this.projectRoot, this.config, this.projectConfigPaths);
|
|
17029
|
+
const watcher = new NativeRecursiveWatcher(
|
|
17030
|
+
this.projectRoot,
|
|
17031
|
+
(filePath) => this.scheduleNativeReconciliation(generation, filePath),
|
|
17032
|
+
{ onError: (error) => void this.fallbackFromNativeWatcher(generation, error) }
|
|
17033
|
+
);
|
|
17034
|
+
this.nativeReconciler = reconciler;
|
|
17035
|
+
this.nativeWatcher = watcher;
|
|
17036
|
+
this.nativeInitializing = true;
|
|
17037
|
+
try {
|
|
17038
|
+
watcher.start();
|
|
17039
|
+
if (!this.isCurrentNativeSetup(generation)) {
|
|
17040
|
+
await watcher.stop();
|
|
17041
|
+
return;
|
|
17042
|
+
}
|
|
17043
|
+
await reconciler.initialize();
|
|
17044
|
+
if (!this.isCurrentNativeSetup(generation) || this.nativeWatcher !== watcher) {
|
|
17045
|
+
await watcher.stop();
|
|
17046
|
+
return;
|
|
17047
|
+
}
|
|
17048
|
+
this.nativeStarting = false;
|
|
17049
|
+
this.nativeInitializing = false;
|
|
17050
|
+
await this.reconcileNativeWatcherWithPendingInvalidations(generation);
|
|
17051
|
+
this.reportStartupReadySignal();
|
|
17052
|
+
} catch (error) {
|
|
17053
|
+
if (!this.isCurrentNativeSetup(generation)) return;
|
|
17054
|
+
this.nativeInitializing = false;
|
|
17055
|
+
if (this.nativeWatcher) {
|
|
17056
|
+
await this.fallbackFromNativeWatcher(generation, error);
|
|
17057
|
+
return;
|
|
17058
|
+
}
|
|
17059
|
+
this.nativeStarting = false;
|
|
17060
|
+
const externalWatcher = this.watcher;
|
|
17061
|
+
this.watcher = null;
|
|
17062
|
+
this.nativeReconciler = null;
|
|
17063
|
+
await externalWatcher?.close();
|
|
17064
|
+
console.warn("[codebase-index] Native recursive watcher unavailable; using Chokidar fallback.", error);
|
|
17065
|
+
this.setStartupReadySignals(1);
|
|
17066
|
+
this.createWatcher();
|
|
17067
|
+
}
|
|
17068
|
+
}
|
|
17069
|
+
isCurrentNativeSetup(generation) {
|
|
17070
|
+
return this.nativeSetupGeneration === generation && this.onChanges !== null;
|
|
17071
|
+
}
|
|
17072
|
+
scheduleNativeReconciliation(generation, filePath) {
|
|
17073
|
+
if (!this.isCurrentNativeSetup(generation)) return;
|
|
17074
|
+
const requiresFullReconciliation = filePath === path23.join(this.projectRoot, ".gitignore");
|
|
17075
|
+
const invalidatedPath = requiresFullReconciliation ? null : filePath;
|
|
17076
|
+
this.nativeInvalidatedPaths.set(invalidatedPath, invalidatedPath !== null);
|
|
17077
|
+
if (this.nativeReconcileTimer) {
|
|
17078
|
+
clearTimeout(this.nativeReconcileTimer);
|
|
17079
|
+
}
|
|
17080
|
+
this.nativeReconcileTimer = setTimeout(() => {
|
|
17081
|
+
this.nativeReconcileTimer = null;
|
|
17082
|
+
void this.reconcileNativeWatcherFromQueue(generation);
|
|
17083
|
+
}, 100);
|
|
17084
|
+
}
|
|
17085
|
+
reconcileNativeWatcherFromQueue(generation) {
|
|
17086
|
+
if (!this.isCurrentNativeSetup(generation) || this.nativeInitializing) return;
|
|
17087
|
+
const invalidatedPaths = this.popNativeInvalidations();
|
|
17088
|
+
if (invalidatedPaths.length === 0) return;
|
|
17089
|
+
void this.reconcileNativeWatcher(generation, invalidatedPaths);
|
|
17090
|
+
}
|
|
17091
|
+
async reconcileNativeWatcher(generation, invalidatedPaths) {
|
|
17092
|
+
if (!this.isCurrentNativeSetup(generation) || !this.nativeReconciler) return;
|
|
17093
|
+
try {
|
|
17094
|
+
const reconciler = this.nativeReconciler;
|
|
17095
|
+
const changes = await reconciler.reconcile(invalidatedPaths);
|
|
17096
|
+
if (!this.isCurrentNativeSetup(generation) || this.nativeReconciler !== reconciler) return;
|
|
17097
|
+
this.recordChanges(changes);
|
|
17098
|
+
} catch (error) {
|
|
17099
|
+
await this.fallbackFromNativeWatcher(generation, error);
|
|
17100
|
+
}
|
|
17101
|
+
}
|
|
17102
|
+
async reconcileNativeWatcherWithPendingInvalidations(generation) {
|
|
17103
|
+
const invalidatedPaths = this.popNativeInvalidations();
|
|
17104
|
+
if (invalidatedPaths.length === 0) return;
|
|
17105
|
+
await this.reconcileNativeWatcher(generation, invalidatedPaths);
|
|
17106
|
+
}
|
|
17107
|
+
popNativeInvalidations() {
|
|
17108
|
+
if (this.nativeInvalidatedPaths.size === 0) return [];
|
|
17109
|
+
const invalidations = [...this.nativeInvalidatedPaths].map(([invalidatedPath, forceChange]) => ({
|
|
17110
|
+
path: invalidatedPath,
|
|
17111
|
+
forceChange
|
|
17112
|
+
}));
|
|
17113
|
+
this.nativeInvalidatedPaths.clear();
|
|
17114
|
+
return invalidations;
|
|
17115
|
+
}
|
|
17116
|
+
async fallbackFromNativeWatcher(generation, error) {
|
|
17117
|
+
if (!this.isCurrentNativeSetup(generation)) return;
|
|
17118
|
+
const watcher = this.nativeWatcher;
|
|
17119
|
+
const externalWatcher = this.watcher;
|
|
17120
|
+
this.nativeWatcher = null;
|
|
17121
|
+
this.watcher = null;
|
|
17122
|
+
this.nativeReconciler = null;
|
|
17123
|
+
this.nativeStarting = false;
|
|
17124
|
+
this.nativeInitializing = false;
|
|
17125
|
+
this.nativeSetupGeneration += 1;
|
|
17126
|
+
if (this.nativeReconcileTimer) {
|
|
17127
|
+
clearTimeout(this.nativeReconcileTimer);
|
|
17128
|
+
this.nativeReconcileTimer = null;
|
|
17129
|
+
}
|
|
17130
|
+
this.nativeInvalidatedPaths.clear();
|
|
17131
|
+
this.setStartupReadySignals(1);
|
|
17132
|
+
console.warn("[codebase-index] Native recursive watcher failed; using Chokidar fallback.", error);
|
|
17133
|
+
await watcher?.stop();
|
|
17134
|
+
await externalWatcher?.close();
|
|
17135
|
+
if (this.onChanges) {
|
|
17136
|
+
this.createWatcher();
|
|
17137
|
+
}
|
|
16760
17138
|
}
|
|
16761
17139
|
handleChange(watcher, type, filePath) {
|
|
16762
17140
|
if (this.watcher !== watcher) {
|
|
16763
17141
|
return;
|
|
16764
17142
|
}
|
|
16765
17143
|
if (this.isProjectConfigPath(filePath)) {
|
|
17144
|
+
this.updateConfigPathState(filePath);
|
|
16766
17145
|
this.pendingChanges.set(filePath, type);
|
|
16767
17146
|
this.scheduleFlush();
|
|
16768
17147
|
return;
|
|
@@ -16777,27 +17156,33 @@ var FileWatcher = class {
|
|
|
16777
17156
|
)) {
|
|
16778
17157
|
return;
|
|
16779
17158
|
}
|
|
16780
|
-
this.
|
|
17159
|
+
this.recordChanges([{ path: filePath, type }]);
|
|
17160
|
+
}
|
|
17161
|
+
recordChanges(changes) {
|
|
17162
|
+
if (changes.length === 0) return;
|
|
17163
|
+
for (const change of changes) {
|
|
17164
|
+
this.pendingChanges.set(change.path, change.type);
|
|
17165
|
+
}
|
|
16781
17166
|
this.scheduleFlush();
|
|
16782
17167
|
}
|
|
16783
17168
|
isProjectConfigPath(filePath) {
|
|
16784
|
-
const relativePath =
|
|
16785
|
-
const normalizedRelativePath =
|
|
17169
|
+
const relativePath = path23.relative(this.projectRoot, filePath);
|
|
17170
|
+
const normalizedRelativePath = path23.normalize(relativePath);
|
|
16786
17171
|
return this.getProjectConfigRelativePaths().some((configPath) => configPath === normalizedRelativePath);
|
|
16787
17172
|
}
|
|
16788
17173
|
isProjectConfigPathOrAncestor(relativePath) {
|
|
16789
|
-
const normalizedRelativePath =
|
|
17174
|
+
const normalizedRelativePath = path23.normalize(relativePath);
|
|
16790
17175
|
return this.getProjectConfigRelativePaths().some(
|
|
16791
|
-
(configPath) => configPath === normalizedRelativePath || configPath.startsWith(`${normalizedRelativePath}${
|
|
17176
|
+
(configPath) => configPath === normalizedRelativePath || configPath.startsWith(`${normalizedRelativePath}${path23.sep}`)
|
|
16792
17177
|
);
|
|
16793
17178
|
}
|
|
16794
17179
|
isOutsideProjectPath(relativePath) {
|
|
16795
|
-
return relativePath === ".." || relativePath.startsWith(`..${
|
|
17180
|
+
return relativePath === ".." || relativePath.startsWith(`..${path23.sep}`) || path23.isAbsolute(relativePath);
|
|
16796
17181
|
}
|
|
16797
17182
|
getNearestExistingDirectory(directoryPath) {
|
|
16798
17183
|
let candidate = directoryPath;
|
|
16799
17184
|
while (!(0, import_fs14.existsSync)(candidate)) {
|
|
16800
|
-
const parent =
|
|
17185
|
+
const parent = path23.dirname(candidate);
|
|
16801
17186
|
if (parent === candidate) break;
|
|
16802
17187
|
candidate = parent;
|
|
16803
17188
|
}
|
|
@@ -16805,9 +17190,51 @@ var FileWatcher = class {
|
|
|
16805
17190
|
}
|
|
16806
17191
|
getProjectConfigRelativePaths() {
|
|
16807
17192
|
return this.projectConfigPaths.map(
|
|
16808
|
-
(configPath) =>
|
|
17193
|
+
(configPath) => path23.normalize(path23.relative(this.projectRoot, configPath))
|
|
16809
17194
|
);
|
|
16810
17195
|
}
|
|
17196
|
+
getConfigPathStates() {
|
|
17197
|
+
const states = /* @__PURE__ */ new Map();
|
|
17198
|
+
for (const configPath of this.projectConfigPaths) {
|
|
17199
|
+
const state = this.getConfigPathState(configPath);
|
|
17200
|
+
if (state) states.set(configPath, state);
|
|
17201
|
+
}
|
|
17202
|
+
return states;
|
|
17203
|
+
}
|
|
17204
|
+
getConfigPathState(configPath) {
|
|
17205
|
+
try {
|
|
17206
|
+
const stats = (0, import_fs14.statSync)(configPath);
|
|
17207
|
+
return stats.isFile() ? { mtimeMs: stats.mtimeMs, size: stats.size } : void 0;
|
|
17208
|
+
} catch (error) {
|
|
17209
|
+
void error;
|
|
17210
|
+
return void 0;
|
|
17211
|
+
}
|
|
17212
|
+
}
|
|
17213
|
+
updateConfigPathState(configPath) {
|
|
17214
|
+
const state = this.getConfigPathState(configPath);
|
|
17215
|
+
if (state) {
|
|
17216
|
+
this.configPathStates.set(configPath, state);
|
|
17217
|
+
} else {
|
|
17218
|
+
this.configPathStates.delete(configPath);
|
|
17219
|
+
}
|
|
17220
|
+
}
|
|
17221
|
+
reconcileConfigPathStates() {
|
|
17222
|
+
const nextStates = this.getConfigPathStates();
|
|
17223
|
+
const changes = [];
|
|
17224
|
+
for (const configPath of this.projectConfigPaths) {
|
|
17225
|
+
const previous = this.configPathStates.get(configPath);
|
|
17226
|
+
const next = nextStates.get(configPath);
|
|
17227
|
+
if (!previous && next) {
|
|
17228
|
+
changes.push({ path: configPath, type: "add" });
|
|
17229
|
+
} else if (previous && !next) {
|
|
17230
|
+
changes.push({ path: configPath, type: "unlink" });
|
|
17231
|
+
} else if (previous && next && (previous.size !== next.size || previous.mtimeMs !== next.mtimeMs)) {
|
|
17232
|
+
changes.push({ path: configPath, type: "change" });
|
|
17233
|
+
}
|
|
17234
|
+
}
|
|
17235
|
+
this.configPathStates = nextStates;
|
|
17236
|
+
this.recordChanges(changes);
|
|
17237
|
+
}
|
|
16811
17238
|
scheduleFlush() {
|
|
16812
17239
|
if (this.debounceTimer) {
|
|
16813
17240
|
clearTimeout(this.debounceTimer);
|
|
@@ -16821,7 +17248,7 @@ var FileWatcher = class {
|
|
|
16821
17248
|
return;
|
|
16822
17249
|
}
|
|
16823
17250
|
const changes = Array.from(this.pendingChanges.entries()).map(
|
|
16824
|
-
([
|
|
17251
|
+
([path30, type]) => ({ path: path30, type })
|
|
16825
17252
|
);
|
|
16826
17253
|
this.pendingChanges.clear();
|
|
16827
17254
|
try {
|
|
@@ -16835,20 +17262,31 @@ var FileWatcher = class {
|
|
|
16835
17262
|
clearTimeout(this.debounceTimer);
|
|
16836
17263
|
this.debounceTimer = null;
|
|
16837
17264
|
}
|
|
17265
|
+
if (this.nativeReconcileTimer) {
|
|
17266
|
+
clearTimeout(this.nativeReconcileTimer);
|
|
17267
|
+
this.nativeReconcileTimer = null;
|
|
17268
|
+
}
|
|
17269
|
+
this.nativeInvalidatedPaths.clear();
|
|
16838
17270
|
const watcher = this.watcher;
|
|
17271
|
+
const nativeWatcher = this.nativeWatcher;
|
|
16839
17272
|
const pendingClose = this.pendingClose;
|
|
16840
17273
|
const resolveReady = this.resolveReady;
|
|
16841
17274
|
this.watcher = null;
|
|
17275
|
+
this.nativeWatcher = null;
|
|
17276
|
+
this.nativeReconciler = null;
|
|
17277
|
+
this.nativeStarting = false;
|
|
17278
|
+
this.nativeInitializing = false;
|
|
17279
|
+
this.nativeSetupGeneration += 1;
|
|
16842
17280
|
this.pendingClose = null;
|
|
16843
17281
|
this.resolveReady = null;
|
|
16844
17282
|
this.readyPromise = null;
|
|
16845
17283
|
this.pendingChanges.clear();
|
|
16846
17284
|
this.onChanges = null;
|
|
16847
|
-
await Promise.all([watcher?.close(), pendingClose]);
|
|
17285
|
+
await Promise.all([watcher?.close(), nativeWatcher?.stop(), pendingClose]);
|
|
16848
17286
|
resolveReady?.();
|
|
16849
17287
|
}
|
|
16850
17288
|
isRunning() {
|
|
16851
|
-
return this.watcher !== null;
|
|
17289
|
+
return this.watcher !== null || this.nativeWatcher !== null || this.nativeStarting;
|
|
16852
17290
|
}
|
|
16853
17291
|
async waitUntilReady() {
|
|
16854
17292
|
await (this.readyPromise ?? Promise.resolve());
|
|
@@ -16856,7 +17294,7 @@ var FileWatcher = class {
|
|
|
16856
17294
|
};
|
|
16857
17295
|
|
|
16858
17296
|
// src/watcher/git-head-watcher.ts
|
|
16859
|
-
var
|
|
17297
|
+
var path24 = __toESM(require("path"), 1);
|
|
16860
17298
|
var GitHeadWatcher = class {
|
|
16861
17299
|
watcher = null;
|
|
16862
17300
|
projectRoot;
|
|
@@ -16878,13 +17316,13 @@ var GitHeadWatcher = class {
|
|
|
16878
17316
|
this.readyPromise = Promise.resolve();
|
|
16879
17317
|
return;
|
|
16880
17318
|
}
|
|
16881
|
-
this.readyPromise = new Promise((
|
|
16882
|
-
this.resolveReady =
|
|
17319
|
+
this.readyPromise = new Promise((resolve17) => {
|
|
17320
|
+
this.resolveReady = resolve17;
|
|
16883
17321
|
});
|
|
16884
17322
|
this.onBranchChange = handler;
|
|
16885
17323
|
this.currentBranch = getCurrentBranch(this.projectRoot);
|
|
16886
17324
|
const headPath = getHeadPath(this.projectRoot);
|
|
16887
|
-
const refsPath =
|
|
17325
|
+
const refsPath = path24.join(this.projectRoot, ".git", "refs", "heads");
|
|
16888
17326
|
this.watcher = chokidar_default.watch([headPath, refsPath], {
|
|
16889
17327
|
persistent: true,
|
|
16890
17328
|
ignoreInitial: true,
|
|
@@ -17740,7 +18178,7 @@ async function resolveCodebaseContextUnmeasured(projectRoot, host, input) {
|
|
|
17740
18178
|
const directory = input.directory ?? void 0;
|
|
17741
18179
|
const tokenBudget = input.tokenBudget ?? void 0;
|
|
17742
18180
|
if (from && to) {
|
|
17743
|
-
const
|
|
18181
|
+
const path30 = await getCallGraphPath(
|
|
17744
18182
|
projectRoot,
|
|
17745
18183
|
host,
|
|
17746
18184
|
from,
|
|
@@ -17749,25 +18187,25 @@ async function resolveCodebaseContextUnmeasured(projectRoot, host, input) {
|
|
|
17749
18187
|
fromFilePath,
|
|
17750
18188
|
toFilePath
|
|
17751
18189
|
);
|
|
17752
|
-
const pathText = formatCallGraphPathResult(
|
|
17753
|
-
if (
|
|
18190
|
+
const pathText = formatCallGraphPathResult(path30);
|
|
18191
|
+
if (path30.path.length > 0) {
|
|
17754
18192
|
const fitted2 = fitTextToContextBudget(
|
|
17755
18193
|
pathText,
|
|
17756
18194
|
tokenBudget
|
|
17757
18195
|
);
|
|
17758
18196
|
return {
|
|
17759
18197
|
text: fitted2.text,
|
|
17760
|
-
details: fittedDetails("path", fitted2,
|
|
18198
|
+
details: fittedDetails("path", fitted2, path30.path.length)
|
|
17761
18199
|
};
|
|
17762
18200
|
}
|
|
17763
|
-
if (
|
|
18201
|
+
if (path30.from.status !== "resolved" || path30.to.status !== "resolved") {
|
|
17764
18202
|
const fitted2 = fitTextToContextBudget(pathText, tokenBudget);
|
|
17765
18203
|
return {
|
|
17766
18204
|
text: fitted2.text,
|
|
17767
18205
|
details: fittedDetails("path", fitted2, 0)
|
|
17768
18206
|
};
|
|
17769
18207
|
}
|
|
17770
|
-
const resolvedFrom =
|
|
18208
|
+
const resolvedFrom = path30.from;
|
|
17771
18209
|
const { callers } = await getCallGraphData(projectRoot, host, {
|
|
17772
18210
|
name: to,
|
|
17773
18211
|
direction: "callers",
|
|
@@ -17926,7 +18364,7 @@ async function executeCallGraph(projectRoot, host, args) {
|
|
|
17926
18364
|
return { text: formatCallGraphResult(await getCallGraphData(projectRoot, host, args)) };
|
|
17927
18365
|
}
|
|
17928
18366
|
async function executeCallGraphPath(projectRoot, host, args) {
|
|
17929
|
-
const
|
|
18367
|
+
const path30 = await getCallGraphPath(
|
|
17930
18368
|
projectRoot,
|
|
17931
18369
|
host,
|
|
17932
18370
|
args.from,
|
|
@@ -17935,7 +18373,7 @@ async function executeCallGraphPath(projectRoot, host, args) {
|
|
|
17935
18373
|
args.fromFilePath,
|
|
17936
18374
|
args.toFilePath
|
|
17937
18375
|
);
|
|
17938
|
-
return { text: formatCallGraphPathResult(
|
|
18376
|
+
return { text: formatCallGraphPathResult(path30) };
|
|
17939
18377
|
}
|
|
17940
18378
|
async function executeCodeCommunities(projectRoot, host, args) {
|
|
17941
18379
|
const result = await getCodeCommunities(projectRoot, host, args);
|
|
@@ -17945,11 +18383,11 @@ async function executeCodeCommunities(projectRoot, host, args) {
|
|
|
17945
18383
|
// src/adapters/opencode/tools.ts
|
|
17946
18384
|
var import_fs15 = require("fs");
|
|
17947
18385
|
var os7 = __toESM(require("os"), 1);
|
|
17948
|
-
var
|
|
18386
|
+
var path27 = __toESM(require("path"), 1);
|
|
17949
18387
|
|
|
17950
18388
|
// src/tools/visualize/activity.ts
|
|
17951
18389
|
var import_child_process5 = require("child_process");
|
|
17952
|
-
var
|
|
18390
|
+
var path25 = __toESM(require("path"), 1);
|
|
17953
18391
|
function attachRecentActivity(data, projectRoot) {
|
|
17954
18392
|
const activity = readGitActivity(projectRoot);
|
|
17955
18393
|
const changes = activity.size > 0 ? buildGitChanges(data, activity, projectRoot) : buildGraphChanges(data);
|
|
@@ -18111,7 +18549,7 @@ function normalizePath3(filePath) {
|
|
|
18111
18549
|
return filePath.replace(/\\/g, "/");
|
|
18112
18550
|
}
|
|
18113
18551
|
function toGitRelativePath(projectRoot, filePath) {
|
|
18114
|
-
const relativePath =
|
|
18552
|
+
const relativePath = path25.isAbsolute(filePath) ? path25.relative(projectRoot, filePath) : filePath;
|
|
18115
18553
|
return normalizePath3(relativePath);
|
|
18116
18554
|
}
|
|
18117
18555
|
|
|
@@ -18369,7 +18807,7 @@ render();
|
|
|
18369
18807
|
}
|
|
18370
18808
|
|
|
18371
18809
|
// src/tools/visualize/transform.ts
|
|
18372
|
-
var
|
|
18810
|
+
var path26 = __toESM(require("path"), 1);
|
|
18373
18811
|
|
|
18374
18812
|
// src/tools/visualize/modules.ts
|
|
18375
18813
|
var MAX_MODULES = 18;
|
|
@@ -18502,8 +18940,8 @@ function compactModules(prefixToNodes) {
|
|
|
18502
18940
|
function deriveModules(nodes) {
|
|
18503
18941
|
const initial = /* @__PURE__ */ new Map();
|
|
18504
18942
|
for (const node of nodes) {
|
|
18505
|
-
const
|
|
18506
|
-
const prefix = modulePrefixFromRelativePath(
|
|
18943
|
+
const relative14 = stripToProjectRelative(node.filePath);
|
|
18944
|
+
const prefix = modulePrefixFromRelativePath(relative14);
|
|
18507
18945
|
if (!initial.has(prefix)) initial.set(prefix, []);
|
|
18508
18946
|
initial.get(prefix)?.push(node);
|
|
18509
18947
|
}
|
|
@@ -18629,7 +19067,7 @@ function transformForVisualization(symbols, edges, options = {}) {
|
|
|
18629
19067
|
filePath: s.filePath,
|
|
18630
19068
|
kind: s.kind,
|
|
18631
19069
|
line: s.startLine,
|
|
18632
|
-
directory:
|
|
19070
|
+
directory: path26.dirname(s.filePath),
|
|
18633
19071
|
moduleId: "",
|
|
18634
19072
|
moduleLabel: ""
|
|
18635
19073
|
}));
|
|
@@ -18949,7 +19387,7 @@ var index_visualize = tool({
|
|
|
18949
19387
|
return "No connected symbols found for visualization. Try including orphans with includeOrphans=true, or check that the call graph has resolved edges.";
|
|
18950
19388
|
}
|
|
18951
19389
|
const html = generateVisualizationHtml(vizData);
|
|
18952
|
-
const outputPath =
|
|
19390
|
+
const outputPath = path27.join(os7.tmpdir(), `call-graph-${Date.now()}.html`);
|
|
18953
19391
|
(0, import_fs15.writeFileSync)(outputPath, html, "utf-8");
|
|
18954
19392
|
let result = `Temporal call graph visualization generated: ${outputPath}
|
|
18955
19393
|
|
|
@@ -19056,7 +19494,7 @@ var PI_TOOL_NAMES = [
|
|
|
19056
19494
|
|
|
19057
19495
|
// src/commands/loader.ts
|
|
19058
19496
|
var import_fs16 = require("fs");
|
|
19059
|
-
var
|
|
19497
|
+
var path28 = __toESM(require("path"), 1);
|
|
19060
19498
|
function parseFrontmatter(content) {
|
|
19061
19499
|
const frontmatterRegex = /^---\s*\n([\s\S]*?)\n---\s*\n([\s\S]*)$/;
|
|
19062
19500
|
const match = content.match(frontmatterRegex);
|
|
@@ -19082,7 +19520,7 @@ function loadCommandsFromDirectory(commandsDir) {
|
|
|
19082
19520
|
}
|
|
19083
19521
|
const files = (0, import_fs16.readdirSync)(commandsDir).filter((f) => f.endsWith(".md"));
|
|
19084
19522
|
for (const file of files) {
|
|
19085
|
-
const filePath =
|
|
19523
|
+
const filePath = path28.join(commandsDir, file);
|
|
19086
19524
|
let content;
|
|
19087
19525
|
try {
|
|
19088
19526
|
content = (0, import_fs16.readFileSync)(filePath, "utf-8");
|
|
@@ -19091,7 +19529,7 @@ function loadCommandsFromDirectory(commandsDir) {
|
|
|
19091
19529
|
throw new Error(`Failed to load command file ${filePath}: ${message}`);
|
|
19092
19530
|
}
|
|
19093
19531
|
const { frontmatter, body } = parseFrontmatter(content);
|
|
19094
|
-
const name =
|
|
19532
|
+
const name = path28.basename(file, ".md");
|
|
19095
19533
|
const description = frontmatter.description || `Run the ${name} command`;
|
|
19096
19534
|
commands.set(name, {
|
|
19097
19535
|
description,
|
|
@@ -19426,23 +19864,41 @@ var RoutingHintController = class {
|
|
|
19426
19864
|
// src/adapters/opencode.ts
|
|
19427
19865
|
var import_meta2 = {};
|
|
19428
19866
|
var activeWatchers = /* @__PURE__ */ new Map();
|
|
19429
|
-
|
|
19430
|
-
|
|
19431
|
-
|
|
19432
|
-
existing.
|
|
19433
|
-
|
|
19434
|
-
|
|
19435
|
-
|
|
19436
|
-
|
|
19867
|
+
var watcherReplacementChains = /* @__PURE__ */ new Map();
|
|
19868
|
+
async function replaceActiveWatcher(projectRoot, createNextWatcher) {
|
|
19869
|
+
const chain = (watcherReplacementChains.get(projectRoot) ?? Promise.resolve()).catch(() => void 0).then(async () => {
|
|
19870
|
+
const existing = activeWatchers.get(projectRoot);
|
|
19871
|
+
if (existing) {
|
|
19872
|
+
try {
|
|
19873
|
+
await existing.stop();
|
|
19874
|
+
} catch (error) {
|
|
19875
|
+
console.error("[codebase-index] Failed to stop replaced watcher:", error);
|
|
19876
|
+
throw error;
|
|
19877
|
+
}
|
|
19878
|
+
if (activeWatchers.get(projectRoot) === existing) {
|
|
19879
|
+
activeWatchers.delete(projectRoot);
|
|
19880
|
+
}
|
|
19881
|
+
}
|
|
19882
|
+
if (createNextWatcher) {
|
|
19883
|
+
activeWatchers.set(projectRoot, createNextWatcher());
|
|
19884
|
+
}
|
|
19885
|
+
});
|
|
19886
|
+
watcherReplacementChains.set(projectRoot, chain);
|
|
19887
|
+
try {
|
|
19888
|
+
await chain;
|
|
19889
|
+
} finally {
|
|
19890
|
+
if (watcherReplacementChains.get(projectRoot) === chain) {
|
|
19891
|
+
watcherReplacementChains.delete(projectRoot);
|
|
19892
|
+
}
|
|
19437
19893
|
}
|
|
19438
19894
|
}
|
|
19439
19895
|
function getCommandsDir() {
|
|
19440
19896
|
let currentDir = process.cwd();
|
|
19441
19897
|
if (typeof import_meta2 !== "undefined" && import_meta2.url) {
|
|
19442
|
-
currentDir =
|
|
19898
|
+
currentDir = path29.dirname((0, import_url.fileURLToPath)(import_meta2.url));
|
|
19443
19899
|
}
|
|
19444
|
-
const packageRoot =
|
|
19445
|
-
return
|
|
19900
|
+
const packageRoot = path29.basename(currentDir) === "adapters" ? path29.join(currentDir, "..", "..") : path29.join(currentDir, "..");
|
|
19901
|
+
return path29.join(packageRoot, "commands");
|
|
19446
19902
|
}
|
|
19447
19903
|
function appendRoutingHints(output, hints, preferredRole) {
|
|
19448
19904
|
const preferredBucket = preferredRole === "developer" ? output.developer : output.system;
|
|
@@ -19483,9 +19939,12 @@ var plugin = async ({ directory, worktree }) => {
|
|
|
19483
19939
|
startAutoIndex(projectRoot, "opencode", "startup");
|
|
19484
19940
|
}
|
|
19485
19941
|
if (config.indexing.watchFiles && isValidProject) {
|
|
19486
|
-
replaceActiveWatcher(
|
|
19942
|
+
await replaceActiveWatcher(
|
|
19943
|
+
projectRoot,
|
|
19944
|
+
() => createWatcherWithIndexer(getProjectIndexer, projectRoot, config, "opencode")
|
|
19945
|
+
);
|
|
19487
19946
|
} else {
|
|
19488
|
-
replaceActiveWatcher(projectRoot, null);
|
|
19947
|
+
await replaceActiveWatcher(projectRoot, null);
|
|
19489
19948
|
}
|
|
19490
19949
|
return {
|
|
19491
19950
|
tool: {
|