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.js
CHANGED
|
@@ -328,7 +328,7 @@ var require_ignore = __commonJS({
|
|
|
328
328
|
// path matching.
|
|
329
329
|
// - check `string` either `MODE_IGNORE` or `MODE_CHECK_IGNORE`
|
|
330
330
|
// @returns {TestResult} true if a file is ignored
|
|
331
|
-
test(
|
|
331
|
+
test(path30, checkUnignored, mode) {
|
|
332
332
|
let ignored = false;
|
|
333
333
|
let unignored = false;
|
|
334
334
|
let matchedRule;
|
|
@@ -337,7 +337,7 @@ var require_ignore = __commonJS({
|
|
|
337
337
|
if (unignored === negative && ignored !== unignored || negative && !ignored && !unignored && !checkUnignored) {
|
|
338
338
|
return;
|
|
339
339
|
}
|
|
340
|
-
const matched = rule[mode].test(
|
|
340
|
+
const matched = rule[mode].test(path30);
|
|
341
341
|
if (!matched) {
|
|
342
342
|
return;
|
|
343
343
|
}
|
|
@@ -358,17 +358,17 @@ var require_ignore = __commonJS({
|
|
|
358
358
|
var throwError = (message, Ctor) => {
|
|
359
359
|
throw new Ctor(message);
|
|
360
360
|
};
|
|
361
|
-
var checkPath = (
|
|
362
|
-
if (!isString(
|
|
361
|
+
var checkPath = (path30, originalPath, doThrow) => {
|
|
362
|
+
if (!isString(path30)) {
|
|
363
363
|
return doThrow(
|
|
364
364
|
`path must be a string, but got \`${originalPath}\``,
|
|
365
365
|
TypeError
|
|
366
366
|
);
|
|
367
367
|
}
|
|
368
|
-
if (!
|
|
368
|
+
if (!path30) {
|
|
369
369
|
return doThrow(`path must not be empty`, TypeError);
|
|
370
370
|
}
|
|
371
|
-
if (checkPath.isNotRelative(
|
|
371
|
+
if (checkPath.isNotRelative(path30)) {
|
|
372
372
|
const r = "`path.relative()`d";
|
|
373
373
|
return doThrow(
|
|
374
374
|
`path should be a ${r} string, but got "${originalPath}"`,
|
|
@@ -377,7 +377,7 @@ var require_ignore = __commonJS({
|
|
|
377
377
|
}
|
|
378
378
|
return true;
|
|
379
379
|
};
|
|
380
|
-
var isNotRelative = (
|
|
380
|
+
var isNotRelative = (path30) => REGEX_TEST_INVALID_PATH.test(path30);
|
|
381
381
|
checkPath.isNotRelative = isNotRelative;
|
|
382
382
|
checkPath.convert = (p) => p;
|
|
383
383
|
var Ignore2 = class {
|
|
@@ -407,19 +407,19 @@ var require_ignore = __commonJS({
|
|
|
407
407
|
}
|
|
408
408
|
// @returns {TestResult}
|
|
409
409
|
_test(originalPath, cache, checkUnignored, slices) {
|
|
410
|
-
const
|
|
410
|
+
const path30 = originalPath && checkPath.convert(originalPath);
|
|
411
411
|
checkPath(
|
|
412
|
-
|
|
412
|
+
path30,
|
|
413
413
|
originalPath,
|
|
414
414
|
this._strictPathCheck ? throwError : RETURN_FALSE
|
|
415
415
|
);
|
|
416
|
-
return this._t(
|
|
416
|
+
return this._t(path30, cache, checkUnignored, slices);
|
|
417
417
|
}
|
|
418
|
-
checkIgnore(
|
|
419
|
-
if (!REGEX_TEST_TRAILING_SLASH.test(
|
|
420
|
-
return this.test(
|
|
418
|
+
checkIgnore(path30) {
|
|
419
|
+
if (!REGEX_TEST_TRAILING_SLASH.test(path30)) {
|
|
420
|
+
return this.test(path30);
|
|
421
421
|
}
|
|
422
|
-
const slices =
|
|
422
|
+
const slices = path30.split(SLASH2).filter(Boolean);
|
|
423
423
|
slices.pop();
|
|
424
424
|
if (slices.length) {
|
|
425
425
|
const parent = this._t(
|
|
@@ -432,18 +432,18 @@ var require_ignore = __commonJS({
|
|
|
432
432
|
return parent;
|
|
433
433
|
}
|
|
434
434
|
}
|
|
435
|
-
return this._rules.test(
|
|
435
|
+
return this._rules.test(path30, false, MODE_CHECK_IGNORE);
|
|
436
436
|
}
|
|
437
|
-
_t(
|
|
438
|
-
if (
|
|
439
|
-
return cache[
|
|
437
|
+
_t(path30, cache, checkUnignored, slices) {
|
|
438
|
+
if (path30 in cache) {
|
|
439
|
+
return cache[path30];
|
|
440
440
|
}
|
|
441
441
|
if (!slices) {
|
|
442
|
-
slices =
|
|
442
|
+
slices = path30.split(SLASH2).filter(Boolean);
|
|
443
443
|
}
|
|
444
444
|
slices.pop();
|
|
445
445
|
if (!slices.length) {
|
|
446
|
-
return cache[
|
|
446
|
+
return cache[path30] = this._rules.test(path30, checkUnignored, MODE_IGNORE);
|
|
447
447
|
}
|
|
448
448
|
const parent = this._t(
|
|
449
449
|
slices.join(SLASH2) + SLASH2,
|
|
@@ -451,29 +451,29 @@ var require_ignore = __commonJS({
|
|
|
451
451
|
checkUnignored,
|
|
452
452
|
slices
|
|
453
453
|
);
|
|
454
|
-
return cache[
|
|
454
|
+
return cache[path30] = parent.ignored ? parent : this._rules.test(path30, checkUnignored, MODE_IGNORE);
|
|
455
455
|
}
|
|
456
|
-
ignores(
|
|
457
|
-
return this._test(
|
|
456
|
+
ignores(path30) {
|
|
457
|
+
return this._test(path30, this._ignoreCache, false).ignored;
|
|
458
458
|
}
|
|
459
459
|
createFilter() {
|
|
460
|
-
return (
|
|
460
|
+
return (path30) => !this.ignores(path30);
|
|
461
461
|
}
|
|
462
462
|
filter(paths) {
|
|
463
463
|
return makeArray(paths).filter(this.createFilter());
|
|
464
464
|
}
|
|
465
465
|
// @returns {TestResult}
|
|
466
|
-
test(
|
|
467
|
-
return this._test(
|
|
466
|
+
test(path30) {
|
|
467
|
+
return this._test(path30, this._testCache, true);
|
|
468
468
|
}
|
|
469
469
|
};
|
|
470
470
|
var factory = (options) => new Ignore2(options);
|
|
471
|
-
var isPathValid = (
|
|
471
|
+
var isPathValid = (path30) => checkPath(path30 && checkPath.convert(path30), path30, RETURN_FALSE);
|
|
472
472
|
var setupWindows = () => {
|
|
473
473
|
const makePosix = (str) => /^\\\\\?\\/.test(str) || /["<>|\u0000-\u001F]+/u.test(str) ? str : str.replace(/\\/g, "/");
|
|
474
474
|
checkPath.convert = makePosix;
|
|
475
475
|
const REGEX_TEST_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i;
|
|
476
|
-
checkPath.isNotRelative = (
|
|
476
|
+
checkPath.isNotRelative = (path30) => REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path30) || isNotRelative(path30);
|
|
477
477
|
};
|
|
478
478
|
if (
|
|
479
479
|
// Detect `process` so that it can run in browsers.
|
|
@@ -651,7 +651,7 @@ var require_eventemitter3 = __commonJS({
|
|
|
651
651
|
});
|
|
652
652
|
|
|
653
653
|
// src/adapters/opencode.ts
|
|
654
|
-
import * as
|
|
654
|
+
import * as path29 from "path";
|
|
655
655
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
656
656
|
|
|
657
657
|
// src/config/constants.ts
|
|
@@ -1129,11 +1129,11 @@ function resolveGitDir(repoRoot) {
|
|
|
1129
1129
|
return null;
|
|
1130
1130
|
}
|
|
1131
1131
|
try {
|
|
1132
|
-
const
|
|
1133
|
-
if (
|
|
1132
|
+
const stat5 = statSync2(gitPath);
|
|
1133
|
+
if (stat5.isDirectory()) {
|
|
1134
1134
|
return gitPath;
|
|
1135
1135
|
}
|
|
1136
|
-
if (
|
|
1136
|
+
if (stat5.isFile()) {
|
|
1137
1137
|
const content = readFileSync2(gitPath, "utf-8").trim();
|
|
1138
1138
|
const match = content.match(/^gitdir:\s*(.+)$/);
|
|
1139
1139
|
if (match) {
|
|
@@ -2202,7 +2202,7 @@ function analyzeQueryIntent(query) {
|
|
|
2202
2202
|
}
|
|
2203
2203
|
function isTestPath(filePath) {
|
|
2204
2204
|
const normalized = normalizePath(filePath);
|
|
2205
|
-
return /(?:^|\/)(?:test|tests|__tests__|spec|specs)(?:\/|$)/u.test(normalized) ||
|
|
2205
|
+
return /(?:^|\/)(?:test|tests|__tests__|spec|specs)(?:\/|$)/u.test(normalized) || /(?:\.(?:test|spec)|_(?:test|spec))\.[^/]+$/u.test(normalized) || /(?:^|\/)(?:test|spec)_[^/]+\.[^/]+$/u.test(normalized);
|
|
2206
2206
|
}
|
|
2207
2207
|
function isFixturePath(filePath) {
|
|
2208
2208
|
const normalized = normalizePath(filePath);
|
|
@@ -2577,8 +2577,8 @@ function formatExactSearchHandoff(results) {
|
|
|
2577
2577
|
}
|
|
2578
2578
|
function formatContextEvidence(result, index) {
|
|
2579
2579
|
const symbol = result.name ? ` ${JSON.stringify(compactEvidenceValue(result.name, 80))}` : "";
|
|
2580
|
-
const
|
|
2581
|
-
return `[${index}] ${result.chunkType}${symbol} in ${
|
|
2580
|
+
const path30 = compactEvidenceValue(result.filePath, 120);
|
|
2581
|
+
return `[${index}] ${result.chunkType}${symbol} in ${path30}:${result.startLine}-${result.endLine} (score ${result.score.toFixed(2)})`;
|
|
2582
2582
|
}
|
|
2583
2583
|
function formatContextPack(heading, selected, candidateCount, duplicateCount, limitOmittedCount, budgetOmittedCount, includeExactSearchHandoff) {
|
|
2584
2584
|
const lines = selected.map((result, index) => formatContextEvidence(result, index + 1));
|
|
@@ -3741,8 +3741,8 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
|
|
|
3741
3741
|
if (entry.isDirectory()) {
|
|
3742
3742
|
subdirs.push({ fullPath, relativePath });
|
|
3743
3743
|
} else if (entry.isFile()) {
|
|
3744
|
-
const
|
|
3745
|
-
if (
|
|
3744
|
+
const stat5 = await fsPromises.stat(fullPath);
|
|
3745
|
+
if (stat5.size > maxFileSize) {
|
|
3746
3746
|
skipped.push({ path: relativePath, reason: "too_large" });
|
|
3747
3747
|
continue;
|
|
3748
3748
|
}
|
|
@@ -3760,7 +3760,7 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
|
|
|
3760
3760
|
}
|
|
3761
3761
|
}
|
|
3762
3762
|
if (matched) {
|
|
3763
|
-
filesInDir.push({ path: fullPath, size:
|
|
3763
|
+
filesInDir.push({ path: fullPath, size: stat5.size });
|
|
3764
3764
|
}
|
|
3765
3765
|
}
|
|
3766
3766
|
}
|
|
@@ -3817,8 +3817,8 @@ async function collectFiles(projectRoot, includePatterns, excludePatterns, maxFi
|
|
|
3817
3817
|
}
|
|
3818
3818
|
for (const resolvedKbRoot of normalizedRoots) {
|
|
3819
3819
|
try {
|
|
3820
|
-
const
|
|
3821
|
-
if (!
|
|
3820
|
+
const stat5 = await fsPromises.stat(resolvedKbRoot);
|
|
3821
|
+
if (!stat5.isDirectory()) {
|
|
3822
3822
|
skipped.push({ path: resolvedKbRoot, reason: "excluded" });
|
|
3823
3823
|
continue;
|
|
3824
3824
|
}
|
|
@@ -3852,7 +3852,7 @@ function getErrorMessage(error) {
|
|
|
3852
3852
|
return error instanceof Error ? error.message : String(error);
|
|
3853
3853
|
}
|
|
3854
3854
|
function runCommand(file, args, options) {
|
|
3855
|
-
return new Promise((
|
|
3855
|
+
return new Promise((resolve17, reject) => {
|
|
3856
3856
|
childProcess.execFile(
|
|
3857
3857
|
file,
|
|
3858
3858
|
args,
|
|
@@ -3862,7 +3862,7 @@ function runCommand(file, args, options) {
|
|
|
3862
3862
|
reject(error);
|
|
3863
3863
|
return;
|
|
3864
3864
|
}
|
|
3865
|
-
|
|
3865
|
+
resolve17(stdout);
|
|
3866
3866
|
}
|
|
3867
3867
|
);
|
|
3868
3868
|
});
|
|
@@ -4007,10 +4007,10 @@ function safeFailureMessage(error) {
|
|
|
4007
4007
|
}
|
|
4008
4008
|
function cancellableDelay(delayMs, signal) {
|
|
4009
4009
|
if (signal.aborted) return Promise.reject(new AutoIndexCancelledError());
|
|
4010
|
-
return new Promise((
|
|
4010
|
+
return new Promise((resolve17, reject) => {
|
|
4011
4011
|
const timer = setTimeout(() => {
|
|
4012
4012
|
signal.removeEventListener("abort", onAbort);
|
|
4013
|
-
|
|
4013
|
+
resolve17();
|
|
4014
4014
|
}, delayMs);
|
|
4015
4015
|
timer.unref?.();
|
|
4016
4016
|
const onAbort = () => {
|
|
@@ -4022,15 +4022,15 @@ function cancellableDelay(delayMs, signal) {
|
|
|
4022
4022
|
}
|
|
4023
4023
|
function withTimeout(promise, timeoutMs) {
|
|
4024
4024
|
if (timeoutMs <= 0) return Promise.resolve(void 0);
|
|
4025
|
-
return new Promise((
|
|
4026
|
-
const timer = setTimeout(() =>
|
|
4025
|
+
return new Promise((resolve17) => {
|
|
4026
|
+
const timer = setTimeout(() => resolve17(void 0), timeoutMs);
|
|
4027
4027
|
timer.unref?.();
|
|
4028
4028
|
void promise.then((value) => {
|
|
4029
4029
|
clearTimeout(timer);
|
|
4030
|
-
|
|
4030
|
+
resolve17(value);
|
|
4031
4031
|
}, () => {
|
|
4032
4032
|
clearTimeout(timer);
|
|
4033
|
-
|
|
4033
|
+
resolve17(void 0);
|
|
4034
4034
|
});
|
|
4035
4035
|
});
|
|
4036
4036
|
}
|
|
@@ -4412,17 +4412,17 @@ var AutoIndexCoordinator = class {
|
|
|
4412
4412
|
}
|
|
4413
4413
|
}
|
|
4414
4414
|
waitForBatteryRetry(delayMs) {
|
|
4415
|
-
return new Promise((
|
|
4415
|
+
return new Promise((resolve17) => {
|
|
4416
4416
|
const timer = setTimeout(() => {
|
|
4417
4417
|
if (this.batteryRetryTimer === timer) {
|
|
4418
4418
|
this.batteryRetryTimer = null;
|
|
4419
4419
|
this.resolveBatteryRetry = null;
|
|
4420
4420
|
}
|
|
4421
|
-
|
|
4421
|
+
resolve17();
|
|
4422
4422
|
}, delayMs);
|
|
4423
4423
|
timer.unref?.();
|
|
4424
4424
|
this.batteryRetryTimer = timer;
|
|
4425
|
-
this.resolveBatteryRetry =
|
|
4425
|
+
this.resolveBatteryRetry = resolve17;
|
|
4426
4426
|
});
|
|
4427
4427
|
}
|
|
4428
4428
|
cancelBatteryRetry() {
|
|
@@ -4430,9 +4430,9 @@ var AutoIndexCoordinator = class {
|
|
|
4430
4430
|
clearTimeout(this.batteryRetryTimer);
|
|
4431
4431
|
this.batteryRetryTimer = null;
|
|
4432
4432
|
}
|
|
4433
|
-
const
|
|
4433
|
+
const resolve17 = this.resolveBatteryRetry;
|
|
4434
4434
|
this.resolveBatteryRetry = null;
|
|
4435
|
-
|
|
4435
|
+
resolve17?.();
|
|
4436
4436
|
}
|
|
4437
4437
|
finishBatteryCheck(batteryCheck) {
|
|
4438
4438
|
if (this.batteryCheck !== batteryCheck) return;
|
|
@@ -4637,7 +4637,7 @@ function pTimeout(promise, options) {
|
|
|
4637
4637
|
} = options;
|
|
4638
4638
|
let timer;
|
|
4639
4639
|
let abortHandler;
|
|
4640
|
-
const wrappedPromise = new Promise((
|
|
4640
|
+
const wrappedPromise = new Promise((resolve17, reject) => {
|
|
4641
4641
|
if (typeof milliseconds !== "number" || Math.sign(milliseconds) !== 1) {
|
|
4642
4642
|
throw new TypeError(`Expected \`milliseconds\` to be a positive number, got \`${milliseconds}\``);
|
|
4643
4643
|
}
|
|
@@ -4651,7 +4651,7 @@ function pTimeout(promise, options) {
|
|
|
4651
4651
|
};
|
|
4652
4652
|
signal.addEventListener("abort", abortHandler, { once: true });
|
|
4653
4653
|
}
|
|
4654
|
-
promise.then(
|
|
4654
|
+
promise.then(resolve17, reject);
|
|
4655
4655
|
if (milliseconds === Number.POSITIVE_INFINITY) {
|
|
4656
4656
|
return;
|
|
4657
4657
|
}
|
|
@@ -4659,7 +4659,7 @@ function pTimeout(promise, options) {
|
|
|
4659
4659
|
timer = customTimers.setTimeout.call(void 0, () => {
|
|
4660
4660
|
if (fallback) {
|
|
4661
4661
|
try {
|
|
4662
|
-
|
|
4662
|
+
resolve17(fallback());
|
|
4663
4663
|
} catch (error) {
|
|
4664
4664
|
reject(error);
|
|
4665
4665
|
}
|
|
@@ -4669,7 +4669,7 @@ function pTimeout(promise, options) {
|
|
|
4669
4669
|
promise.cancel();
|
|
4670
4670
|
}
|
|
4671
4671
|
if (message === false) {
|
|
4672
|
-
|
|
4672
|
+
resolve17();
|
|
4673
4673
|
} else if (message instanceof Error) {
|
|
4674
4674
|
reject(message);
|
|
4675
4675
|
} else {
|
|
@@ -5071,7 +5071,7 @@ var PQueue = class extends import_index.default {
|
|
|
5071
5071
|
// Assign unique ID if not provided
|
|
5072
5072
|
id: options.id ?? (this.#idAssigner++).toString()
|
|
5073
5073
|
};
|
|
5074
|
-
return new Promise((
|
|
5074
|
+
return new Promise((resolve17, reject) => {
|
|
5075
5075
|
const taskSymbol = /* @__PURE__ */ Symbol(`task-${options.id}`);
|
|
5076
5076
|
let cleanupQueueAbortHandler = () => void 0;
|
|
5077
5077
|
const run = async () => {
|
|
@@ -5111,7 +5111,7 @@ var PQueue = class extends import_index.default {
|
|
|
5111
5111
|
})]);
|
|
5112
5112
|
}
|
|
5113
5113
|
const result = await operation;
|
|
5114
|
-
|
|
5114
|
+
resolve17(result);
|
|
5115
5115
|
this.emit("completed", result);
|
|
5116
5116
|
} catch (error) {
|
|
5117
5117
|
reject(error);
|
|
@@ -5299,13 +5299,13 @@ var PQueue = class extends import_index.default {
|
|
|
5299
5299
|
});
|
|
5300
5300
|
}
|
|
5301
5301
|
async #onEvent(event, filter) {
|
|
5302
|
-
return new Promise((
|
|
5302
|
+
return new Promise((resolve17) => {
|
|
5303
5303
|
const listener = () => {
|
|
5304
5304
|
if (filter && !filter()) {
|
|
5305
5305
|
return;
|
|
5306
5306
|
}
|
|
5307
5307
|
this.off(event, listener);
|
|
5308
|
-
|
|
5308
|
+
resolve17();
|
|
5309
5309
|
};
|
|
5310
5310
|
this.on(event, listener);
|
|
5311
5311
|
});
|
|
@@ -5591,7 +5591,7 @@ async function onAttemptFailure({ error, attemptNumber, retriesConsumed, startTi
|
|
|
5591
5591
|
const finalDelay = Math.min(delayTime, remainingTime);
|
|
5592
5592
|
options.signal?.throwIfAborted();
|
|
5593
5593
|
if (finalDelay > 0) {
|
|
5594
|
-
await new Promise((
|
|
5594
|
+
await new Promise((resolve17, reject) => {
|
|
5595
5595
|
const onAbort = () => {
|
|
5596
5596
|
clearTimeout(timeoutToken);
|
|
5597
5597
|
options.signal?.removeEventListener("abort", onAbort);
|
|
@@ -5599,7 +5599,7 @@ async function onAttemptFailure({ error, attemptNumber, retriesConsumed, startTi
|
|
|
5599
5599
|
};
|
|
5600
5600
|
const timeoutToken = setTimeout(() => {
|
|
5601
5601
|
options.signal?.removeEventListener("abort", onAbort);
|
|
5602
|
-
|
|
5602
|
+
resolve17();
|
|
5603
5603
|
}, finalDelay);
|
|
5604
5604
|
if (options.unref) {
|
|
5605
5605
|
timeoutToken.unref?.();
|
|
@@ -6405,85 +6405,6 @@ function createEmbeddingProvider(configuredProviderInfo) {
|
|
|
6405
6405
|
}
|
|
6406
6406
|
}
|
|
6407
6407
|
|
|
6408
|
-
// src/rerank/index.ts
|
|
6409
|
-
function createReranker(config) {
|
|
6410
|
-
if (!config.enabled) {
|
|
6411
|
-
return new NoOpReranker();
|
|
6412
|
-
}
|
|
6413
|
-
return new SiliconFlowReranker(config);
|
|
6414
|
-
}
|
|
6415
|
-
var NoOpReranker = class {
|
|
6416
|
-
isAvailable() {
|
|
6417
|
-
return false;
|
|
6418
|
-
}
|
|
6419
|
-
async rerank(_query, documents, _topN) {
|
|
6420
|
-
return {
|
|
6421
|
-
results: documents.map((_, index) => ({ index, relevanceScore: 0 }))
|
|
6422
|
-
};
|
|
6423
|
-
}
|
|
6424
|
-
};
|
|
6425
|
-
var SiliconFlowReranker = class {
|
|
6426
|
-
config;
|
|
6427
|
-
constructor(config) {
|
|
6428
|
-
this.config = config;
|
|
6429
|
-
}
|
|
6430
|
-
isAvailable() {
|
|
6431
|
-
return this.config.enabled && !!this.config.baseUrl && !!this.config.model;
|
|
6432
|
-
}
|
|
6433
|
-
async rerank(query, documents, topN) {
|
|
6434
|
-
if (documents.length === 0) {
|
|
6435
|
-
return { results: [] };
|
|
6436
|
-
}
|
|
6437
|
-
const headers = {
|
|
6438
|
-
"Content-Type": "application/json"
|
|
6439
|
-
};
|
|
6440
|
-
if (this.config.apiKey) {
|
|
6441
|
-
headers["Authorization"] = `Bearer ${this.config.apiKey}`;
|
|
6442
|
-
}
|
|
6443
|
-
const baseUrl = this.config.baseUrl;
|
|
6444
|
-
if (!baseUrl) {
|
|
6445
|
-
throw new Error("Reranker baseUrl is required. Configure reranker.baseUrl in your codebase-index.json.");
|
|
6446
|
-
}
|
|
6447
|
-
const timeoutMs = this.config.timeoutMs ?? 3e4;
|
|
6448
|
-
const controller = new AbortController();
|
|
6449
|
-
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
6450
|
-
try {
|
|
6451
|
-
const response = await fetch(`${baseUrl}/rerank`, {
|
|
6452
|
-
method: "POST",
|
|
6453
|
-
headers,
|
|
6454
|
-
body: JSON.stringify({
|
|
6455
|
-
model: this.config.model,
|
|
6456
|
-
query,
|
|
6457
|
-
documents,
|
|
6458
|
-
top_n: topN ?? this.config.topN ?? 20,
|
|
6459
|
-
return_documents: false
|
|
6460
|
-
}),
|
|
6461
|
-
signal: controller.signal
|
|
6462
|
-
});
|
|
6463
|
-
clearTimeout(timeout);
|
|
6464
|
-
if (!response.ok) {
|
|
6465
|
-
const errorText = await response.text();
|
|
6466
|
-
throw new Error(`Rerank API error: ${response.status} - ${errorText}`);
|
|
6467
|
-
}
|
|
6468
|
-
const data = await response.json();
|
|
6469
|
-
return {
|
|
6470
|
-
results: data.results.map((r) => ({
|
|
6471
|
-
index: r.index,
|
|
6472
|
-
relevanceScore: r.relevance_score,
|
|
6473
|
-
document: r.document?.text
|
|
6474
|
-
})),
|
|
6475
|
-
tokensUsed: data.meta?.tokens?.input_tokens
|
|
6476
|
-
};
|
|
6477
|
-
} catch (error) {
|
|
6478
|
-
clearTimeout(timeout);
|
|
6479
|
-
if (error instanceof Error && error.name === "AbortError") {
|
|
6480
|
-
throw new Error(`Rerank API request timed out after ${timeoutMs}ms`);
|
|
6481
|
-
}
|
|
6482
|
-
throw error;
|
|
6483
|
-
}
|
|
6484
|
-
}
|
|
6485
|
-
};
|
|
6486
|
-
|
|
6487
6408
|
// src/utils/cost.ts
|
|
6488
6409
|
function estimateChunksFromFiles(files) {
|
|
6489
6410
|
let totalChunks = 0;
|
|
@@ -8043,8 +7964,8 @@ async function isWorktreeRegistered(projectRoot, worktreePath) {
|
|
|
8043
7964
|
return false;
|
|
8044
7965
|
}
|
|
8045
7966
|
function isPathWithinRoot(filePath, rootPath) {
|
|
8046
|
-
const
|
|
8047
|
-
return
|
|
7967
|
+
const relative14 = path15.relative(path15.resolve(rootPath), path15.resolve(filePath));
|
|
7968
|
+
return relative14 === "" || !relative14.startsWith(`..${path15.sep}`) && relative14 !== ".." && !path15.isAbsolute(relative14);
|
|
8048
7969
|
}
|
|
8049
7970
|
async function pruneExactMissingWorktreeRegistration(projectRoot, worktreePath) {
|
|
8050
7971
|
if (await pathExists(worktreePath)) return false;
|
|
@@ -8421,11 +8342,11 @@ function normalizeFiles(rawFiles, projectRoot) {
|
|
|
8421
8342
|
for (const raw of rawFiles) {
|
|
8422
8343
|
if (raw.length === 0) continue;
|
|
8423
8344
|
const absolute = path16.resolve(root, raw);
|
|
8424
|
-
const
|
|
8425
|
-
if (path16.isAbsolute(raw) ||
|
|
8345
|
+
const relative14 = path16.relative(root, absolute);
|
|
8346
|
+
if (path16.isAbsolute(raw) || relative14 === ".." || relative14.startsWith(`..${path16.sep}`) || path16.isAbsolute(relative14)) {
|
|
8426
8347
|
throw new Error(`Changed file escapes the project root: ${JSON.stringify(raw)}`);
|
|
8427
8348
|
}
|
|
8428
|
-
const cleaned =
|
|
8349
|
+
const cleaned = relative14.startsWith(`.${path16.sep}`) ? relative14.slice(2) : relative14;
|
|
8429
8350
|
if (!seen.has(cleaned)) {
|
|
8430
8351
|
seen.add(cleaned);
|
|
8431
8352
|
result.push(cleaned);
|
|
@@ -8657,7 +8578,8 @@ function rankHybridResults(query, semanticResults, keywordResults, options) {
|
|
|
8657
8578
|
return cached;
|
|
8658
8579
|
}
|
|
8659
8580
|
}
|
|
8660
|
-
const
|
|
8581
|
+
const overfetchFactor = prioritizeSourcePaths ? 12 : 4;
|
|
8582
|
+
const overfetchLimit = Math.max(options.limit * overfetchFactor, options.limit);
|
|
8661
8583
|
const fused = options.fusionStrategy === "rrf" ? fuseResultsRrf(semanticResults, keywordResults, options.rrfK, overfetchLimit) : fuseResultsWeighted(semanticResults, keywordResults, options.hybridWeight, overfetchLimit);
|
|
8662
8584
|
const rerankPoolLimit = Math.max(overfetchLimit, options.rerankTopN * 3, options.limit * 6);
|
|
8663
8585
|
const rerankPool = fused.slice(0, rerankPoolLimit);
|
|
@@ -10168,7 +10090,6 @@ var Indexer = class _Indexer {
|
|
|
10168
10090
|
database = null;
|
|
10169
10091
|
provider = null;
|
|
10170
10092
|
configuredProviderInfo = null;
|
|
10171
|
-
reranker = null;
|
|
10172
10093
|
fileHashCache = /* @__PURE__ */ new Map();
|
|
10173
10094
|
fileHashCachePath = "";
|
|
10174
10095
|
failedBatchesPath = "";
|
|
@@ -10328,7 +10249,6 @@ var Indexer = class _Indexer {
|
|
|
10328
10249
|
this.database = null;
|
|
10329
10250
|
this.provider = null;
|
|
10330
10251
|
this.configuredProviderInfo = null;
|
|
10331
|
-
this.reranker = null;
|
|
10332
10252
|
this.indexCompatibility = null;
|
|
10333
10253
|
this.initializationMode = "none";
|
|
10334
10254
|
this.readIssues = [];
|
|
@@ -11058,7 +10978,7 @@ var Indexer = class _Indexer {
|
|
|
11058
10978
|
await options.queue.onSizeLessThan(Math.max(1, options.providerRateLimits.concurrency));
|
|
11059
10979
|
const task = options.queue.add(async () => {
|
|
11060
10980
|
if (options.rateLimitState.backoffMs > 0) {
|
|
11061
|
-
await new Promise((
|
|
10981
|
+
await new Promise((resolve17) => setTimeout(resolve17, options.rateLimitState.backoffMs));
|
|
11062
10982
|
}
|
|
11063
10983
|
try {
|
|
11064
10984
|
const embeddingResult = await pRetry(
|
|
@@ -11625,15 +11545,6 @@ var Indexer = class _Indexer {
|
|
|
11625
11545
|
rerankerEnabled: this.config.reranker?.enabled ?? false
|
|
11626
11546
|
});
|
|
11627
11547
|
this.provider = createEmbeddingProvider(this.configuredProviderInfo);
|
|
11628
|
-
if (this.config.reranker?.enabled) {
|
|
11629
|
-
this.reranker = createReranker(this.config.reranker);
|
|
11630
|
-
if (this.reranker.isAvailable()) {
|
|
11631
|
-
this.logger.info("Reranker initialized", {
|
|
11632
|
-
model: this.config.reranker.model,
|
|
11633
|
-
baseUrl: this.config.reranker.baseUrl
|
|
11634
|
-
});
|
|
11635
|
-
}
|
|
11636
|
-
}
|
|
11637
11548
|
const dimensions = this.configuredProviderInfo.modelInfo.dimensions;
|
|
11638
11549
|
const storePath = path19.join(this.indexPath, "vectors");
|
|
11639
11550
|
const vectorMetadataPath = `${storePath}.meta.json`;
|
|
@@ -13038,6 +12949,7 @@ var Indexer = class _Indexer {
|
|
|
13038
12949
|
const filterByBranch = options?.filterByBranch ?? true;
|
|
13039
12950
|
const sourceIntent = options?.definitionIntent === true || classifyQueryIntentRaw(query) === "source";
|
|
13040
12951
|
const identifierHints = extractIdentifierHints(query);
|
|
12952
|
+
const candidateLimit = maxResults * (sourceIntent ? 12 : 4);
|
|
13041
12953
|
this.logger.search("debug", "Starting search", {
|
|
13042
12954
|
query,
|
|
13043
12955
|
maxResults,
|
|
@@ -13074,7 +12986,7 @@ var Indexer = class _Indexer {
|
|
|
13074
12986
|
const semanticCandidates = embedding ? this.searchSemanticCandidates(
|
|
13075
12987
|
store,
|
|
13076
12988
|
embedding,
|
|
13077
|
-
|
|
12989
|
+
candidateLimit,
|
|
13078
12990
|
branchChunkIds,
|
|
13079
12991
|
shouldPrefilterByBranch
|
|
13080
12992
|
) : [];
|
|
@@ -13082,7 +12994,7 @@ var Indexer = class _Indexer {
|
|
|
13082
12994
|
const keywordStartTime = performance2.now();
|
|
13083
12995
|
const keywordCandidates = await this.keywordSearch(
|
|
13084
12996
|
query,
|
|
13085
|
-
|
|
12997
|
+
candidateLimit,
|
|
13086
12998
|
store,
|
|
13087
12999
|
invertedIndex,
|
|
13088
13000
|
branchChunkIds,
|
|
@@ -13840,9 +13752,9 @@ var Indexer = class _Indexer {
|
|
|
13840
13752
|
this.requireReadableComponents(readIssues, "database");
|
|
13841
13753
|
let shortest = [];
|
|
13842
13754
|
for (const branchKey of this.getBranchCatalogKeys()) {
|
|
13843
|
-
const
|
|
13844
|
-
if (
|
|
13845
|
-
shortest =
|
|
13755
|
+
const path30 = database.findShortestPath(fromName, toName, branchKey, maxDepth);
|
|
13756
|
+
if (path30.length > 0 && (shortest.length === 0 || path30.length < shortest.length)) {
|
|
13757
|
+
shortest = path30;
|
|
13846
13758
|
}
|
|
13847
13759
|
}
|
|
13848
13760
|
return shortest.map((hop) => this.resolveFilePathRecord(hop));
|
|
@@ -13890,13 +13802,13 @@ var Indexer = class _Indexer {
|
|
|
13890
13802
|
}
|
|
13891
13803
|
}
|
|
13892
13804
|
if (!found) continue;
|
|
13893
|
-
const
|
|
13805
|
+
const path30 = [];
|
|
13894
13806
|
let currentSymbolId = toSymbolId;
|
|
13895
13807
|
while (true) {
|
|
13896
13808
|
const symbol = symbolsById.get(currentSymbolId);
|
|
13897
13809
|
if (!symbol) break;
|
|
13898
13810
|
const parent = parentBySymbolId.get(currentSymbolId);
|
|
13899
|
-
|
|
13811
|
+
path30.push({
|
|
13900
13812
|
symbolId: symbol.id,
|
|
13901
13813
|
symbolName: symbol.name,
|
|
13902
13814
|
filePath: symbol.filePath,
|
|
@@ -13906,9 +13818,9 @@ var Indexer = class _Indexer {
|
|
|
13906
13818
|
if (!parent) break;
|
|
13907
13819
|
currentSymbolId = parent.parentId;
|
|
13908
13820
|
}
|
|
13909
|
-
|
|
13910
|
-
if (
|
|
13911
|
-
shortest =
|
|
13821
|
+
path30.reverse();
|
|
13822
|
+
if (path30.length > 0 && (shortest.length === 0 || path30.length < shortest.length)) {
|
|
13823
|
+
shortest = path30;
|
|
13912
13824
|
}
|
|
13913
13825
|
}
|
|
13914
13826
|
return shortest.map((hop) => this.resolveFilePathRecord(hop));
|
|
@@ -14244,7 +14156,6 @@ var Indexer = class _Indexer {
|
|
|
14244
14156
|
this.store = null;
|
|
14245
14157
|
this.invertedIndex = null;
|
|
14246
14158
|
this.provider = null;
|
|
14247
|
-
this.reranker = null;
|
|
14248
14159
|
this.configuredProviderInfo = null;
|
|
14249
14160
|
this.indexCompatibility = null;
|
|
14250
14161
|
this.initializationMode = "none";
|
|
@@ -14569,12 +14480,12 @@ async function getCallGraphPath(projectRoot, host, from, to, maxDepth, fromFileP
|
|
|
14569
14480
|
if (fromResolution.status !== "resolved" || toResolution.status !== "resolved") {
|
|
14570
14481
|
return { from: fromResolution, to: toResolution, path: [] };
|
|
14571
14482
|
}
|
|
14572
|
-
const
|
|
14483
|
+
const path30 = await indexer.findCallPathBySymbolIds(
|
|
14573
14484
|
fromResolution.symbolId,
|
|
14574
14485
|
toResolution.symbolId,
|
|
14575
14486
|
maxDepth
|
|
14576
14487
|
);
|
|
14577
|
-
return { from: fromResolution, to: toResolution, path:
|
|
14488
|
+
return { from: fromResolution, to: toResolution, path: path30 };
|
|
14578
14489
|
}
|
|
14579
14490
|
async function runIndexCodebase(projectRoot, host, args, onProgress) {
|
|
14580
14491
|
const root = getProjectRoot(projectRoot, host);
|
|
@@ -14800,8 +14711,8 @@ function addKnowledgeBase(projectRoot, host, knowledgeBasePath) {
|
|
|
14800
14711
|
}
|
|
14801
14712
|
}
|
|
14802
14713
|
try {
|
|
14803
|
-
const
|
|
14804
|
-
if (!
|
|
14714
|
+
const stat5 = statSync5(normalizedPath2);
|
|
14715
|
+
if (!stat5.isDirectory()) {
|
|
14805
14716
|
return `Error: Path is not a directory: ${normalizedPath2}`;
|
|
14806
14717
|
}
|
|
14807
14718
|
} catch (error) {
|
|
@@ -14849,8 +14760,8 @@ function listKnowledgeBases(projectRoot, host) {
|
|
|
14849
14760
|
`;
|
|
14850
14761
|
if (exists) {
|
|
14851
14762
|
try {
|
|
14852
|
-
const
|
|
14853
|
-
result += ` Type: ${
|
|
14763
|
+
const stat5 = statSync5(resolvedPath);
|
|
14764
|
+
result += ` Type: ${stat5.isDirectory() ? "Directory" : "File"}
|
|
14854
14765
|
`;
|
|
14855
14766
|
} catch {
|
|
14856
14767
|
}
|
|
@@ -14891,7 +14802,7 @@ Run /index to rebuild the index without the removed knowledge base.`;
|
|
|
14891
14802
|
}
|
|
14892
14803
|
|
|
14893
14804
|
// src/watcher/file-watcher.ts
|
|
14894
|
-
import { existsSync as existsSync13 } from "fs";
|
|
14805
|
+
import { existsSync as existsSync13, statSync as statSync6 } from "fs";
|
|
14895
14806
|
|
|
14896
14807
|
// node_modules/chokidar/index.js
|
|
14897
14808
|
import { EventEmitter as EventEmitter2 } from "events";
|
|
@@ -14983,7 +14894,7 @@ var ReaddirpStream = class extends Readable {
|
|
|
14983
14894
|
this._directoryFilter = normalizeFilter(opts.directoryFilter);
|
|
14984
14895
|
const statMethod = opts.lstat ? lstat : stat;
|
|
14985
14896
|
if (wantBigintFsStats) {
|
|
14986
|
-
this._stat = (
|
|
14897
|
+
this._stat = (path30) => statMethod(path30, { bigint: true });
|
|
14987
14898
|
} else {
|
|
14988
14899
|
this._stat = statMethod;
|
|
14989
14900
|
}
|
|
@@ -15008,8 +14919,8 @@ var ReaddirpStream = class extends Readable {
|
|
|
15008
14919
|
const par = this.parent;
|
|
15009
14920
|
const fil = par && par.files;
|
|
15010
14921
|
if (fil && fil.length > 0) {
|
|
15011
|
-
const { path:
|
|
15012
|
-
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent,
|
|
14922
|
+
const { path: path30, depth } = par;
|
|
14923
|
+
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path30));
|
|
15013
14924
|
const awaited = await Promise.all(slice);
|
|
15014
14925
|
for (const entry of awaited) {
|
|
15015
14926
|
if (!entry)
|
|
@@ -15049,20 +14960,20 @@ var ReaddirpStream = class extends Readable {
|
|
|
15049
14960
|
this.reading = false;
|
|
15050
14961
|
}
|
|
15051
14962
|
}
|
|
15052
|
-
async _exploreDir(
|
|
14963
|
+
async _exploreDir(path30, depth) {
|
|
15053
14964
|
let files;
|
|
15054
14965
|
try {
|
|
15055
|
-
files = await readdir(
|
|
14966
|
+
files = await readdir(path30, this._rdOptions);
|
|
15056
14967
|
} catch (error) {
|
|
15057
14968
|
this._onError(error);
|
|
15058
14969
|
}
|
|
15059
|
-
return { files, depth, path:
|
|
14970
|
+
return { files, depth, path: path30 };
|
|
15060
14971
|
}
|
|
15061
|
-
async _formatEntry(dirent,
|
|
14972
|
+
async _formatEntry(dirent, path30) {
|
|
15062
14973
|
let entry;
|
|
15063
14974
|
const basename9 = this._isDirent ? dirent.name : dirent;
|
|
15064
14975
|
try {
|
|
15065
|
-
const fullPath = presolve(pjoin(
|
|
14976
|
+
const fullPath = presolve(pjoin(path30, basename9));
|
|
15066
14977
|
entry = { path: prelative(this._root, fullPath), fullPath, basename: basename9 };
|
|
15067
14978
|
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
15068
14979
|
} catch (err) {
|
|
@@ -15462,16 +15373,16 @@ var delFromSet = (main, prop, item) => {
|
|
|
15462
15373
|
};
|
|
15463
15374
|
var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
|
|
15464
15375
|
var FsWatchInstances = /* @__PURE__ */ new Map();
|
|
15465
|
-
function createFsWatchInstance(
|
|
15376
|
+
function createFsWatchInstance(path30, options, listener, errHandler, emitRaw) {
|
|
15466
15377
|
const handleEvent = (rawEvent, evPath) => {
|
|
15467
|
-
listener(
|
|
15468
|
-
emitRaw(rawEvent, evPath, { watchedPath:
|
|
15469
|
-
if (evPath &&
|
|
15470
|
-
fsWatchBroadcast(sp.resolve(
|
|
15378
|
+
listener(path30);
|
|
15379
|
+
emitRaw(rawEvent, evPath, { watchedPath: path30 });
|
|
15380
|
+
if (evPath && path30 !== evPath) {
|
|
15381
|
+
fsWatchBroadcast(sp.resolve(path30, evPath), KEY_LISTENERS, sp.join(path30, evPath));
|
|
15471
15382
|
}
|
|
15472
15383
|
};
|
|
15473
15384
|
try {
|
|
15474
|
-
return fs_watch(
|
|
15385
|
+
return fs_watch(path30, {
|
|
15475
15386
|
persistent: options.persistent
|
|
15476
15387
|
}, handleEvent);
|
|
15477
15388
|
} catch (error) {
|
|
@@ -15487,12 +15398,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
|
|
|
15487
15398
|
listener(val1, val2, val3);
|
|
15488
15399
|
});
|
|
15489
15400
|
};
|
|
15490
|
-
var setFsWatchListener = (
|
|
15401
|
+
var setFsWatchListener = (path30, fullPath, options, handlers) => {
|
|
15491
15402
|
const { listener, errHandler, rawEmitter } = handlers;
|
|
15492
15403
|
let cont = FsWatchInstances.get(fullPath);
|
|
15493
15404
|
let watcher;
|
|
15494
15405
|
if (!options.persistent) {
|
|
15495
|
-
watcher = createFsWatchInstance(
|
|
15406
|
+
watcher = createFsWatchInstance(path30, options, listener, errHandler, rawEmitter);
|
|
15496
15407
|
if (!watcher)
|
|
15497
15408
|
return;
|
|
15498
15409
|
return watcher.close.bind(watcher);
|
|
@@ -15503,7 +15414,7 @@ var setFsWatchListener = (path28, fullPath, options, handlers) => {
|
|
|
15503
15414
|
addAndConvert(cont, KEY_RAW, rawEmitter);
|
|
15504
15415
|
} else {
|
|
15505
15416
|
watcher = createFsWatchInstance(
|
|
15506
|
-
|
|
15417
|
+
path30,
|
|
15507
15418
|
options,
|
|
15508
15419
|
fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
|
|
15509
15420
|
errHandler,
|
|
@@ -15518,7 +15429,7 @@ var setFsWatchListener = (path28, fullPath, options, handlers) => {
|
|
|
15518
15429
|
cont.watcherUnusable = true;
|
|
15519
15430
|
if (isWindows && error.code === "EPERM") {
|
|
15520
15431
|
try {
|
|
15521
|
-
const fd = await open(
|
|
15432
|
+
const fd = await open(path30, "r");
|
|
15522
15433
|
await fd.close();
|
|
15523
15434
|
broadcastErr(error);
|
|
15524
15435
|
} catch (err) {
|
|
@@ -15549,7 +15460,7 @@ var setFsWatchListener = (path28, fullPath, options, handlers) => {
|
|
|
15549
15460
|
};
|
|
15550
15461
|
};
|
|
15551
15462
|
var FsWatchFileInstances = /* @__PURE__ */ new Map();
|
|
15552
|
-
var setFsWatchFileListener = (
|
|
15463
|
+
var setFsWatchFileListener = (path30, fullPath, options, handlers) => {
|
|
15553
15464
|
const { listener, rawEmitter } = handlers;
|
|
15554
15465
|
let cont = FsWatchFileInstances.get(fullPath);
|
|
15555
15466
|
const copts = cont && cont.options;
|
|
@@ -15571,7 +15482,7 @@ var setFsWatchFileListener = (path28, fullPath, options, handlers) => {
|
|
|
15571
15482
|
});
|
|
15572
15483
|
const currmtime = curr.mtimeMs;
|
|
15573
15484
|
if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
|
|
15574
|
-
foreach(cont.listeners, (listener2) => listener2(
|
|
15485
|
+
foreach(cont.listeners, (listener2) => listener2(path30, curr));
|
|
15575
15486
|
}
|
|
15576
15487
|
})
|
|
15577
15488
|
};
|
|
@@ -15601,13 +15512,13 @@ var NodeFsHandler = class {
|
|
|
15601
15512
|
* @param listener on fs change
|
|
15602
15513
|
* @returns closer for the watcher instance
|
|
15603
15514
|
*/
|
|
15604
|
-
_watchWithNodeFs(
|
|
15515
|
+
_watchWithNodeFs(path30, listener) {
|
|
15605
15516
|
const opts = this.fsw.options;
|
|
15606
|
-
const directory = sp.dirname(
|
|
15607
|
-
const basename9 = sp.basename(
|
|
15517
|
+
const directory = sp.dirname(path30);
|
|
15518
|
+
const basename9 = sp.basename(path30);
|
|
15608
15519
|
const parent = this.fsw._getWatchedDir(directory);
|
|
15609
15520
|
parent.add(basename9);
|
|
15610
|
-
const absolutePath = sp.resolve(
|
|
15521
|
+
const absolutePath = sp.resolve(path30);
|
|
15611
15522
|
const options = {
|
|
15612
15523
|
persistent: opts.persistent
|
|
15613
15524
|
};
|
|
@@ -15617,12 +15528,12 @@ var NodeFsHandler = class {
|
|
|
15617
15528
|
if (opts.usePolling) {
|
|
15618
15529
|
const enableBin = opts.interval !== opts.binaryInterval;
|
|
15619
15530
|
options.interval = enableBin && isBinaryPath(basename9) ? opts.binaryInterval : opts.interval;
|
|
15620
|
-
closer = setFsWatchFileListener(
|
|
15531
|
+
closer = setFsWatchFileListener(path30, absolutePath, options, {
|
|
15621
15532
|
listener,
|
|
15622
15533
|
rawEmitter: this.fsw._emitRaw
|
|
15623
15534
|
});
|
|
15624
15535
|
} else {
|
|
15625
|
-
closer = setFsWatchListener(
|
|
15536
|
+
closer = setFsWatchListener(path30, absolutePath, options, {
|
|
15626
15537
|
listener,
|
|
15627
15538
|
errHandler: this._boundHandleError,
|
|
15628
15539
|
rawEmitter: this.fsw._emitRaw
|
|
@@ -15644,7 +15555,7 @@ var NodeFsHandler = class {
|
|
|
15644
15555
|
let prevStats = stats;
|
|
15645
15556
|
if (parent.has(basename9))
|
|
15646
15557
|
return;
|
|
15647
|
-
const listener = async (
|
|
15558
|
+
const listener = async (path30, newStats) => {
|
|
15648
15559
|
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
|
|
15649
15560
|
return;
|
|
15650
15561
|
if (!newStats || newStats.mtimeMs === 0) {
|
|
@@ -15658,11 +15569,11 @@ var NodeFsHandler = class {
|
|
|
15658
15569
|
this.fsw._emit(EV.CHANGE, file, newStats2);
|
|
15659
15570
|
}
|
|
15660
15571
|
if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
|
|
15661
|
-
this.fsw._closeFile(
|
|
15572
|
+
this.fsw._closeFile(path30);
|
|
15662
15573
|
prevStats = newStats2;
|
|
15663
15574
|
const closer2 = this._watchWithNodeFs(file, listener);
|
|
15664
15575
|
if (closer2)
|
|
15665
|
-
this.fsw._addPathCloser(
|
|
15576
|
+
this.fsw._addPathCloser(path30, closer2);
|
|
15666
15577
|
} else {
|
|
15667
15578
|
prevStats = newStats2;
|
|
15668
15579
|
}
|
|
@@ -15694,7 +15605,7 @@ var NodeFsHandler = class {
|
|
|
15694
15605
|
* @param item basename of this item
|
|
15695
15606
|
* @returns true if no more processing is needed for this entry.
|
|
15696
15607
|
*/
|
|
15697
|
-
async _handleSymlink(entry, directory,
|
|
15608
|
+
async _handleSymlink(entry, directory, path30, item) {
|
|
15698
15609
|
if (this.fsw.closed) {
|
|
15699
15610
|
return;
|
|
15700
15611
|
}
|
|
@@ -15704,7 +15615,7 @@ var NodeFsHandler = class {
|
|
|
15704
15615
|
this.fsw._incrReadyCount();
|
|
15705
15616
|
let linkPath;
|
|
15706
15617
|
try {
|
|
15707
|
-
linkPath = await fsrealpath(
|
|
15618
|
+
linkPath = await fsrealpath(path30);
|
|
15708
15619
|
} catch (e) {
|
|
15709
15620
|
this.fsw._emitReady();
|
|
15710
15621
|
return true;
|
|
@@ -15714,12 +15625,12 @@ var NodeFsHandler = class {
|
|
|
15714
15625
|
if (dir.has(item)) {
|
|
15715
15626
|
if (this.fsw._symlinkPaths.get(full) !== linkPath) {
|
|
15716
15627
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
15717
|
-
this.fsw._emit(EV.CHANGE,
|
|
15628
|
+
this.fsw._emit(EV.CHANGE, path30, entry.stats);
|
|
15718
15629
|
}
|
|
15719
15630
|
} else {
|
|
15720
15631
|
dir.add(item);
|
|
15721
15632
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
15722
|
-
this.fsw._emit(EV.ADD,
|
|
15633
|
+
this.fsw._emit(EV.ADD, path30, entry.stats);
|
|
15723
15634
|
}
|
|
15724
15635
|
this.fsw._emitReady();
|
|
15725
15636
|
return true;
|
|
@@ -15749,9 +15660,9 @@ var NodeFsHandler = class {
|
|
|
15749
15660
|
return;
|
|
15750
15661
|
}
|
|
15751
15662
|
const item = entry.path;
|
|
15752
|
-
let
|
|
15663
|
+
let path30 = sp.join(directory, item);
|
|
15753
15664
|
current.add(item);
|
|
15754
|
-
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory,
|
|
15665
|
+
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path30, item)) {
|
|
15755
15666
|
return;
|
|
15756
15667
|
}
|
|
15757
15668
|
if (this.fsw.closed) {
|
|
@@ -15760,11 +15671,11 @@ var NodeFsHandler = class {
|
|
|
15760
15671
|
}
|
|
15761
15672
|
if (item === target || !target && !previous.has(item)) {
|
|
15762
15673
|
this.fsw._incrReadyCount();
|
|
15763
|
-
|
|
15764
|
-
this._addToNodeFs(
|
|
15674
|
+
path30 = sp.join(dir, sp.relative(dir, path30));
|
|
15675
|
+
this._addToNodeFs(path30, initialAdd, wh, depth + 1);
|
|
15765
15676
|
}
|
|
15766
15677
|
}).on(EV.ERROR, this._boundHandleError);
|
|
15767
|
-
return new Promise((
|
|
15678
|
+
return new Promise((resolve17, reject) => {
|
|
15768
15679
|
if (!stream)
|
|
15769
15680
|
return reject();
|
|
15770
15681
|
stream.once(STR_END, () => {
|
|
@@ -15773,7 +15684,7 @@ var NodeFsHandler = class {
|
|
|
15773
15684
|
return;
|
|
15774
15685
|
}
|
|
15775
15686
|
const wasThrottled = throttler ? throttler.clear() : false;
|
|
15776
|
-
|
|
15687
|
+
resolve17(void 0);
|
|
15777
15688
|
previous.getChildren().filter((item) => {
|
|
15778
15689
|
return item !== directory && !current.has(item);
|
|
15779
15690
|
}).forEach((item) => {
|
|
@@ -15830,13 +15741,13 @@ var NodeFsHandler = class {
|
|
|
15830
15741
|
* @param depth Child path actually targeted for watch
|
|
15831
15742
|
* @param target Child path actually targeted for watch
|
|
15832
15743
|
*/
|
|
15833
|
-
async _addToNodeFs(
|
|
15744
|
+
async _addToNodeFs(path30, initialAdd, priorWh, depth, target) {
|
|
15834
15745
|
const ready = this.fsw._emitReady;
|
|
15835
|
-
if (this.fsw._isIgnored(
|
|
15746
|
+
if (this.fsw._isIgnored(path30) || this.fsw.closed) {
|
|
15836
15747
|
ready();
|
|
15837
15748
|
return false;
|
|
15838
15749
|
}
|
|
15839
|
-
const wh = this.fsw._getWatchHelpers(
|
|
15750
|
+
const wh = this.fsw._getWatchHelpers(path30);
|
|
15840
15751
|
if (priorWh) {
|
|
15841
15752
|
wh.filterPath = (entry) => priorWh.filterPath(entry);
|
|
15842
15753
|
wh.filterDir = (entry) => priorWh.filterDir(entry);
|
|
@@ -15852,8 +15763,8 @@ var NodeFsHandler = class {
|
|
|
15852
15763
|
const follow = this.fsw.options.followSymlinks;
|
|
15853
15764
|
let closer;
|
|
15854
15765
|
if (stats.isDirectory()) {
|
|
15855
|
-
const absPath = sp.resolve(
|
|
15856
|
-
const targetPath = follow ? await fsrealpath(
|
|
15766
|
+
const absPath = sp.resolve(path30);
|
|
15767
|
+
const targetPath = follow ? await fsrealpath(path30) : path30;
|
|
15857
15768
|
if (this.fsw.closed)
|
|
15858
15769
|
return;
|
|
15859
15770
|
closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
|
|
@@ -15863,29 +15774,29 @@ var NodeFsHandler = class {
|
|
|
15863
15774
|
this.fsw._symlinkPaths.set(absPath, targetPath);
|
|
15864
15775
|
}
|
|
15865
15776
|
} else if (stats.isSymbolicLink()) {
|
|
15866
|
-
const targetPath = follow ? await fsrealpath(
|
|
15777
|
+
const targetPath = follow ? await fsrealpath(path30) : path30;
|
|
15867
15778
|
if (this.fsw.closed)
|
|
15868
15779
|
return;
|
|
15869
15780
|
const parent = sp.dirname(wh.watchPath);
|
|
15870
15781
|
this.fsw._getWatchedDir(parent).add(wh.watchPath);
|
|
15871
15782
|
this.fsw._emit(EV.ADD, wh.watchPath, stats);
|
|
15872
|
-
closer = await this._handleDir(parent, stats, initialAdd, depth,
|
|
15783
|
+
closer = await this._handleDir(parent, stats, initialAdd, depth, path30, wh, targetPath);
|
|
15873
15784
|
if (this.fsw.closed)
|
|
15874
15785
|
return;
|
|
15875
15786
|
if (targetPath !== void 0) {
|
|
15876
|
-
this.fsw._symlinkPaths.set(sp.resolve(
|
|
15787
|
+
this.fsw._symlinkPaths.set(sp.resolve(path30), targetPath);
|
|
15877
15788
|
}
|
|
15878
15789
|
} else {
|
|
15879
15790
|
closer = this._handleFile(wh.watchPath, stats, initialAdd);
|
|
15880
15791
|
}
|
|
15881
15792
|
ready();
|
|
15882
15793
|
if (closer)
|
|
15883
|
-
this.fsw._addPathCloser(
|
|
15794
|
+
this.fsw._addPathCloser(path30, closer);
|
|
15884
15795
|
return false;
|
|
15885
15796
|
} catch (error) {
|
|
15886
15797
|
if (this.fsw._handleError(error)) {
|
|
15887
15798
|
ready();
|
|
15888
|
-
return
|
|
15799
|
+
return path30;
|
|
15889
15800
|
}
|
|
15890
15801
|
}
|
|
15891
15802
|
}
|
|
@@ -15917,35 +15828,35 @@ function createPattern(matcher) {
|
|
|
15917
15828
|
if (matcher.path === string)
|
|
15918
15829
|
return true;
|
|
15919
15830
|
if (matcher.recursive) {
|
|
15920
|
-
const
|
|
15921
|
-
if (!
|
|
15831
|
+
const relative14 = sp2.relative(matcher.path, string);
|
|
15832
|
+
if (!relative14) {
|
|
15922
15833
|
return false;
|
|
15923
15834
|
}
|
|
15924
|
-
return !
|
|
15835
|
+
return !relative14.startsWith("..") && !sp2.isAbsolute(relative14);
|
|
15925
15836
|
}
|
|
15926
15837
|
return false;
|
|
15927
15838
|
};
|
|
15928
15839
|
}
|
|
15929
15840
|
return () => false;
|
|
15930
15841
|
}
|
|
15931
|
-
function normalizePath2(
|
|
15932
|
-
if (typeof
|
|
15842
|
+
function normalizePath2(path30) {
|
|
15843
|
+
if (typeof path30 !== "string")
|
|
15933
15844
|
throw new Error("string expected");
|
|
15934
|
-
|
|
15935
|
-
|
|
15845
|
+
path30 = sp2.normalize(path30);
|
|
15846
|
+
path30 = path30.replace(/\\/g, "/");
|
|
15936
15847
|
let prepend = false;
|
|
15937
|
-
if (
|
|
15848
|
+
if (path30.startsWith("//"))
|
|
15938
15849
|
prepend = true;
|
|
15939
|
-
|
|
15850
|
+
path30 = path30.replace(DOUBLE_SLASH_RE, "/");
|
|
15940
15851
|
if (prepend)
|
|
15941
|
-
|
|
15942
|
-
return
|
|
15852
|
+
path30 = "/" + path30;
|
|
15853
|
+
return path30;
|
|
15943
15854
|
}
|
|
15944
15855
|
function matchPatterns(patterns, testString, stats) {
|
|
15945
|
-
const
|
|
15856
|
+
const path30 = normalizePath2(testString);
|
|
15946
15857
|
for (let index = 0; index < patterns.length; index++) {
|
|
15947
15858
|
const pattern = patterns[index];
|
|
15948
|
-
if (pattern(
|
|
15859
|
+
if (pattern(path30, stats)) {
|
|
15949
15860
|
return true;
|
|
15950
15861
|
}
|
|
15951
15862
|
}
|
|
@@ -15983,19 +15894,19 @@ var toUnix = (string) => {
|
|
|
15983
15894
|
}
|
|
15984
15895
|
return str;
|
|
15985
15896
|
};
|
|
15986
|
-
var normalizePathToUnix = (
|
|
15987
|
-
var normalizeIgnored = (cwd = "") => (
|
|
15988
|
-
if (typeof
|
|
15989
|
-
return normalizePathToUnix(sp2.isAbsolute(
|
|
15897
|
+
var normalizePathToUnix = (path30) => toUnix(sp2.normalize(toUnix(path30)));
|
|
15898
|
+
var normalizeIgnored = (cwd = "") => (path30) => {
|
|
15899
|
+
if (typeof path30 === "string") {
|
|
15900
|
+
return normalizePathToUnix(sp2.isAbsolute(path30) ? path30 : sp2.join(cwd, path30));
|
|
15990
15901
|
} else {
|
|
15991
|
-
return
|
|
15902
|
+
return path30;
|
|
15992
15903
|
}
|
|
15993
15904
|
};
|
|
15994
|
-
var getAbsolutePath = (
|
|
15995
|
-
if (sp2.isAbsolute(
|
|
15996
|
-
return
|
|
15905
|
+
var getAbsolutePath = (path30, cwd) => {
|
|
15906
|
+
if (sp2.isAbsolute(path30)) {
|
|
15907
|
+
return path30;
|
|
15997
15908
|
}
|
|
15998
|
-
return sp2.join(cwd,
|
|
15909
|
+
return sp2.join(cwd, path30);
|
|
15999
15910
|
};
|
|
16000
15911
|
var EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
|
|
16001
15912
|
var DirEntry = class {
|
|
@@ -16060,10 +15971,10 @@ var WatchHelper = class {
|
|
|
16060
15971
|
dirParts;
|
|
16061
15972
|
followSymlinks;
|
|
16062
15973
|
statMethod;
|
|
16063
|
-
constructor(
|
|
15974
|
+
constructor(path30, follow, fsw) {
|
|
16064
15975
|
this.fsw = fsw;
|
|
16065
|
-
const watchPath =
|
|
16066
|
-
this.path =
|
|
15976
|
+
const watchPath = path30;
|
|
15977
|
+
this.path = path30 = path30.replace(REPLACER_RE, "");
|
|
16067
15978
|
this.watchPath = watchPath;
|
|
16068
15979
|
this.fullWatchPath = sp2.resolve(watchPath);
|
|
16069
15980
|
this.dirParts = [];
|
|
@@ -16203,20 +16114,20 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
16203
16114
|
this._closePromise = void 0;
|
|
16204
16115
|
let paths = unifyPaths(paths_);
|
|
16205
16116
|
if (cwd) {
|
|
16206
|
-
paths = paths.map((
|
|
16207
|
-
const absPath = getAbsolutePath(
|
|
16117
|
+
paths = paths.map((path30) => {
|
|
16118
|
+
const absPath = getAbsolutePath(path30, cwd);
|
|
16208
16119
|
return absPath;
|
|
16209
16120
|
});
|
|
16210
16121
|
}
|
|
16211
|
-
paths.forEach((
|
|
16212
|
-
this._removeIgnoredPath(
|
|
16122
|
+
paths.forEach((path30) => {
|
|
16123
|
+
this._removeIgnoredPath(path30);
|
|
16213
16124
|
});
|
|
16214
16125
|
this._userIgnored = void 0;
|
|
16215
16126
|
if (!this._readyCount)
|
|
16216
16127
|
this._readyCount = 0;
|
|
16217
16128
|
this._readyCount += paths.length;
|
|
16218
|
-
Promise.all(paths.map(async (
|
|
16219
|
-
const res = await this._nodeFsHandler._addToNodeFs(
|
|
16129
|
+
Promise.all(paths.map(async (path30) => {
|
|
16130
|
+
const res = await this._nodeFsHandler._addToNodeFs(path30, !_internal, void 0, 0, _origAdd);
|
|
16220
16131
|
if (res)
|
|
16221
16132
|
this._emitReady();
|
|
16222
16133
|
return res;
|
|
@@ -16238,17 +16149,17 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
16238
16149
|
return this;
|
|
16239
16150
|
const paths = unifyPaths(paths_);
|
|
16240
16151
|
const { cwd } = this.options;
|
|
16241
|
-
paths.forEach((
|
|
16242
|
-
if (!sp2.isAbsolute(
|
|
16152
|
+
paths.forEach((path30) => {
|
|
16153
|
+
if (!sp2.isAbsolute(path30) && !this._closers.has(path30)) {
|
|
16243
16154
|
if (cwd)
|
|
16244
|
-
|
|
16245
|
-
|
|
16155
|
+
path30 = sp2.join(cwd, path30);
|
|
16156
|
+
path30 = sp2.resolve(path30);
|
|
16246
16157
|
}
|
|
16247
|
-
this._closePath(
|
|
16248
|
-
this._addIgnoredPath(
|
|
16249
|
-
if (this._watched.has(
|
|
16158
|
+
this._closePath(path30);
|
|
16159
|
+
this._addIgnoredPath(path30);
|
|
16160
|
+
if (this._watched.has(path30)) {
|
|
16250
16161
|
this._addIgnoredPath({
|
|
16251
|
-
path:
|
|
16162
|
+
path: path30,
|
|
16252
16163
|
recursive: true
|
|
16253
16164
|
});
|
|
16254
16165
|
}
|
|
@@ -16312,38 +16223,38 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
16312
16223
|
* @param stats arguments to be passed with event
|
|
16313
16224
|
* @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
|
|
16314
16225
|
*/
|
|
16315
|
-
async _emit(event,
|
|
16226
|
+
async _emit(event, path30, stats) {
|
|
16316
16227
|
if (this.closed)
|
|
16317
16228
|
return;
|
|
16318
16229
|
const opts = this.options;
|
|
16319
16230
|
if (isWindows)
|
|
16320
|
-
|
|
16231
|
+
path30 = sp2.normalize(path30);
|
|
16321
16232
|
if (opts.cwd)
|
|
16322
|
-
|
|
16323
|
-
const args = [
|
|
16233
|
+
path30 = sp2.relative(opts.cwd, path30);
|
|
16234
|
+
const args = [path30];
|
|
16324
16235
|
if (stats != null)
|
|
16325
16236
|
args.push(stats);
|
|
16326
16237
|
const awf = opts.awaitWriteFinish;
|
|
16327
16238
|
let pw;
|
|
16328
|
-
if (awf && (pw = this._pendingWrites.get(
|
|
16239
|
+
if (awf && (pw = this._pendingWrites.get(path30))) {
|
|
16329
16240
|
pw.lastChange = /* @__PURE__ */ new Date();
|
|
16330
16241
|
return this;
|
|
16331
16242
|
}
|
|
16332
16243
|
if (opts.atomic) {
|
|
16333
16244
|
if (event === EVENTS.UNLINK) {
|
|
16334
|
-
this._pendingUnlinks.set(
|
|
16245
|
+
this._pendingUnlinks.set(path30, [event, ...args]);
|
|
16335
16246
|
setTimeout(() => {
|
|
16336
|
-
this._pendingUnlinks.forEach((entry,
|
|
16247
|
+
this._pendingUnlinks.forEach((entry, path31) => {
|
|
16337
16248
|
this.emit(...entry);
|
|
16338
16249
|
this.emit(EVENTS.ALL, ...entry);
|
|
16339
|
-
this._pendingUnlinks.delete(
|
|
16250
|
+
this._pendingUnlinks.delete(path31);
|
|
16340
16251
|
});
|
|
16341
16252
|
}, typeof opts.atomic === "number" ? opts.atomic : 100);
|
|
16342
16253
|
return this;
|
|
16343
16254
|
}
|
|
16344
|
-
if (event === EVENTS.ADD && this._pendingUnlinks.has(
|
|
16255
|
+
if (event === EVENTS.ADD && this._pendingUnlinks.has(path30)) {
|
|
16345
16256
|
event = EVENTS.CHANGE;
|
|
16346
|
-
this._pendingUnlinks.delete(
|
|
16257
|
+
this._pendingUnlinks.delete(path30);
|
|
16347
16258
|
}
|
|
16348
16259
|
}
|
|
16349
16260
|
if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
|
|
@@ -16361,16 +16272,16 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
16361
16272
|
this.emitWithAll(event, args);
|
|
16362
16273
|
}
|
|
16363
16274
|
};
|
|
16364
|
-
this._awaitWriteFinish(
|
|
16275
|
+
this._awaitWriteFinish(path30, awf.stabilityThreshold, event, awfEmit);
|
|
16365
16276
|
return this;
|
|
16366
16277
|
}
|
|
16367
16278
|
if (event === EVENTS.CHANGE) {
|
|
16368
|
-
const isThrottled = !this._throttle(EVENTS.CHANGE,
|
|
16279
|
+
const isThrottled = !this._throttle(EVENTS.CHANGE, path30, 50);
|
|
16369
16280
|
if (isThrottled)
|
|
16370
16281
|
return this;
|
|
16371
16282
|
}
|
|
16372
16283
|
if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
|
|
16373
|
-
const fullPath = opts.cwd ? sp2.join(opts.cwd,
|
|
16284
|
+
const fullPath = opts.cwd ? sp2.join(opts.cwd, path30) : path30;
|
|
16374
16285
|
let stats2;
|
|
16375
16286
|
try {
|
|
16376
16287
|
stats2 = await stat3(fullPath);
|
|
@@ -16401,23 +16312,23 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
16401
16312
|
* @param timeout duration of time to suppress duplicate actions
|
|
16402
16313
|
* @returns tracking object or false if action should be suppressed
|
|
16403
16314
|
*/
|
|
16404
|
-
_throttle(actionType,
|
|
16315
|
+
_throttle(actionType, path30, timeout) {
|
|
16405
16316
|
if (!this._throttled.has(actionType)) {
|
|
16406
16317
|
this._throttled.set(actionType, /* @__PURE__ */ new Map());
|
|
16407
16318
|
}
|
|
16408
16319
|
const action = this._throttled.get(actionType);
|
|
16409
16320
|
if (!action)
|
|
16410
16321
|
throw new Error("invalid throttle");
|
|
16411
|
-
const actionPath = action.get(
|
|
16322
|
+
const actionPath = action.get(path30);
|
|
16412
16323
|
if (actionPath) {
|
|
16413
16324
|
actionPath.count++;
|
|
16414
16325
|
return false;
|
|
16415
16326
|
}
|
|
16416
16327
|
let timeoutObject;
|
|
16417
16328
|
const clear = () => {
|
|
16418
|
-
const item = action.get(
|
|
16329
|
+
const item = action.get(path30);
|
|
16419
16330
|
const count = item ? item.count : 0;
|
|
16420
|
-
action.delete(
|
|
16331
|
+
action.delete(path30);
|
|
16421
16332
|
clearTimeout(timeoutObject);
|
|
16422
16333
|
if (item)
|
|
16423
16334
|
clearTimeout(item.timeoutObject);
|
|
@@ -16425,7 +16336,7 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
16425
16336
|
};
|
|
16426
16337
|
timeoutObject = setTimeout(clear, timeout);
|
|
16427
16338
|
const thr = { timeoutObject, clear, count: 0 };
|
|
16428
|
-
action.set(
|
|
16339
|
+
action.set(path30, thr);
|
|
16429
16340
|
return thr;
|
|
16430
16341
|
}
|
|
16431
16342
|
_incrReadyCount() {
|
|
@@ -16439,44 +16350,44 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
16439
16350
|
* @param event
|
|
16440
16351
|
* @param awfEmit Callback to be called when ready for event to be emitted.
|
|
16441
16352
|
*/
|
|
16442
|
-
_awaitWriteFinish(
|
|
16353
|
+
_awaitWriteFinish(path30, threshold, event, awfEmit) {
|
|
16443
16354
|
const awf = this.options.awaitWriteFinish;
|
|
16444
16355
|
if (typeof awf !== "object")
|
|
16445
16356
|
return;
|
|
16446
16357
|
const pollInterval = awf.pollInterval;
|
|
16447
16358
|
let timeoutHandler;
|
|
16448
|
-
let fullPath =
|
|
16449
|
-
if (this.options.cwd && !sp2.isAbsolute(
|
|
16450
|
-
fullPath = sp2.join(this.options.cwd,
|
|
16359
|
+
let fullPath = path30;
|
|
16360
|
+
if (this.options.cwd && !sp2.isAbsolute(path30)) {
|
|
16361
|
+
fullPath = sp2.join(this.options.cwd, path30);
|
|
16451
16362
|
}
|
|
16452
16363
|
const now2 = /* @__PURE__ */ new Date();
|
|
16453
16364
|
const writes = this._pendingWrites;
|
|
16454
16365
|
function awaitWriteFinishFn(prevStat) {
|
|
16455
16366
|
statcb(fullPath, (err, curStat) => {
|
|
16456
|
-
if (err || !writes.has(
|
|
16367
|
+
if (err || !writes.has(path30)) {
|
|
16457
16368
|
if (err && err.code !== "ENOENT")
|
|
16458
16369
|
awfEmit(err);
|
|
16459
16370
|
return;
|
|
16460
16371
|
}
|
|
16461
16372
|
const now3 = Number(/* @__PURE__ */ new Date());
|
|
16462
16373
|
if (prevStat && curStat.size !== prevStat.size) {
|
|
16463
|
-
writes.get(
|
|
16374
|
+
writes.get(path30).lastChange = now3;
|
|
16464
16375
|
}
|
|
16465
|
-
const pw = writes.get(
|
|
16376
|
+
const pw = writes.get(path30);
|
|
16466
16377
|
const df = now3 - pw.lastChange;
|
|
16467
16378
|
if (df >= threshold) {
|
|
16468
|
-
writes.delete(
|
|
16379
|
+
writes.delete(path30);
|
|
16469
16380
|
awfEmit(void 0, curStat);
|
|
16470
16381
|
} else {
|
|
16471
16382
|
timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
|
|
16472
16383
|
}
|
|
16473
16384
|
});
|
|
16474
16385
|
}
|
|
16475
|
-
if (!writes.has(
|
|
16476
|
-
writes.set(
|
|
16386
|
+
if (!writes.has(path30)) {
|
|
16387
|
+
writes.set(path30, {
|
|
16477
16388
|
lastChange: now2,
|
|
16478
16389
|
cancelWait: () => {
|
|
16479
|
-
writes.delete(
|
|
16390
|
+
writes.delete(path30);
|
|
16480
16391
|
clearTimeout(timeoutHandler);
|
|
16481
16392
|
return event;
|
|
16482
16393
|
}
|
|
@@ -16487,8 +16398,8 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
16487
16398
|
/**
|
|
16488
16399
|
* Determines whether user has asked to ignore this path.
|
|
16489
16400
|
*/
|
|
16490
|
-
_isIgnored(
|
|
16491
|
-
if (this.options.atomic && DOT_RE.test(
|
|
16401
|
+
_isIgnored(path30, stats) {
|
|
16402
|
+
if (this.options.atomic && DOT_RE.test(path30))
|
|
16492
16403
|
return true;
|
|
16493
16404
|
if (!this._userIgnored) {
|
|
16494
16405
|
const { cwd } = this.options;
|
|
@@ -16498,17 +16409,17 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
16498
16409
|
const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
|
|
16499
16410
|
this._userIgnored = anymatch(list, void 0);
|
|
16500
16411
|
}
|
|
16501
|
-
return this._userIgnored(
|
|
16412
|
+
return this._userIgnored(path30, stats);
|
|
16502
16413
|
}
|
|
16503
|
-
_isntIgnored(
|
|
16504
|
-
return !this._isIgnored(
|
|
16414
|
+
_isntIgnored(path30, stat5) {
|
|
16415
|
+
return !this._isIgnored(path30, stat5);
|
|
16505
16416
|
}
|
|
16506
16417
|
/**
|
|
16507
16418
|
* Provides a set of common helpers and properties relating to symlink handling.
|
|
16508
16419
|
* @param path file or directory pattern being watched
|
|
16509
16420
|
*/
|
|
16510
|
-
_getWatchHelpers(
|
|
16511
|
-
return new WatchHelper(
|
|
16421
|
+
_getWatchHelpers(path30) {
|
|
16422
|
+
return new WatchHelper(path30, this.options.followSymlinks, this);
|
|
16512
16423
|
}
|
|
16513
16424
|
// Directory helpers
|
|
16514
16425
|
// -----------------
|
|
@@ -16540,63 +16451,63 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
16540
16451
|
* @param item base path of item/directory
|
|
16541
16452
|
*/
|
|
16542
16453
|
_remove(directory, item, isDirectory) {
|
|
16543
|
-
const
|
|
16544
|
-
const fullPath = sp2.resolve(
|
|
16545
|
-
isDirectory = isDirectory != null ? isDirectory : this._watched.has(
|
|
16546
|
-
if (!this._throttle("remove",
|
|
16454
|
+
const path30 = sp2.join(directory, item);
|
|
16455
|
+
const fullPath = sp2.resolve(path30);
|
|
16456
|
+
isDirectory = isDirectory != null ? isDirectory : this._watched.has(path30) || this._watched.has(fullPath);
|
|
16457
|
+
if (!this._throttle("remove", path30, 100))
|
|
16547
16458
|
return;
|
|
16548
16459
|
if (!isDirectory && this._watched.size === 1) {
|
|
16549
16460
|
this.add(directory, item, true);
|
|
16550
16461
|
}
|
|
16551
|
-
const wp = this._getWatchedDir(
|
|
16462
|
+
const wp = this._getWatchedDir(path30);
|
|
16552
16463
|
const nestedDirectoryChildren = wp.getChildren();
|
|
16553
|
-
nestedDirectoryChildren.forEach((nested) => this._remove(
|
|
16464
|
+
nestedDirectoryChildren.forEach((nested) => this._remove(path30, nested));
|
|
16554
16465
|
const parent = this._getWatchedDir(directory);
|
|
16555
16466
|
const wasTracked = parent.has(item);
|
|
16556
16467
|
parent.remove(item);
|
|
16557
16468
|
if (this._symlinkPaths.has(fullPath)) {
|
|
16558
16469
|
this._symlinkPaths.delete(fullPath);
|
|
16559
16470
|
}
|
|
16560
|
-
let relPath =
|
|
16471
|
+
let relPath = path30;
|
|
16561
16472
|
if (this.options.cwd)
|
|
16562
|
-
relPath = sp2.relative(this.options.cwd,
|
|
16473
|
+
relPath = sp2.relative(this.options.cwd, path30);
|
|
16563
16474
|
if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
|
|
16564
16475
|
const event = this._pendingWrites.get(relPath).cancelWait();
|
|
16565
16476
|
if (event === EVENTS.ADD)
|
|
16566
16477
|
return;
|
|
16567
16478
|
}
|
|
16568
|
-
this._watched.delete(
|
|
16479
|
+
this._watched.delete(path30);
|
|
16569
16480
|
this._watched.delete(fullPath);
|
|
16570
16481
|
const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
|
|
16571
|
-
if (wasTracked && !this._isIgnored(
|
|
16572
|
-
this._emit(eventName,
|
|
16573
|
-
this._closePath(
|
|
16482
|
+
if (wasTracked && !this._isIgnored(path30))
|
|
16483
|
+
this._emit(eventName, path30);
|
|
16484
|
+
this._closePath(path30);
|
|
16574
16485
|
}
|
|
16575
16486
|
/**
|
|
16576
16487
|
* Closes all watchers for a path
|
|
16577
16488
|
*/
|
|
16578
|
-
_closePath(
|
|
16579
|
-
this._closeFile(
|
|
16580
|
-
const dir = sp2.dirname(
|
|
16581
|
-
this._getWatchedDir(dir).remove(sp2.basename(
|
|
16489
|
+
_closePath(path30) {
|
|
16490
|
+
this._closeFile(path30);
|
|
16491
|
+
const dir = sp2.dirname(path30);
|
|
16492
|
+
this._getWatchedDir(dir).remove(sp2.basename(path30));
|
|
16582
16493
|
}
|
|
16583
16494
|
/**
|
|
16584
16495
|
* Closes only file-specific watchers
|
|
16585
16496
|
*/
|
|
16586
|
-
_closeFile(
|
|
16587
|
-
const closers = this._closers.get(
|
|
16497
|
+
_closeFile(path30) {
|
|
16498
|
+
const closers = this._closers.get(path30);
|
|
16588
16499
|
if (!closers)
|
|
16589
16500
|
return;
|
|
16590
16501
|
closers.forEach((closer) => closer());
|
|
16591
|
-
this._closers.delete(
|
|
16502
|
+
this._closers.delete(path30);
|
|
16592
16503
|
}
|
|
16593
|
-
_addPathCloser(
|
|
16504
|
+
_addPathCloser(path30, closer) {
|
|
16594
16505
|
if (!closer)
|
|
16595
16506
|
return;
|
|
16596
|
-
let list = this._closers.get(
|
|
16507
|
+
let list = this._closers.get(path30);
|
|
16597
16508
|
if (!list) {
|
|
16598
16509
|
list = [];
|
|
16599
|
-
this._closers.set(
|
|
16510
|
+
this._closers.set(path30, list);
|
|
16600
16511
|
}
|
|
16601
16512
|
list.push(closer);
|
|
16602
16513
|
}
|
|
@@ -16626,12 +16537,291 @@ function watch(paths, options = {}) {
|
|
|
16626
16537
|
var chokidar_default = { watch, FSWatcher };
|
|
16627
16538
|
|
|
16628
16539
|
// src/watcher/file-watcher.ts
|
|
16540
|
+
import * as path23 from "path";
|
|
16541
|
+
|
|
16542
|
+
// src/watcher/native-recursive-watcher.ts
|
|
16543
|
+
import { watch as watch2 } from "fs";
|
|
16629
16544
|
import * as path21 from "path";
|
|
16545
|
+
var NativeRecursiveWatcher = class {
|
|
16546
|
+
constructor(root, onChange, options = {}) {
|
|
16547
|
+
this.root = root;
|
|
16548
|
+
this.onChange = onChange;
|
|
16549
|
+
this.watchFactory = options.watchFactory ?? this.defaultWatchFactory;
|
|
16550
|
+
this.onError = options.onError;
|
|
16551
|
+
}
|
|
16552
|
+
root;
|
|
16553
|
+
onChange;
|
|
16554
|
+
watcher = null;
|
|
16555
|
+
listenerToken = 0;
|
|
16556
|
+
watchFactory;
|
|
16557
|
+
onError;
|
|
16558
|
+
start() {
|
|
16559
|
+
if (this.watcher) return;
|
|
16560
|
+
const token = ++this.listenerToken;
|
|
16561
|
+
const listener = (_eventType, filename) => {
|
|
16562
|
+
if (this.watcher === null || this.listenerToken !== token) return;
|
|
16563
|
+
const absolutePath = this.toAbsolutePath(filename);
|
|
16564
|
+
const nextResult = this.onChange(absolutePath);
|
|
16565
|
+
if (nextResult instanceof Promise) {
|
|
16566
|
+
void nextResult.catch((error) => {
|
|
16567
|
+
console.error("[codebase-index] Error handling native watcher event:", error);
|
|
16568
|
+
});
|
|
16569
|
+
}
|
|
16570
|
+
};
|
|
16571
|
+
const watcher = this.watchFactory(this.root, listener, {
|
|
16572
|
+
persistent: true,
|
|
16573
|
+
recursive: true
|
|
16574
|
+
});
|
|
16575
|
+
watcher.on?.("error", (error) => {
|
|
16576
|
+
if (this.watcher === watcher && this.listenerToken === token) {
|
|
16577
|
+
this.onError?.(error);
|
|
16578
|
+
}
|
|
16579
|
+
});
|
|
16580
|
+
this.watcher = watcher;
|
|
16581
|
+
}
|
|
16582
|
+
async stop() {
|
|
16583
|
+
const watcher = this.watcher;
|
|
16584
|
+
this.watcher = null;
|
|
16585
|
+
this.listenerToken += 1;
|
|
16586
|
+
if (!watcher) return;
|
|
16587
|
+
await watcher.close();
|
|
16588
|
+
}
|
|
16589
|
+
toAbsolutePath(filename) {
|
|
16590
|
+
if (filename == null) return null;
|
|
16591
|
+
const normalizedFilename = typeof filename === "string" ? filename : filename.toString();
|
|
16592
|
+
const absolutePath = path21.resolve(this.root, normalizedFilename);
|
|
16593
|
+
const relativePath = path21.relative(this.root, absolutePath);
|
|
16594
|
+
const outsideRoot = relativePath === ".." || relativePath.startsWith(`..${path21.sep}`) || path21.isAbsolute(relativePath);
|
|
16595
|
+
return outsideRoot ? null : absolutePath;
|
|
16596
|
+
}
|
|
16597
|
+
defaultWatchFactory = (root, listener, options) => watch2(root, options, listener);
|
|
16598
|
+
};
|
|
16599
|
+
|
|
16600
|
+
// src/watcher/snapshot.ts
|
|
16601
|
+
import * as fsPromises4 from "fs/promises";
|
|
16602
|
+
import * as path22 from "path";
|
|
16603
|
+
async function buildFileSnapshotScan(projectRoot, config, configPaths = []) {
|
|
16604
|
+
const normalizedProjectRoot = path22.resolve(projectRoot);
|
|
16605
|
+
const ignoreFilter = createIgnoreFilter(normalizedProjectRoot);
|
|
16606
|
+
const includePatterns = [...config.include, ...config.additionalInclude ?? []];
|
|
16607
|
+
const maxDepth = config.indexing?.maxDepth ?? -1;
|
|
16608
|
+
const snapshot = /* @__PURE__ */ new Map();
|
|
16609
|
+
const unreadablePrefixes = /* @__PURE__ */ new Set();
|
|
16610
|
+
const includeFile = async (filePath) => {
|
|
16611
|
+
const normalizedPath2 = path22.resolve(filePath);
|
|
16612
|
+
if (!shouldIncludeFile(normalizedPath2, normalizedProjectRoot, includePatterns, config.exclude, ignoreFilter)) return;
|
|
16613
|
+
const stat5 = await readStatIfFile(normalizedPath2, unreadablePrefixes);
|
|
16614
|
+
if (stat5) snapshot.set(normalizedPath2, { size: stat5.size, mtimeMs: stat5.mtimeMs });
|
|
16615
|
+
};
|
|
16616
|
+
const walk = async (directoryPath, depth) => {
|
|
16617
|
+
let entries;
|
|
16618
|
+
try {
|
|
16619
|
+
entries = await fsPromises4.readdir(directoryPath, { withFileTypes: true });
|
|
16620
|
+
} catch (error) {
|
|
16621
|
+
if (isMissingFsError(error)) return;
|
|
16622
|
+
if (isPermissionFsError(error)) {
|
|
16623
|
+
unreadablePrefixes.add(path22.resolve(directoryPath));
|
|
16624
|
+
return;
|
|
16625
|
+
}
|
|
16626
|
+
throw error;
|
|
16627
|
+
}
|
|
16628
|
+
for (const entry of entries) {
|
|
16629
|
+
const fullPath = path22.join(directoryPath, entry.name);
|
|
16630
|
+
const relativePath = path22.relative(normalizedProjectRoot, fullPath);
|
|
16631
|
+
if (entry.isDirectory()) {
|
|
16632
|
+
if (hasFilteredPathSegment(relativePath, path22.sep) || isRestrictedDirectory(relativePath, path22.sep)) continue;
|
|
16633
|
+
if (ignoreFilter.ignores(relativePath)) continue;
|
|
16634
|
+
if (maxDepth === -1 || depth < maxDepth) await walk(fullPath, depth + 1);
|
|
16635
|
+
} else if (entry.isFile()) {
|
|
16636
|
+
await includeFile(fullPath);
|
|
16637
|
+
}
|
|
16638
|
+
}
|
|
16639
|
+
};
|
|
16640
|
+
await walk(normalizedProjectRoot, 0);
|
|
16641
|
+
await includeExplicitConfigPaths(snapshot, unreadablePrefixes, configPaths);
|
|
16642
|
+
return { entries: snapshot, unreadablePrefixes };
|
|
16643
|
+
}
|
|
16644
|
+
async function buildFileSnapshotForPathScan(projectRoot, config, configPaths, targetPath) {
|
|
16645
|
+
const normalizedProjectRoot = path22.resolve(projectRoot);
|
|
16646
|
+
const normalizedTargetPath = path22.resolve(targetPath);
|
|
16647
|
+
if (!isWithinPath(normalizedProjectRoot, normalizedTargetPath)) {
|
|
16648
|
+
return { entries: /* @__PURE__ */ new Map(), unreadablePrefixes: /* @__PURE__ */ new Set() };
|
|
16649
|
+
}
|
|
16650
|
+
const ignoreFilter = createIgnoreFilter(normalizedProjectRoot);
|
|
16651
|
+
const includePatterns = [...config.include, ...config.additionalInclude ?? []];
|
|
16652
|
+
const maxDepth = config.indexing?.maxDepth ?? -1;
|
|
16653
|
+
const explicitConfigPaths = new Set(configPaths.map((configPath) => path22.resolve(configPath)));
|
|
16654
|
+
const snapshot = /* @__PURE__ */ new Map();
|
|
16655
|
+
const unreadablePrefixes = /* @__PURE__ */ new Set();
|
|
16656
|
+
const includeFile = async (filePath) => {
|
|
16657
|
+
const normalizedPath2 = path22.resolve(filePath);
|
|
16658
|
+
if (!explicitConfigPaths.has(normalizedPath2) && !shouldIncludeFile(
|
|
16659
|
+
normalizedPath2,
|
|
16660
|
+
normalizedProjectRoot,
|
|
16661
|
+
includePatterns,
|
|
16662
|
+
config.exclude,
|
|
16663
|
+
ignoreFilter
|
|
16664
|
+
)) return;
|
|
16665
|
+
const stat5 = await readStatIfFile(normalizedPath2, unreadablePrefixes);
|
|
16666
|
+
if (stat5) snapshot.set(normalizedPath2, { size: stat5.size, mtimeMs: stat5.mtimeMs });
|
|
16667
|
+
};
|
|
16668
|
+
const walk = async (directoryPath, depth) => {
|
|
16669
|
+
let entries;
|
|
16670
|
+
try {
|
|
16671
|
+
entries = await fsPromises4.readdir(directoryPath, { withFileTypes: true });
|
|
16672
|
+
} catch (error) {
|
|
16673
|
+
if (isMissingFsError(error)) return;
|
|
16674
|
+
if (isPermissionFsError(error)) {
|
|
16675
|
+
unreadablePrefixes.add(path22.resolve(directoryPath));
|
|
16676
|
+
return;
|
|
16677
|
+
}
|
|
16678
|
+
throw error;
|
|
16679
|
+
}
|
|
16680
|
+
for (const entry of entries) {
|
|
16681
|
+
const fullPath = path22.join(directoryPath, entry.name);
|
|
16682
|
+
const relativePath = path22.relative(normalizedProjectRoot, fullPath);
|
|
16683
|
+
if (entry.isDirectory()) {
|
|
16684
|
+
if (hasFilteredPathSegment(relativePath, path22.sep) || isRestrictedDirectory(relativePath, path22.sep)) continue;
|
|
16685
|
+
if (ignoreFilter.ignores(relativePath)) continue;
|
|
16686
|
+
if (maxDepth === -1 || depth < maxDepth) await walk(fullPath, depth + 1);
|
|
16687
|
+
} else if (entry.isFile()) {
|
|
16688
|
+
await includeFile(fullPath);
|
|
16689
|
+
}
|
|
16690
|
+
}
|
|
16691
|
+
};
|
|
16692
|
+
const targetStat = await readStatIfFile(normalizedTargetPath, unreadablePrefixes);
|
|
16693
|
+
if (targetStat) await includeFile(normalizedTargetPath);
|
|
16694
|
+
else await walk(normalizedTargetPath, 0);
|
|
16695
|
+
await includeExplicitConfigPathsInPath(snapshot, unreadablePrefixes, configPaths, normalizedTargetPath);
|
|
16696
|
+
return { entries: snapshot, unreadablePrefixes };
|
|
16697
|
+
}
|
|
16698
|
+
function completeFileSnapshot(previous, scan) {
|
|
16699
|
+
const completed = new Map(scan.entries);
|
|
16700
|
+
for (const unreadablePrefix of scan.unreadablePrefixes) {
|
|
16701
|
+
for (const [entryPath, entry] of previous) {
|
|
16702
|
+
if (isWithinPath(unreadablePrefix, entryPath) && !completed.has(entryPath)) completed.set(entryPath, entry);
|
|
16703
|
+
}
|
|
16704
|
+
}
|
|
16705
|
+
return completed;
|
|
16706
|
+
}
|
|
16707
|
+
async function includeExplicitConfigPaths(snapshot, unreadablePrefixes, configPaths) {
|
|
16708
|
+
for (const configPath of [...new Set(configPaths.map((value) => path22.resolve(value)))]) {
|
|
16709
|
+
if (snapshot.has(configPath)) continue;
|
|
16710
|
+
const stat5 = await readStatIfFile(configPath, unreadablePrefixes);
|
|
16711
|
+
if (stat5) snapshot.set(configPath, { size: stat5.size, mtimeMs: stat5.mtimeMs });
|
|
16712
|
+
}
|
|
16713
|
+
}
|
|
16714
|
+
async function includeExplicitConfigPathsInPath(snapshot, unreadablePrefixes, configPaths, targetPath) {
|
|
16715
|
+
await includeExplicitConfigPaths(
|
|
16716
|
+
snapshot,
|
|
16717
|
+
unreadablePrefixes,
|
|
16718
|
+
configPaths.filter((configPath) => isWithinPath(targetPath, path22.resolve(configPath)))
|
|
16719
|
+
);
|
|
16720
|
+
}
|
|
16721
|
+
function isWithinPath(parentPath, childPath) {
|
|
16722
|
+
const relativePath = path22.relative(parentPath, childPath);
|
|
16723
|
+
return relativePath === "" || !relativePath.startsWith(`..${path22.sep}`) && relativePath !== ".." && !path22.isAbsolute(relativePath);
|
|
16724
|
+
}
|
|
16725
|
+
async function readStatIfFile(filePath, unreadablePrefixes) {
|
|
16726
|
+
try {
|
|
16727
|
+
const stat5 = await fsPromises4.stat(filePath);
|
|
16728
|
+
return stat5.isFile() ? stat5 : null;
|
|
16729
|
+
} catch (error) {
|
|
16730
|
+
if (isMissingFsError(error)) return null;
|
|
16731
|
+
if (isPermissionFsError(error)) {
|
|
16732
|
+
unreadablePrefixes.add(path22.resolve(filePath));
|
|
16733
|
+
return null;
|
|
16734
|
+
}
|
|
16735
|
+
throw error;
|
|
16736
|
+
}
|
|
16737
|
+
}
|
|
16738
|
+
function isMissingFsError(error) {
|
|
16739
|
+
return error instanceof Error && ["ENOENT", "ENOTDIR"].includes(error.code ?? "");
|
|
16740
|
+
}
|
|
16741
|
+
function isPermissionFsError(error) {
|
|
16742
|
+
return error instanceof Error && ["EACCES", "EPERM"].includes(error.code ?? "");
|
|
16743
|
+
}
|
|
16744
|
+
var diffTypeOrder = { add: 0, change: 1, unlink: 2 };
|
|
16745
|
+
function diffFileSnapshots(previous, current, forcedChanges = /* @__PURE__ */ new Set()) {
|
|
16746
|
+
const changes = [];
|
|
16747
|
+
for (const [filePath, previousEntry] of previous) {
|
|
16748
|
+
const currentEntry = current.get(filePath);
|
|
16749
|
+
if (!currentEntry) changes.push({ type: "unlink", path: filePath });
|
|
16750
|
+
else if (forcedChanges.has(filePath) || currentEntry.size !== previousEntry.size || currentEntry.mtimeMs !== previousEntry.mtimeMs) {
|
|
16751
|
+
changes.push({ type: "change", path: filePath });
|
|
16752
|
+
}
|
|
16753
|
+
}
|
|
16754
|
+
for (const [filePath] of current) {
|
|
16755
|
+
if (!previous.has(filePath)) changes.push({ type: "add", path: filePath });
|
|
16756
|
+
}
|
|
16757
|
+
return changes.sort((left, right) => left.path.localeCompare(right.path) || diffTypeOrder[left.type] - diffTypeOrder[right.type]);
|
|
16758
|
+
}
|
|
16759
|
+
|
|
16760
|
+
// src/watcher/snapshot-reconciler.ts
|
|
16761
|
+
var FileSnapshotReconciler = class {
|
|
16762
|
+
constructor(projectRoot, config, configPaths) {
|
|
16763
|
+
this.projectRoot = projectRoot;
|
|
16764
|
+
this.config = config;
|
|
16765
|
+
this.configPaths = configPaths;
|
|
16766
|
+
}
|
|
16767
|
+
projectRoot;
|
|
16768
|
+
config;
|
|
16769
|
+
configPaths;
|
|
16770
|
+
snapshot = null;
|
|
16771
|
+
reconciliationTail = Promise.resolve();
|
|
16772
|
+
async initialize() {
|
|
16773
|
+
this.snapshot = (await buildFileSnapshotScan(this.projectRoot, this.config, this.configPaths)).entries;
|
|
16774
|
+
}
|
|
16775
|
+
async reconcile(invalidations = []) {
|
|
16776
|
+
if (this.snapshot === null) {
|
|
16777
|
+
throw new Error("FileSnapshotReconciler is not initialized. Call initialize() before reconcile().");
|
|
16778
|
+
}
|
|
16779
|
+
const reconciliation = this.reconciliationTail.then(async () => {
|
|
16780
|
+
const previousSnapshot = this.snapshot;
|
|
16781
|
+
if (previousSnapshot === null) {
|
|
16782
|
+
throw new Error("FileSnapshotReconciler is not initialized. Call initialize() before reconcile().");
|
|
16783
|
+
}
|
|
16784
|
+
const normalizedInvalidations = invalidations.map((invalidation) => typeof invalidation === "string" || invalidation === null ? { path: invalidation, forceChange: false } : { path: invalidation.path, forceChange: invalidation.forceChange === true });
|
|
16785
|
+
const scopedPaths = normalizedInvalidations.map((invalidation) => invalidation.path).filter((filePath) => filePath !== null);
|
|
16786
|
+
const scan = scopedPaths.length === 0 || scopedPaths.length !== normalizedInvalidations.length ? await buildFileSnapshotScan(this.projectRoot, this.config, this.configPaths) : await this.reconcilePaths(previousSnapshot, scopedPaths);
|
|
16787
|
+
const nextSnapshot = completeFileSnapshot(previousSnapshot, scan);
|
|
16788
|
+
const forcedChanges = new Set(normalizedInvalidations.filter((invalidation) => invalidation.path !== null && invalidation.forceChange).map((invalidation) => invalidation.path));
|
|
16789
|
+
const changes = diffFileSnapshots(previousSnapshot, nextSnapshot, forcedChanges);
|
|
16790
|
+
this.snapshot = nextSnapshot;
|
|
16791
|
+
return changes;
|
|
16792
|
+
});
|
|
16793
|
+
this.reconciliationTail = reconciliation.then(() => void 0, () => void 0);
|
|
16794
|
+
return reconciliation;
|
|
16795
|
+
}
|
|
16796
|
+
async reconcilePaths(previousSnapshot, invalidatedPaths) {
|
|
16797
|
+
const scopes = this.getScopes(invalidatedPaths);
|
|
16798
|
+
const entries = new Map(previousSnapshot);
|
|
16799
|
+
const unreadablePrefixes = /* @__PURE__ */ new Set();
|
|
16800
|
+
for (const scope of scopes) {
|
|
16801
|
+
for (const previousPath of entries.keys()) {
|
|
16802
|
+
if (isWithinPath(scope, previousPath)) entries.delete(previousPath);
|
|
16803
|
+
}
|
|
16804
|
+
const scopedScan = await buildFileSnapshotForPathScan(this.projectRoot, this.config, this.configPaths, scope);
|
|
16805
|
+
for (const [filePath, entry] of scopedScan.entries) entries.set(filePath, entry);
|
|
16806
|
+
for (const unreadablePrefix of scopedScan.unreadablePrefixes) unreadablePrefixes.add(unreadablePrefix);
|
|
16807
|
+
}
|
|
16808
|
+
return { entries, unreadablePrefixes };
|
|
16809
|
+
}
|
|
16810
|
+
getScopes(invalidatedPaths) {
|
|
16811
|
+
const uniquePaths = [...new Set(invalidatedPaths)].sort((left, right) => left.length - right.length);
|
|
16812
|
+
return uniquePaths.filter((candidate, index) => !uniquePaths.slice(0, index).some(
|
|
16813
|
+
(ancestor) => isWithinPath(ancestor, candidate)
|
|
16814
|
+
));
|
|
16815
|
+
}
|
|
16816
|
+
};
|
|
16817
|
+
|
|
16818
|
+
// src/watcher/file-watcher.ts
|
|
16630
16819
|
var FileWatcher = class {
|
|
16631
16820
|
watcher = null;
|
|
16632
16821
|
projectRoot;
|
|
16633
16822
|
config;
|
|
16634
16823
|
configPath;
|
|
16824
|
+
backend;
|
|
16635
16825
|
projectConfigPaths;
|
|
16636
16826
|
pendingChanges = /* @__PURE__ */ new Map();
|
|
16637
16827
|
debounceTimer = null;
|
|
@@ -16641,44 +16831,74 @@ var FileWatcher = class {
|
|
|
16641
16831
|
resolveReady = null;
|
|
16642
16832
|
pollingFallbackAttempted = false;
|
|
16643
16833
|
pendingClose = null;
|
|
16834
|
+
startupReadySignals = 1;
|
|
16835
|
+
nativeWatcher = null;
|
|
16836
|
+
nativeReconciler = null;
|
|
16837
|
+
nativeSetupGeneration = 0;
|
|
16838
|
+
nativeStarting = false;
|
|
16839
|
+
nativeInitializing = false;
|
|
16840
|
+
nativeReconcileTimer = null;
|
|
16841
|
+
nativeInvalidatedPaths = /* @__PURE__ */ new Map();
|
|
16842
|
+
configPathStates = /* @__PURE__ */ new Map();
|
|
16644
16843
|
constructor(projectRoot, config, host, options = {}) {
|
|
16645
16844
|
this.projectRoot = projectRoot;
|
|
16646
16845
|
this.config = config;
|
|
16846
|
+
this.backend = options.backend ?? "auto";
|
|
16647
16847
|
this.configPath = options.configPath;
|
|
16648
16848
|
this.projectConfigPaths = options.configPath ? [options.configPath] : getProjectConfigCandidatePaths(projectRoot, host);
|
|
16649
16849
|
}
|
|
16650
16850
|
start(handler) {
|
|
16651
|
-
if (this.watcher) {
|
|
16851
|
+
if (this.watcher || this.nativeWatcher || this.nativeStarting) {
|
|
16652
16852
|
return;
|
|
16653
16853
|
}
|
|
16654
16854
|
this.onChanges = handler;
|
|
16655
16855
|
this.pollingFallbackAttempted = false;
|
|
16656
16856
|
this.resetReady();
|
|
16857
|
+
if (this.shouldUseNativeWatcher()) {
|
|
16858
|
+
if (this.hasExternalConfigWatchTarget()) {
|
|
16859
|
+
this.setStartupReadySignals(2);
|
|
16860
|
+
this.startExternalConfigWatcher();
|
|
16861
|
+
}
|
|
16862
|
+
this.nativeStarting = true;
|
|
16863
|
+
void this.createNativeWatcher();
|
|
16864
|
+
return;
|
|
16865
|
+
}
|
|
16657
16866
|
this.createWatcher();
|
|
16658
16867
|
}
|
|
16659
16868
|
resetReady() {
|
|
16660
|
-
this.readyPromise = new Promise((
|
|
16661
|
-
this.resolveReady =
|
|
16869
|
+
this.readyPromise = new Promise((resolve17) => {
|
|
16870
|
+
this.resolveReady = resolve17;
|
|
16662
16871
|
});
|
|
16872
|
+
this.startupReadySignals = 1;
|
|
16663
16873
|
}
|
|
16664
|
-
|
|
16665
|
-
|
|
16666
|
-
|
|
16667
|
-
|
|
16668
|
-
|
|
16669
|
-
|
|
16670
|
-
|
|
16671
|
-
|
|
16672
|
-
|
|
16673
|
-
}).map((projectConfigPath) => existsSync13(projectConfigPath) ? projectConfigPath : this.getNearestExistingDirectory(path21.dirname(projectConfigPath)));
|
|
16674
|
-
const uniqueExternalConfigTargets = [...new Set(externalConfigTargets)];
|
|
16675
|
-
if (uniqueExternalConfigTargets.length > 0) {
|
|
16676
|
-
watchTargets = [this.projectRoot, ...uniqueExternalConfigTargets];
|
|
16677
|
-
}
|
|
16874
|
+
setStartupReadySignals(expectedSignals) {
|
|
16875
|
+
if (!this.readyPromise) {
|
|
16876
|
+
return;
|
|
16877
|
+
}
|
|
16878
|
+
this.startupReadySignals = Math.max(0, expectedSignals);
|
|
16879
|
+
}
|
|
16880
|
+
reportStartupReadySignal() {
|
|
16881
|
+
if (!this.readyPromise || !this.resolveReady) {
|
|
16882
|
+
return;
|
|
16678
16883
|
}
|
|
16884
|
+
if (this.startupReadySignals <= 0) {
|
|
16885
|
+
return;
|
|
16886
|
+
}
|
|
16887
|
+
this.startupReadySignals -= 1;
|
|
16888
|
+
if (this.startupReadySignals !== 0) {
|
|
16889
|
+
return;
|
|
16890
|
+
}
|
|
16891
|
+
this.resolveReady();
|
|
16892
|
+
this.resolveReady = null;
|
|
16893
|
+
}
|
|
16894
|
+
createWatcher(watchTargets, usePolling = false, reportsStartupReady = true) {
|
|
16895
|
+
let reportedStartupReady = false;
|
|
16896
|
+
this.configPathStates = this.getConfigPathStates();
|
|
16897
|
+
const ignoreFilter = createIgnoreFilter(this.projectRoot);
|
|
16898
|
+
const resolvedWatchTargets = watchTargets ?? this.getFullChokidarWatchTargets();
|
|
16679
16899
|
const watcherOptions = {
|
|
16680
16900
|
ignored: (filePath) => {
|
|
16681
|
-
const relativePath =
|
|
16901
|
+
const relativePath = path23.relative(this.projectRoot, filePath);
|
|
16682
16902
|
if (!relativePath) return false;
|
|
16683
16903
|
if (this.isProjectConfigPathOrAncestor(relativePath)) {
|
|
16684
16904
|
return false;
|
|
@@ -16686,10 +16906,10 @@ var FileWatcher = class {
|
|
|
16686
16906
|
if (this.isOutsideProjectPath(relativePath)) {
|
|
16687
16907
|
return true;
|
|
16688
16908
|
}
|
|
16689
|
-
if (hasFilteredPathSegment(relativePath,
|
|
16909
|
+
if (hasFilteredPathSegment(relativePath, path23.sep)) {
|
|
16690
16910
|
return true;
|
|
16691
16911
|
}
|
|
16692
|
-
if (isRestrictedDirectory(relativePath,
|
|
16912
|
+
if (isRestrictedDirectory(relativePath, path23.sep)) {
|
|
16693
16913
|
return true;
|
|
16694
16914
|
}
|
|
16695
16915
|
if (ignoreFilter.ignores(relativePath)) {
|
|
@@ -16722,10 +16942,13 @@ var FileWatcher = class {
|
|
|
16722
16942
|
watcher = new FSWatcher(watcherOptions);
|
|
16723
16943
|
}
|
|
16724
16944
|
this.watcher = watcher;
|
|
16725
|
-
watcher.
|
|
16945
|
+
watcher.on("ready", () => {
|
|
16726
16946
|
if (this.watcher !== watcher) return;
|
|
16727
|
-
this.
|
|
16728
|
-
|
|
16947
|
+
this.reconcileConfigPathStates();
|
|
16948
|
+
if (reportsStartupReady) {
|
|
16949
|
+
this.reportStartupReadySignal();
|
|
16950
|
+
reportedStartupReady = true;
|
|
16951
|
+
}
|
|
16729
16952
|
});
|
|
16730
16953
|
watcher.on("error", (error) => {
|
|
16731
16954
|
const err = error instanceof Error ? error : null;
|
|
@@ -16739,10 +16962,13 @@ var FileWatcher = class {
|
|
|
16739
16962
|
console.error("[codebase-index] Failed to close exhausted file watcher:", closeError);
|
|
16740
16963
|
});
|
|
16741
16964
|
if (this.onChanges) {
|
|
16965
|
+
const replacementReportsStartupReady = reportsStartupReady || reportedStartupReady;
|
|
16742
16966
|
if (!this.resolveReady) {
|
|
16743
16967
|
this.resetReady();
|
|
16968
|
+
} else if (reportedStartupReady) {
|
|
16969
|
+
this.startupReadySignals += 1;
|
|
16744
16970
|
}
|
|
16745
|
-
this.createWatcher(true);
|
|
16971
|
+
this.createWatcher(resolvedWatchTargets, true, replacementReportsStartupReady);
|
|
16746
16972
|
} else {
|
|
16747
16973
|
this.watcher = null;
|
|
16748
16974
|
}
|
|
@@ -16753,13 +16979,166 @@ var FileWatcher = class {
|
|
|
16753
16979
|
watcher.on("add", (filePath) => this.handleChange(watcher, "add", filePath));
|
|
16754
16980
|
watcher.on("change", (filePath) => this.handleChange(watcher, "change", filePath));
|
|
16755
16981
|
watcher.on("unlink", (filePath) => this.handleChange(watcher, "unlink", filePath));
|
|
16756
|
-
watcher.add(
|
|
16982
|
+
watcher.add(resolvedWatchTargets);
|
|
16983
|
+
}
|
|
16984
|
+
shouldUseNativeWatcher() {
|
|
16985
|
+
if (this.backend === "chokidar") {
|
|
16986
|
+
return false;
|
|
16987
|
+
}
|
|
16988
|
+
return true;
|
|
16989
|
+
}
|
|
16990
|
+
getFullChokidarWatchTargets() {
|
|
16991
|
+
if (this.configPath) {
|
|
16992
|
+
return [this.projectRoot, this.configPath];
|
|
16993
|
+
}
|
|
16994
|
+
const externalConfigTargets = this.getExternalConfigWatchTargets();
|
|
16995
|
+
if (externalConfigTargets.length === 0) {
|
|
16996
|
+
return this.projectRoot;
|
|
16997
|
+
}
|
|
16998
|
+
return [this.projectRoot, ...externalConfigTargets];
|
|
16999
|
+
}
|
|
17000
|
+
getExternalConfigWatchTargets() {
|
|
17001
|
+
return [...new Set(
|
|
17002
|
+
this.projectConfigPaths.filter((projectConfigPath) => {
|
|
17003
|
+
const relativeConfigPath = path23.relative(this.projectRoot, projectConfigPath);
|
|
17004
|
+
return this.isOutsideProjectPath(relativeConfigPath);
|
|
17005
|
+
}).map((projectConfigPath) => {
|
|
17006
|
+
if (existsSync13(projectConfigPath)) {
|
|
17007
|
+
return projectConfigPath;
|
|
17008
|
+
}
|
|
17009
|
+
return this.getNearestExistingDirectory(path23.dirname(projectConfigPath));
|
|
17010
|
+
})
|
|
17011
|
+
)];
|
|
17012
|
+
}
|
|
17013
|
+
hasExternalConfigWatchTarget() {
|
|
17014
|
+
return this.getExternalConfigWatchTargets().length > 0;
|
|
17015
|
+
}
|
|
17016
|
+
startExternalConfigWatcher(usePolling = false) {
|
|
17017
|
+
const externalTargets = this.getExternalConfigWatchTargets();
|
|
17018
|
+
if (externalTargets.length === 0) {
|
|
17019
|
+
return;
|
|
17020
|
+
}
|
|
17021
|
+
this.createWatcher(externalTargets, usePolling);
|
|
17022
|
+
}
|
|
17023
|
+
async createNativeWatcher() {
|
|
17024
|
+
const generation = ++this.nativeSetupGeneration;
|
|
17025
|
+
const reconciler = new FileSnapshotReconciler(this.projectRoot, this.config, this.projectConfigPaths);
|
|
17026
|
+
const watcher = new NativeRecursiveWatcher(
|
|
17027
|
+
this.projectRoot,
|
|
17028
|
+
(filePath) => this.scheduleNativeReconciliation(generation, filePath),
|
|
17029
|
+
{ onError: (error) => void this.fallbackFromNativeWatcher(generation, error) }
|
|
17030
|
+
);
|
|
17031
|
+
this.nativeReconciler = reconciler;
|
|
17032
|
+
this.nativeWatcher = watcher;
|
|
17033
|
+
this.nativeInitializing = true;
|
|
17034
|
+
try {
|
|
17035
|
+
watcher.start();
|
|
17036
|
+
if (!this.isCurrentNativeSetup(generation)) {
|
|
17037
|
+
await watcher.stop();
|
|
17038
|
+
return;
|
|
17039
|
+
}
|
|
17040
|
+
await reconciler.initialize();
|
|
17041
|
+
if (!this.isCurrentNativeSetup(generation) || this.nativeWatcher !== watcher) {
|
|
17042
|
+
await watcher.stop();
|
|
17043
|
+
return;
|
|
17044
|
+
}
|
|
17045
|
+
this.nativeStarting = false;
|
|
17046
|
+
this.nativeInitializing = false;
|
|
17047
|
+
await this.reconcileNativeWatcherWithPendingInvalidations(generation);
|
|
17048
|
+
this.reportStartupReadySignal();
|
|
17049
|
+
} catch (error) {
|
|
17050
|
+
if (!this.isCurrentNativeSetup(generation)) return;
|
|
17051
|
+
this.nativeInitializing = false;
|
|
17052
|
+
if (this.nativeWatcher) {
|
|
17053
|
+
await this.fallbackFromNativeWatcher(generation, error);
|
|
17054
|
+
return;
|
|
17055
|
+
}
|
|
17056
|
+
this.nativeStarting = false;
|
|
17057
|
+
const externalWatcher = this.watcher;
|
|
17058
|
+
this.watcher = null;
|
|
17059
|
+
this.nativeReconciler = null;
|
|
17060
|
+
await externalWatcher?.close();
|
|
17061
|
+
console.warn("[codebase-index] Native recursive watcher unavailable; using Chokidar fallback.", error);
|
|
17062
|
+
this.setStartupReadySignals(1);
|
|
17063
|
+
this.createWatcher();
|
|
17064
|
+
}
|
|
17065
|
+
}
|
|
17066
|
+
isCurrentNativeSetup(generation) {
|
|
17067
|
+
return this.nativeSetupGeneration === generation && this.onChanges !== null;
|
|
17068
|
+
}
|
|
17069
|
+
scheduleNativeReconciliation(generation, filePath) {
|
|
17070
|
+
if (!this.isCurrentNativeSetup(generation)) return;
|
|
17071
|
+
const requiresFullReconciliation = filePath === path23.join(this.projectRoot, ".gitignore");
|
|
17072
|
+
const invalidatedPath = requiresFullReconciliation ? null : filePath;
|
|
17073
|
+
this.nativeInvalidatedPaths.set(invalidatedPath, invalidatedPath !== null);
|
|
17074
|
+
if (this.nativeReconcileTimer) {
|
|
17075
|
+
clearTimeout(this.nativeReconcileTimer);
|
|
17076
|
+
}
|
|
17077
|
+
this.nativeReconcileTimer = setTimeout(() => {
|
|
17078
|
+
this.nativeReconcileTimer = null;
|
|
17079
|
+
void this.reconcileNativeWatcherFromQueue(generation);
|
|
17080
|
+
}, 100);
|
|
17081
|
+
}
|
|
17082
|
+
reconcileNativeWatcherFromQueue(generation) {
|
|
17083
|
+
if (!this.isCurrentNativeSetup(generation) || this.nativeInitializing) return;
|
|
17084
|
+
const invalidatedPaths = this.popNativeInvalidations();
|
|
17085
|
+
if (invalidatedPaths.length === 0) return;
|
|
17086
|
+
void this.reconcileNativeWatcher(generation, invalidatedPaths);
|
|
17087
|
+
}
|
|
17088
|
+
async reconcileNativeWatcher(generation, invalidatedPaths) {
|
|
17089
|
+
if (!this.isCurrentNativeSetup(generation) || !this.nativeReconciler) return;
|
|
17090
|
+
try {
|
|
17091
|
+
const reconciler = this.nativeReconciler;
|
|
17092
|
+
const changes = await reconciler.reconcile(invalidatedPaths);
|
|
17093
|
+
if (!this.isCurrentNativeSetup(generation) || this.nativeReconciler !== reconciler) return;
|
|
17094
|
+
this.recordChanges(changes);
|
|
17095
|
+
} catch (error) {
|
|
17096
|
+
await this.fallbackFromNativeWatcher(generation, error);
|
|
17097
|
+
}
|
|
17098
|
+
}
|
|
17099
|
+
async reconcileNativeWatcherWithPendingInvalidations(generation) {
|
|
17100
|
+
const invalidatedPaths = this.popNativeInvalidations();
|
|
17101
|
+
if (invalidatedPaths.length === 0) return;
|
|
17102
|
+
await this.reconcileNativeWatcher(generation, invalidatedPaths);
|
|
17103
|
+
}
|
|
17104
|
+
popNativeInvalidations() {
|
|
17105
|
+
if (this.nativeInvalidatedPaths.size === 0) return [];
|
|
17106
|
+
const invalidations = [...this.nativeInvalidatedPaths].map(([invalidatedPath, forceChange]) => ({
|
|
17107
|
+
path: invalidatedPath,
|
|
17108
|
+
forceChange
|
|
17109
|
+
}));
|
|
17110
|
+
this.nativeInvalidatedPaths.clear();
|
|
17111
|
+
return invalidations;
|
|
17112
|
+
}
|
|
17113
|
+
async fallbackFromNativeWatcher(generation, error) {
|
|
17114
|
+
if (!this.isCurrentNativeSetup(generation)) return;
|
|
17115
|
+
const watcher = this.nativeWatcher;
|
|
17116
|
+
const externalWatcher = this.watcher;
|
|
17117
|
+
this.nativeWatcher = null;
|
|
17118
|
+
this.watcher = null;
|
|
17119
|
+
this.nativeReconciler = null;
|
|
17120
|
+
this.nativeStarting = false;
|
|
17121
|
+
this.nativeInitializing = false;
|
|
17122
|
+
this.nativeSetupGeneration += 1;
|
|
17123
|
+
if (this.nativeReconcileTimer) {
|
|
17124
|
+
clearTimeout(this.nativeReconcileTimer);
|
|
17125
|
+
this.nativeReconcileTimer = null;
|
|
17126
|
+
}
|
|
17127
|
+
this.nativeInvalidatedPaths.clear();
|
|
17128
|
+
this.setStartupReadySignals(1);
|
|
17129
|
+
console.warn("[codebase-index] Native recursive watcher failed; using Chokidar fallback.", error);
|
|
17130
|
+
await watcher?.stop();
|
|
17131
|
+
await externalWatcher?.close();
|
|
17132
|
+
if (this.onChanges) {
|
|
17133
|
+
this.createWatcher();
|
|
17134
|
+
}
|
|
16757
17135
|
}
|
|
16758
17136
|
handleChange(watcher, type, filePath) {
|
|
16759
17137
|
if (this.watcher !== watcher) {
|
|
16760
17138
|
return;
|
|
16761
17139
|
}
|
|
16762
17140
|
if (this.isProjectConfigPath(filePath)) {
|
|
17141
|
+
this.updateConfigPathState(filePath);
|
|
16763
17142
|
this.pendingChanges.set(filePath, type);
|
|
16764
17143
|
this.scheduleFlush();
|
|
16765
17144
|
return;
|
|
@@ -16774,27 +17153,33 @@ var FileWatcher = class {
|
|
|
16774
17153
|
)) {
|
|
16775
17154
|
return;
|
|
16776
17155
|
}
|
|
16777
|
-
this.
|
|
17156
|
+
this.recordChanges([{ path: filePath, type }]);
|
|
17157
|
+
}
|
|
17158
|
+
recordChanges(changes) {
|
|
17159
|
+
if (changes.length === 0) return;
|
|
17160
|
+
for (const change of changes) {
|
|
17161
|
+
this.pendingChanges.set(change.path, change.type);
|
|
17162
|
+
}
|
|
16778
17163
|
this.scheduleFlush();
|
|
16779
17164
|
}
|
|
16780
17165
|
isProjectConfigPath(filePath) {
|
|
16781
|
-
const relativePath =
|
|
16782
|
-
const normalizedRelativePath =
|
|
17166
|
+
const relativePath = path23.relative(this.projectRoot, filePath);
|
|
17167
|
+
const normalizedRelativePath = path23.normalize(relativePath);
|
|
16783
17168
|
return this.getProjectConfigRelativePaths().some((configPath) => configPath === normalizedRelativePath);
|
|
16784
17169
|
}
|
|
16785
17170
|
isProjectConfigPathOrAncestor(relativePath) {
|
|
16786
|
-
const normalizedRelativePath =
|
|
17171
|
+
const normalizedRelativePath = path23.normalize(relativePath);
|
|
16787
17172
|
return this.getProjectConfigRelativePaths().some(
|
|
16788
|
-
(configPath) => configPath === normalizedRelativePath || configPath.startsWith(`${normalizedRelativePath}${
|
|
17173
|
+
(configPath) => configPath === normalizedRelativePath || configPath.startsWith(`${normalizedRelativePath}${path23.sep}`)
|
|
16789
17174
|
);
|
|
16790
17175
|
}
|
|
16791
17176
|
isOutsideProjectPath(relativePath) {
|
|
16792
|
-
return relativePath === ".." || relativePath.startsWith(`..${
|
|
17177
|
+
return relativePath === ".." || relativePath.startsWith(`..${path23.sep}`) || path23.isAbsolute(relativePath);
|
|
16793
17178
|
}
|
|
16794
17179
|
getNearestExistingDirectory(directoryPath) {
|
|
16795
17180
|
let candidate = directoryPath;
|
|
16796
17181
|
while (!existsSync13(candidate)) {
|
|
16797
|
-
const parent =
|
|
17182
|
+
const parent = path23.dirname(candidate);
|
|
16798
17183
|
if (parent === candidate) break;
|
|
16799
17184
|
candidate = parent;
|
|
16800
17185
|
}
|
|
@@ -16802,9 +17187,51 @@ var FileWatcher = class {
|
|
|
16802
17187
|
}
|
|
16803
17188
|
getProjectConfigRelativePaths() {
|
|
16804
17189
|
return this.projectConfigPaths.map(
|
|
16805
|
-
(configPath) =>
|
|
17190
|
+
(configPath) => path23.normalize(path23.relative(this.projectRoot, configPath))
|
|
16806
17191
|
);
|
|
16807
17192
|
}
|
|
17193
|
+
getConfigPathStates() {
|
|
17194
|
+
const states = /* @__PURE__ */ new Map();
|
|
17195
|
+
for (const configPath of this.projectConfigPaths) {
|
|
17196
|
+
const state = this.getConfigPathState(configPath);
|
|
17197
|
+
if (state) states.set(configPath, state);
|
|
17198
|
+
}
|
|
17199
|
+
return states;
|
|
17200
|
+
}
|
|
17201
|
+
getConfigPathState(configPath) {
|
|
17202
|
+
try {
|
|
17203
|
+
const stats = statSync6(configPath);
|
|
17204
|
+
return stats.isFile() ? { mtimeMs: stats.mtimeMs, size: stats.size } : void 0;
|
|
17205
|
+
} catch (error) {
|
|
17206
|
+
void error;
|
|
17207
|
+
return void 0;
|
|
17208
|
+
}
|
|
17209
|
+
}
|
|
17210
|
+
updateConfigPathState(configPath) {
|
|
17211
|
+
const state = this.getConfigPathState(configPath);
|
|
17212
|
+
if (state) {
|
|
17213
|
+
this.configPathStates.set(configPath, state);
|
|
17214
|
+
} else {
|
|
17215
|
+
this.configPathStates.delete(configPath);
|
|
17216
|
+
}
|
|
17217
|
+
}
|
|
17218
|
+
reconcileConfigPathStates() {
|
|
17219
|
+
const nextStates = this.getConfigPathStates();
|
|
17220
|
+
const changes = [];
|
|
17221
|
+
for (const configPath of this.projectConfigPaths) {
|
|
17222
|
+
const previous = this.configPathStates.get(configPath);
|
|
17223
|
+
const next = nextStates.get(configPath);
|
|
17224
|
+
if (!previous && next) {
|
|
17225
|
+
changes.push({ path: configPath, type: "add" });
|
|
17226
|
+
} else if (previous && !next) {
|
|
17227
|
+
changes.push({ path: configPath, type: "unlink" });
|
|
17228
|
+
} else if (previous && next && (previous.size !== next.size || previous.mtimeMs !== next.mtimeMs)) {
|
|
17229
|
+
changes.push({ path: configPath, type: "change" });
|
|
17230
|
+
}
|
|
17231
|
+
}
|
|
17232
|
+
this.configPathStates = nextStates;
|
|
17233
|
+
this.recordChanges(changes);
|
|
17234
|
+
}
|
|
16808
17235
|
scheduleFlush() {
|
|
16809
17236
|
if (this.debounceTimer) {
|
|
16810
17237
|
clearTimeout(this.debounceTimer);
|
|
@@ -16818,7 +17245,7 @@ var FileWatcher = class {
|
|
|
16818
17245
|
return;
|
|
16819
17246
|
}
|
|
16820
17247
|
const changes = Array.from(this.pendingChanges.entries()).map(
|
|
16821
|
-
([
|
|
17248
|
+
([path30, type]) => ({ path: path30, type })
|
|
16822
17249
|
);
|
|
16823
17250
|
this.pendingChanges.clear();
|
|
16824
17251
|
try {
|
|
@@ -16832,20 +17259,31 @@ var FileWatcher = class {
|
|
|
16832
17259
|
clearTimeout(this.debounceTimer);
|
|
16833
17260
|
this.debounceTimer = null;
|
|
16834
17261
|
}
|
|
17262
|
+
if (this.nativeReconcileTimer) {
|
|
17263
|
+
clearTimeout(this.nativeReconcileTimer);
|
|
17264
|
+
this.nativeReconcileTimer = null;
|
|
17265
|
+
}
|
|
17266
|
+
this.nativeInvalidatedPaths.clear();
|
|
16835
17267
|
const watcher = this.watcher;
|
|
17268
|
+
const nativeWatcher = this.nativeWatcher;
|
|
16836
17269
|
const pendingClose = this.pendingClose;
|
|
16837
17270
|
const resolveReady = this.resolveReady;
|
|
16838
17271
|
this.watcher = null;
|
|
17272
|
+
this.nativeWatcher = null;
|
|
17273
|
+
this.nativeReconciler = null;
|
|
17274
|
+
this.nativeStarting = false;
|
|
17275
|
+
this.nativeInitializing = false;
|
|
17276
|
+
this.nativeSetupGeneration += 1;
|
|
16839
17277
|
this.pendingClose = null;
|
|
16840
17278
|
this.resolveReady = null;
|
|
16841
17279
|
this.readyPromise = null;
|
|
16842
17280
|
this.pendingChanges.clear();
|
|
16843
17281
|
this.onChanges = null;
|
|
16844
|
-
await Promise.all([watcher?.close(), pendingClose]);
|
|
17282
|
+
await Promise.all([watcher?.close(), nativeWatcher?.stop(), pendingClose]);
|
|
16845
17283
|
resolveReady?.();
|
|
16846
17284
|
}
|
|
16847
17285
|
isRunning() {
|
|
16848
|
-
return this.watcher !== null;
|
|
17286
|
+
return this.watcher !== null || this.nativeWatcher !== null || this.nativeStarting;
|
|
16849
17287
|
}
|
|
16850
17288
|
async waitUntilReady() {
|
|
16851
17289
|
await (this.readyPromise ?? Promise.resolve());
|
|
@@ -16853,7 +17291,7 @@ var FileWatcher = class {
|
|
|
16853
17291
|
};
|
|
16854
17292
|
|
|
16855
17293
|
// src/watcher/git-head-watcher.ts
|
|
16856
|
-
import * as
|
|
17294
|
+
import * as path24 from "path";
|
|
16857
17295
|
var GitHeadWatcher = class {
|
|
16858
17296
|
watcher = null;
|
|
16859
17297
|
projectRoot;
|
|
@@ -16875,13 +17313,13 @@ var GitHeadWatcher = class {
|
|
|
16875
17313
|
this.readyPromise = Promise.resolve();
|
|
16876
17314
|
return;
|
|
16877
17315
|
}
|
|
16878
|
-
this.readyPromise = new Promise((
|
|
16879
|
-
this.resolveReady =
|
|
17316
|
+
this.readyPromise = new Promise((resolve17) => {
|
|
17317
|
+
this.resolveReady = resolve17;
|
|
16880
17318
|
});
|
|
16881
17319
|
this.onBranchChange = handler;
|
|
16882
17320
|
this.currentBranch = getCurrentBranch(this.projectRoot);
|
|
16883
17321
|
const headPath = getHeadPath(this.projectRoot);
|
|
16884
|
-
const refsPath =
|
|
17322
|
+
const refsPath = path24.join(this.projectRoot, ".git", "refs", "heads");
|
|
16885
17323
|
this.watcher = chokidar_default.watch([headPath, refsPath], {
|
|
16886
17324
|
persistent: true,
|
|
16887
17325
|
ignoreInitial: true,
|
|
@@ -17737,7 +18175,7 @@ async function resolveCodebaseContextUnmeasured(projectRoot, host, input) {
|
|
|
17737
18175
|
const directory = input.directory ?? void 0;
|
|
17738
18176
|
const tokenBudget = input.tokenBudget ?? void 0;
|
|
17739
18177
|
if (from && to) {
|
|
17740
|
-
const
|
|
18178
|
+
const path30 = await getCallGraphPath(
|
|
17741
18179
|
projectRoot,
|
|
17742
18180
|
host,
|
|
17743
18181
|
from,
|
|
@@ -17746,25 +18184,25 @@ async function resolveCodebaseContextUnmeasured(projectRoot, host, input) {
|
|
|
17746
18184
|
fromFilePath,
|
|
17747
18185
|
toFilePath
|
|
17748
18186
|
);
|
|
17749
|
-
const pathText = formatCallGraphPathResult(
|
|
17750
|
-
if (
|
|
18187
|
+
const pathText = formatCallGraphPathResult(path30);
|
|
18188
|
+
if (path30.path.length > 0) {
|
|
17751
18189
|
const fitted2 = fitTextToContextBudget(
|
|
17752
18190
|
pathText,
|
|
17753
18191
|
tokenBudget
|
|
17754
18192
|
);
|
|
17755
18193
|
return {
|
|
17756
18194
|
text: fitted2.text,
|
|
17757
|
-
details: fittedDetails("path", fitted2,
|
|
18195
|
+
details: fittedDetails("path", fitted2, path30.path.length)
|
|
17758
18196
|
};
|
|
17759
18197
|
}
|
|
17760
|
-
if (
|
|
18198
|
+
if (path30.from.status !== "resolved" || path30.to.status !== "resolved") {
|
|
17761
18199
|
const fitted2 = fitTextToContextBudget(pathText, tokenBudget);
|
|
17762
18200
|
return {
|
|
17763
18201
|
text: fitted2.text,
|
|
17764
18202
|
details: fittedDetails("path", fitted2, 0)
|
|
17765
18203
|
};
|
|
17766
18204
|
}
|
|
17767
|
-
const resolvedFrom =
|
|
18205
|
+
const resolvedFrom = path30.from;
|
|
17768
18206
|
const { callers } = await getCallGraphData(projectRoot, host, {
|
|
17769
18207
|
name: to,
|
|
17770
18208
|
direction: "callers",
|
|
@@ -17923,7 +18361,7 @@ async function executeCallGraph(projectRoot, host, args) {
|
|
|
17923
18361
|
return { text: formatCallGraphResult(await getCallGraphData(projectRoot, host, args)) };
|
|
17924
18362
|
}
|
|
17925
18363
|
async function executeCallGraphPath(projectRoot, host, args) {
|
|
17926
|
-
const
|
|
18364
|
+
const path30 = await getCallGraphPath(
|
|
17927
18365
|
projectRoot,
|
|
17928
18366
|
host,
|
|
17929
18367
|
args.from,
|
|
@@ -17932,7 +18370,7 @@ async function executeCallGraphPath(projectRoot, host, args) {
|
|
|
17932
18370
|
args.fromFilePath,
|
|
17933
18371
|
args.toFilePath
|
|
17934
18372
|
);
|
|
17935
|
-
return { text: formatCallGraphPathResult(
|
|
18373
|
+
return { text: formatCallGraphPathResult(path30) };
|
|
17936
18374
|
}
|
|
17937
18375
|
async function executeCodeCommunities(projectRoot, host, args) {
|
|
17938
18376
|
const result = await getCodeCommunities(projectRoot, host, args);
|
|
@@ -17942,11 +18380,11 @@ async function executeCodeCommunities(projectRoot, host, args) {
|
|
|
17942
18380
|
// src/adapters/opencode/tools.ts
|
|
17943
18381
|
import { writeFileSync as writeFileSync4 } from "fs";
|
|
17944
18382
|
import * as os7 from "os";
|
|
17945
|
-
import * as
|
|
18383
|
+
import * as path27 from "path";
|
|
17946
18384
|
|
|
17947
18385
|
// src/tools/visualize/activity.ts
|
|
17948
18386
|
import { execFileSync } from "child_process";
|
|
17949
|
-
import * as
|
|
18387
|
+
import * as path25 from "path";
|
|
17950
18388
|
function attachRecentActivity(data, projectRoot) {
|
|
17951
18389
|
const activity = readGitActivity(projectRoot);
|
|
17952
18390
|
const changes = activity.size > 0 ? buildGitChanges(data, activity, projectRoot) : buildGraphChanges(data);
|
|
@@ -18108,7 +18546,7 @@ function normalizePath3(filePath) {
|
|
|
18108
18546
|
return filePath.replace(/\\/g, "/");
|
|
18109
18547
|
}
|
|
18110
18548
|
function toGitRelativePath(projectRoot, filePath) {
|
|
18111
|
-
const relativePath =
|
|
18549
|
+
const relativePath = path25.isAbsolute(filePath) ? path25.relative(projectRoot, filePath) : filePath;
|
|
18112
18550
|
return normalizePath3(relativePath);
|
|
18113
18551
|
}
|
|
18114
18552
|
|
|
@@ -18366,7 +18804,7 @@ render();
|
|
|
18366
18804
|
}
|
|
18367
18805
|
|
|
18368
18806
|
// src/tools/visualize/transform.ts
|
|
18369
|
-
import * as
|
|
18807
|
+
import * as path26 from "path";
|
|
18370
18808
|
|
|
18371
18809
|
// src/tools/visualize/modules.ts
|
|
18372
18810
|
var MAX_MODULES = 18;
|
|
@@ -18499,8 +18937,8 @@ function compactModules(prefixToNodes) {
|
|
|
18499
18937
|
function deriveModules(nodes) {
|
|
18500
18938
|
const initial = /* @__PURE__ */ new Map();
|
|
18501
18939
|
for (const node of nodes) {
|
|
18502
|
-
const
|
|
18503
|
-
const prefix = modulePrefixFromRelativePath(
|
|
18940
|
+
const relative14 = stripToProjectRelative(node.filePath);
|
|
18941
|
+
const prefix = modulePrefixFromRelativePath(relative14);
|
|
18504
18942
|
if (!initial.has(prefix)) initial.set(prefix, []);
|
|
18505
18943
|
initial.get(prefix)?.push(node);
|
|
18506
18944
|
}
|
|
@@ -18626,7 +19064,7 @@ function transformForVisualization(symbols, edges, options = {}) {
|
|
|
18626
19064
|
filePath: s.filePath,
|
|
18627
19065
|
kind: s.kind,
|
|
18628
19066
|
line: s.startLine,
|
|
18629
|
-
directory:
|
|
19067
|
+
directory: path26.dirname(s.filePath),
|
|
18630
19068
|
moduleId: "",
|
|
18631
19069
|
moduleLabel: ""
|
|
18632
19070
|
}));
|
|
@@ -18946,7 +19384,7 @@ var index_visualize = tool({
|
|
|
18946
19384
|
return "No connected symbols found for visualization. Try including orphans with includeOrphans=true, or check that the call graph has resolved edges.";
|
|
18947
19385
|
}
|
|
18948
19386
|
const html = generateVisualizationHtml(vizData);
|
|
18949
|
-
const outputPath =
|
|
19387
|
+
const outputPath = path27.join(os7.tmpdir(), `call-graph-${Date.now()}.html`);
|
|
18950
19388
|
writeFileSync4(outputPath, html, "utf-8");
|
|
18951
19389
|
let result = `Temporal call graph visualization generated: ${outputPath}
|
|
18952
19390
|
|
|
@@ -19053,7 +19491,7 @@ var PI_TOOL_NAMES = [
|
|
|
19053
19491
|
|
|
19054
19492
|
// src/commands/loader.ts
|
|
19055
19493
|
import { existsSync as existsSync14, readdirSync as readdirSync3, readFileSync as readFileSync9 } from "fs";
|
|
19056
|
-
import * as
|
|
19494
|
+
import * as path28 from "path";
|
|
19057
19495
|
function parseFrontmatter(content) {
|
|
19058
19496
|
const frontmatterRegex = /^---\s*\n([\s\S]*?)\n---\s*\n([\s\S]*)$/;
|
|
19059
19497
|
const match = content.match(frontmatterRegex);
|
|
@@ -19079,7 +19517,7 @@ function loadCommandsFromDirectory(commandsDir) {
|
|
|
19079
19517
|
}
|
|
19080
19518
|
const files = readdirSync3(commandsDir).filter((f) => f.endsWith(".md"));
|
|
19081
19519
|
for (const file of files) {
|
|
19082
|
-
const filePath =
|
|
19520
|
+
const filePath = path28.join(commandsDir, file);
|
|
19083
19521
|
let content;
|
|
19084
19522
|
try {
|
|
19085
19523
|
content = readFileSync9(filePath, "utf-8");
|
|
@@ -19088,7 +19526,7 @@ function loadCommandsFromDirectory(commandsDir) {
|
|
|
19088
19526
|
throw new Error(`Failed to load command file ${filePath}: ${message}`);
|
|
19089
19527
|
}
|
|
19090
19528
|
const { frontmatter, body } = parseFrontmatter(content);
|
|
19091
|
-
const name =
|
|
19529
|
+
const name = path28.basename(file, ".md");
|
|
19092
19530
|
const description = frontmatter.description || `Run the ${name} command`;
|
|
19093
19531
|
commands.set(name, {
|
|
19094
19532
|
description,
|
|
@@ -19422,23 +19860,41 @@ var RoutingHintController = class {
|
|
|
19422
19860
|
|
|
19423
19861
|
// src/adapters/opencode.ts
|
|
19424
19862
|
var activeWatchers = /* @__PURE__ */ new Map();
|
|
19425
|
-
|
|
19426
|
-
|
|
19427
|
-
|
|
19428
|
-
existing.
|
|
19429
|
-
|
|
19430
|
-
|
|
19431
|
-
|
|
19432
|
-
|
|
19863
|
+
var watcherReplacementChains = /* @__PURE__ */ new Map();
|
|
19864
|
+
async function replaceActiveWatcher(projectRoot, createNextWatcher) {
|
|
19865
|
+
const chain = (watcherReplacementChains.get(projectRoot) ?? Promise.resolve()).catch(() => void 0).then(async () => {
|
|
19866
|
+
const existing = activeWatchers.get(projectRoot);
|
|
19867
|
+
if (existing) {
|
|
19868
|
+
try {
|
|
19869
|
+
await existing.stop();
|
|
19870
|
+
} catch (error) {
|
|
19871
|
+
console.error("[codebase-index] Failed to stop replaced watcher:", error);
|
|
19872
|
+
throw error;
|
|
19873
|
+
}
|
|
19874
|
+
if (activeWatchers.get(projectRoot) === existing) {
|
|
19875
|
+
activeWatchers.delete(projectRoot);
|
|
19876
|
+
}
|
|
19877
|
+
}
|
|
19878
|
+
if (createNextWatcher) {
|
|
19879
|
+
activeWatchers.set(projectRoot, createNextWatcher());
|
|
19880
|
+
}
|
|
19881
|
+
});
|
|
19882
|
+
watcherReplacementChains.set(projectRoot, chain);
|
|
19883
|
+
try {
|
|
19884
|
+
await chain;
|
|
19885
|
+
} finally {
|
|
19886
|
+
if (watcherReplacementChains.get(projectRoot) === chain) {
|
|
19887
|
+
watcherReplacementChains.delete(projectRoot);
|
|
19888
|
+
}
|
|
19433
19889
|
}
|
|
19434
19890
|
}
|
|
19435
19891
|
function getCommandsDir() {
|
|
19436
19892
|
let currentDir = process.cwd();
|
|
19437
19893
|
if (typeof import.meta !== "undefined" && import.meta.url) {
|
|
19438
|
-
currentDir =
|
|
19894
|
+
currentDir = path29.dirname(fileURLToPath2(import.meta.url));
|
|
19439
19895
|
}
|
|
19440
|
-
const packageRoot =
|
|
19441
|
-
return
|
|
19896
|
+
const packageRoot = path29.basename(currentDir) === "adapters" ? path29.join(currentDir, "..", "..") : path29.join(currentDir, "..");
|
|
19897
|
+
return path29.join(packageRoot, "commands");
|
|
19442
19898
|
}
|
|
19443
19899
|
function appendRoutingHints(output, hints, preferredRole) {
|
|
19444
19900
|
const preferredBucket = preferredRole === "developer" ? output.developer : output.system;
|
|
@@ -19479,9 +19935,12 @@ var plugin = async ({ directory, worktree }) => {
|
|
|
19479
19935
|
startAutoIndex(projectRoot, "opencode", "startup");
|
|
19480
19936
|
}
|
|
19481
19937
|
if (config.indexing.watchFiles && isValidProject) {
|
|
19482
|
-
replaceActiveWatcher(
|
|
19938
|
+
await replaceActiveWatcher(
|
|
19939
|
+
projectRoot,
|
|
19940
|
+
() => createWatcherWithIndexer(getProjectIndexer, projectRoot, config, "opencode")
|
|
19941
|
+
);
|
|
19483
19942
|
} else {
|
|
19484
|
-
replaceActiveWatcher(projectRoot, null);
|
|
19943
|
+
await replaceActiveWatcher(projectRoot, null);
|
|
19485
19944
|
}
|
|
19486
19945
|
return {
|
|
19487
19946
|
tool: {
|