opencode-codebase-index 0.22.4 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/dist/cli.cjs +983 -482
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +984 -483
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +888 -398
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +889 -399
- package/dist/index.js.map +1 -1
- package/dist/pi-extension.cjs +40 -98
- package/dist/pi-extension.cjs.map +1 -1
- package/dist/pi-extension.js +40 -98
- package/dist/pi-extension.js.map +1 -1
- package/native/codebase-index-native.darwin-arm64.node +0 -0
- package/native/codebase-index-native.darwin-x64.node +0 -0
- package/native/codebase-index-native.linux-arm64-gnu.node +0 -0
- package/native/codebase-index-native.linux-x64-gnu.node +0 -0
- package/native/codebase-index-native.win32-x64-msvc.node +0 -0
- package/package.json +3 -1
package/dist/index.cjs
CHANGED
|
@@ -333,7 +333,7 @@ var require_ignore = __commonJS({
|
|
|
333
333
|
// path matching.
|
|
334
334
|
// - check `string` either `MODE_IGNORE` or `MODE_CHECK_IGNORE`
|
|
335
335
|
// @returns {TestResult} true if a file is ignored
|
|
336
|
-
test(
|
|
336
|
+
test(path30, checkUnignored, mode) {
|
|
337
337
|
let ignored = false;
|
|
338
338
|
let unignored = false;
|
|
339
339
|
let matchedRule;
|
|
@@ -342,7 +342,7 @@ var require_ignore = __commonJS({
|
|
|
342
342
|
if (unignored === negative && ignored !== unignored || negative && !ignored && !unignored && !checkUnignored) {
|
|
343
343
|
return;
|
|
344
344
|
}
|
|
345
|
-
const matched = rule[mode].test(
|
|
345
|
+
const matched = rule[mode].test(path30);
|
|
346
346
|
if (!matched) {
|
|
347
347
|
return;
|
|
348
348
|
}
|
|
@@ -363,17 +363,17 @@ var require_ignore = __commonJS({
|
|
|
363
363
|
var throwError = (message, Ctor) => {
|
|
364
364
|
throw new Ctor(message);
|
|
365
365
|
};
|
|
366
|
-
var checkPath = (
|
|
367
|
-
if (!isString(
|
|
366
|
+
var checkPath = (path30, originalPath, doThrow) => {
|
|
367
|
+
if (!isString(path30)) {
|
|
368
368
|
return doThrow(
|
|
369
369
|
`path must be a string, but got \`${originalPath}\``,
|
|
370
370
|
TypeError
|
|
371
371
|
);
|
|
372
372
|
}
|
|
373
|
-
if (!
|
|
373
|
+
if (!path30) {
|
|
374
374
|
return doThrow(`path must not be empty`, TypeError);
|
|
375
375
|
}
|
|
376
|
-
if (checkPath.isNotRelative(
|
|
376
|
+
if (checkPath.isNotRelative(path30)) {
|
|
377
377
|
const r = "`path.relative()`d";
|
|
378
378
|
return doThrow(
|
|
379
379
|
`path should be a ${r} string, but got "${originalPath}"`,
|
|
@@ -382,7 +382,7 @@ var require_ignore = __commonJS({
|
|
|
382
382
|
}
|
|
383
383
|
return true;
|
|
384
384
|
};
|
|
385
|
-
var isNotRelative = (
|
|
385
|
+
var isNotRelative = (path30) => REGEX_TEST_INVALID_PATH.test(path30);
|
|
386
386
|
checkPath.isNotRelative = isNotRelative;
|
|
387
387
|
checkPath.convert = (p) => p;
|
|
388
388
|
var Ignore2 = class {
|
|
@@ -412,19 +412,19 @@ var require_ignore = __commonJS({
|
|
|
412
412
|
}
|
|
413
413
|
// @returns {TestResult}
|
|
414
414
|
_test(originalPath, cache, checkUnignored, slices) {
|
|
415
|
-
const
|
|
415
|
+
const path30 = originalPath && checkPath.convert(originalPath);
|
|
416
416
|
checkPath(
|
|
417
|
-
|
|
417
|
+
path30,
|
|
418
418
|
originalPath,
|
|
419
419
|
this._strictPathCheck ? throwError : RETURN_FALSE
|
|
420
420
|
);
|
|
421
|
-
return this._t(
|
|
421
|
+
return this._t(path30, cache, checkUnignored, slices);
|
|
422
422
|
}
|
|
423
|
-
checkIgnore(
|
|
424
|
-
if (!REGEX_TEST_TRAILING_SLASH.test(
|
|
425
|
-
return this.test(
|
|
423
|
+
checkIgnore(path30) {
|
|
424
|
+
if (!REGEX_TEST_TRAILING_SLASH.test(path30)) {
|
|
425
|
+
return this.test(path30);
|
|
426
426
|
}
|
|
427
|
-
const slices =
|
|
427
|
+
const slices = path30.split(SLASH2).filter(Boolean);
|
|
428
428
|
slices.pop();
|
|
429
429
|
if (slices.length) {
|
|
430
430
|
const parent = this._t(
|
|
@@ -437,18 +437,18 @@ var require_ignore = __commonJS({
|
|
|
437
437
|
return parent;
|
|
438
438
|
}
|
|
439
439
|
}
|
|
440
|
-
return this._rules.test(
|
|
440
|
+
return this._rules.test(path30, false, MODE_CHECK_IGNORE);
|
|
441
441
|
}
|
|
442
|
-
_t(
|
|
443
|
-
if (
|
|
444
|
-
return cache[
|
|
442
|
+
_t(path30, cache, checkUnignored, slices) {
|
|
443
|
+
if (path30 in cache) {
|
|
444
|
+
return cache[path30];
|
|
445
445
|
}
|
|
446
446
|
if (!slices) {
|
|
447
|
-
slices =
|
|
447
|
+
slices = path30.split(SLASH2).filter(Boolean);
|
|
448
448
|
}
|
|
449
449
|
slices.pop();
|
|
450
450
|
if (!slices.length) {
|
|
451
|
-
return cache[
|
|
451
|
+
return cache[path30] = this._rules.test(path30, checkUnignored, MODE_IGNORE);
|
|
452
452
|
}
|
|
453
453
|
const parent = this._t(
|
|
454
454
|
slices.join(SLASH2) + SLASH2,
|
|
@@ -456,29 +456,29 @@ var require_ignore = __commonJS({
|
|
|
456
456
|
checkUnignored,
|
|
457
457
|
slices
|
|
458
458
|
);
|
|
459
|
-
return cache[
|
|
459
|
+
return cache[path30] = parent.ignored ? parent : this._rules.test(path30, checkUnignored, MODE_IGNORE);
|
|
460
460
|
}
|
|
461
|
-
ignores(
|
|
462
|
-
return this._test(
|
|
461
|
+
ignores(path30) {
|
|
462
|
+
return this._test(path30, this._ignoreCache, false).ignored;
|
|
463
463
|
}
|
|
464
464
|
createFilter() {
|
|
465
|
-
return (
|
|
465
|
+
return (path30) => !this.ignores(path30);
|
|
466
466
|
}
|
|
467
467
|
filter(paths) {
|
|
468
468
|
return makeArray(paths).filter(this.createFilter());
|
|
469
469
|
}
|
|
470
470
|
// @returns {TestResult}
|
|
471
|
-
test(
|
|
472
|
-
return this._test(
|
|
471
|
+
test(path30) {
|
|
472
|
+
return this._test(path30, this._testCache, true);
|
|
473
473
|
}
|
|
474
474
|
};
|
|
475
475
|
var factory = (options) => new Ignore2(options);
|
|
476
|
-
var isPathValid = (
|
|
476
|
+
var isPathValid = (path30) => checkPath(path30 && checkPath.convert(path30), path30, RETURN_FALSE);
|
|
477
477
|
var setupWindows = () => {
|
|
478
478
|
const makePosix = (str) => /^\\\\\?\\/.test(str) || /["<>|\u0000-\u001F]+/u.test(str) ? str : str.replace(/\\/g, "/");
|
|
479
479
|
checkPath.convert = makePosix;
|
|
480
480
|
const REGEX_TEST_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i;
|
|
481
|
-
checkPath.isNotRelative = (
|
|
481
|
+
checkPath.isNotRelative = (path30) => REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path30) || isNotRelative(path30);
|
|
482
482
|
};
|
|
483
483
|
if (
|
|
484
484
|
// Detect `process` so that it can run in browsers.
|
|
@@ -663,7 +663,7 @@ __export(index_exports, {
|
|
|
663
663
|
module.exports = __toCommonJS(index_exports);
|
|
664
664
|
|
|
665
665
|
// src/adapters/opencode.ts
|
|
666
|
-
var
|
|
666
|
+
var path29 = __toESM(require("path"), 1);
|
|
667
667
|
var import_url = require("url");
|
|
668
668
|
|
|
669
669
|
// src/config/constants.ts
|
|
@@ -1141,11 +1141,11 @@ function resolveGitDir(repoRoot) {
|
|
|
1141
1141
|
return null;
|
|
1142
1142
|
}
|
|
1143
1143
|
try {
|
|
1144
|
-
const
|
|
1145
|
-
if (
|
|
1144
|
+
const stat5 = (0, import_fs2.statSync)(gitPath);
|
|
1145
|
+
if (stat5.isDirectory()) {
|
|
1146
1146
|
return gitPath;
|
|
1147
1147
|
}
|
|
1148
|
-
if (
|
|
1148
|
+
if (stat5.isFile()) {
|
|
1149
1149
|
const content = (0, import_fs2.readFileSync)(gitPath, "utf-8").trim();
|
|
1150
1150
|
const match = content.match(/^gitdir:\s*(.+)$/);
|
|
1151
1151
|
if (match) {
|
|
@@ -2214,7 +2214,7 @@ function analyzeQueryIntent(query) {
|
|
|
2214
2214
|
}
|
|
2215
2215
|
function isTestPath(filePath) {
|
|
2216
2216
|
const normalized = normalizePath(filePath);
|
|
2217
|
-
return /(?:^|\/)(?:test|tests|__tests__|spec|specs)(?:\/|$)/u.test(normalized) ||
|
|
2217
|
+
return /(?:^|\/)(?:test|tests|__tests__|spec|specs)(?:\/|$)/u.test(normalized) || /(?:\.(?:test|spec)|_(?:test|spec))\.[^/]+$/u.test(normalized) || /(?:^|\/)(?:test|spec)_[^/]+\.[^/]+$/u.test(normalized);
|
|
2218
2218
|
}
|
|
2219
2219
|
function isFixturePath(filePath) {
|
|
2220
2220
|
const normalized = normalizePath(filePath);
|
|
@@ -2589,8 +2589,8 @@ function formatExactSearchHandoff(results) {
|
|
|
2589
2589
|
}
|
|
2590
2590
|
function formatContextEvidence(result, index) {
|
|
2591
2591
|
const symbol = result.name ? ` ${JSON.stringify(compactEvidenceValue(result.name, 80))}` : "";
|
|
2592
|
-
const
|
|
2593
|
-
return `[${index}] ${result.chunkType}${symbol} in ${
|
|
2592
|
+
const path30 = compactEvidenceValue(result.filePath, 120);
|
|
2593
|
+
return `[${index}] ${result.chunkType}${symbol} in ${path30}:${result.startLine}-${result.endLine} (score ${result.score.toFixed(2)})`;
|
|
2594
2594
|
}
|
|
2595
2595
|
function formatContextPack(heading, selected, candidateCount, duplicateCount, limitOmittedCount, budgetOmittedCount, includeExactSearchHandoff) {
|
|
2596
2596
|
const lines = selected.map((result, index) => formatContextEvidence(result, index + 1));
|
|
@@ -3743,8 +3743,8 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
|
|
|
3743
3743
|
if (entry.isDirectory()) {
|
|
3744
3744
|
subdirs.push({ fullPath, relativePath });
|
|
3745
3745
|
} else if (entry.isFile()) {
|
|
3746
|
-
const
|
|
3747
|
-
if (
|
|
3746
|
+
const stat5 = await import_fs6.promises.stat(fullPath);
|
|
3747
|
+
if (stat5.size > maxFileSize) {
|
|
3748
3748
|
skipped.push({ path: relativePath, reason: "too_large" });
|
|
3749
3749
|
continue;
|
|
3750
3750
|
}
|
|
@@ -3762,7 +3762,7 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
|
|
|
3762
3762
|
}
|
|
3763
3763
|
}
|
|
3764
3764
|
if (matched) {
|
|
3765
|
-
filesInDir.push({ path: fullPath, size:
|
|
3765
|
+
filesInDir.push({ path: fullPath, size: stat5.size });
|
|
3766
3766
|
}
|
|
3767
3767
|
}
|
|
3768
3768
|
}
|
|
@@ -3819,8 +3819,8 @@ async function collectFiles(projectRoot, includePatterns, excludePatterns, maxFi
|
|
|
3819
3819
|
}
|
|
3820
3820
|
for (const resolvedKbRoot of normalizedRoots) {
|
|
3821
3821
|
try {
|
|
3822
|
-
const
|
|
3823
|
-
if (!
|
|
3822
|
+
const stat5 = await import_fs6.promises.stat(resolvedKbRoot);
|
|
3823
|
+
if (!stat5.isDirectory()) {
|
|
3824
3824
|
skipped.push({ path: resolvedKbRoot, reason: "excluded" });
|
|
3825
3825
|
continue;
|
|
3826
3826
|
}
|
|
@@ -3854,7 +3854,7 @@ function getErrorMessage(error) {
|
|
|
3854
3854
|
return error instanceof Error ? error.message : String(error);
|
|
3855
3855
|
}
|
|
3856
3856
|
function runCommand(file, args, options) {
|
|
3857
|
-
return new Promise((
|
|
3857
|
+
return new Promise((resolve17, reject) => {
|
|
3858
3858
|
childProcess.execFile(
|
|
3859
3859
|
file,
|
|
3860
3860
|
args,
|
|
@@ -3864,7 +3864,7 @@ function runCommand(file, args, options) {
|
|
|
3864
3864
|
reject(error);
|
|
3865
3865
|
return;
|
|
3866
3866
|
}
|
|
3867
|
-
|
|
3867
|
+
resolve17(stdout);
|
|
3868
3868
|
}
|
|
3869
3869
|
);
|
|
3870
3870
|
});
|
|
@@ -4009,10 +4009,10 @@ function safeFailureMessage(error) {
|
|
|
4009
4009
|
}
|
|
4010
4010
|
function cancellableDelay(delayMs, signal) {
|
|
4011
4011
|
if (signal.aborted) return Promise.reject(new AutoIndexCancelledError());
|
|
4012
|
-
return new Promise((
|
|
4012
|
+
return new Promise((resolve17, reject) => {
|
|
4013
4013
|
const timer = setTimeout(() => {
|
|
4014
4014
|
signal.removeEventListener("abort", onAbort);
|
|
4015
|
-
|
|
4015
|
+
resolve17();
|
|
4016
4016
|
}, delayMs);
|
|
4017
4017
|
timer.unref?.();
|
|
4018
4018
|
const onAbort = () => {
|
|
@@ -4024,15 +4024,15 @@ function cancellableDelay(delayMs, signal) {
|
|
|
4024
4024
|
}
|
|
4025
4025
|
function withTimeout(promise, timeoutMs) {
|
|
4026
4026
|
if (timeoutMs <= 0) return Promise.resolve(void 0);
|
|
4027
|
-
return new Promise((
|
|
4028
|
-
const timer = setTimeout(() =>
|
|
4027
|
+
return new Promise((resolve17) => {
|
|
4028
|
+
const timer = setTimeout(() => resolve17(void 0), timeoutMs);
|
|
4029
4029
|
timer.unref?.();
|
|
4030
4030
|
void promise.then((value) => {
|
|
4031
4031
|
clearTimeout(timer);
|
|
4032
|
-
|
|
4032
|
+
resolve17(value);
|
|
4033
4033
|
}, () => {
|
|
4034
4034
|
clearTimeout(timer);
|
|
4035
|
-
|
|
4035
|
+
resolve17(void 0);
|
|
4036
4036
|
});
|
|
4037
4037
|
});
|
|
4038
4038
|
}
|
|
@@ -4414,17 +4414,17 @@ var AutoIndexCoordinator = class {
|
|
|
4414
4414
|
}
|
|
4415
4415
|
}
|
|
4416
4416
|
waitForBatteryRetry(delayMs) {
|
|
4417
|
-
return new Promise((
|
|
4417
|
+
return new Promise((resolve17) => {
|
|
4418
4418
|
const timer = setTimeout(() => {
|
|
4419
4419
|
if (this.batteryRetryTimer === timer) {
|
|
4420
4420
|
this.batteryRetryTimer = null;
|
|
4421
4421
|
this.resolveBatteryRetry = null;
|
|
4422
4422
|
}
|
|
4423
|
-
|
|
4423
|
+
resolve17();
|
|
4424
4424
|
}, delayMs);
|
|
4425
4425
|
timer.unref?.();
|
|
4426
4426
|
this.batteryRetryTimer = timer;
|
|
4427
|
-
this.resolveBatteryRetry =
|
|
4427
|
+
this.resolveBatteryRetry = resolve17;
|
|
4428
4428
|
});
|
|
4429
4429
|
}
|
|
4430
4430
|
cancelBatteryRetry() {
|
|
@@ -4432,9 +4432,9 @@ var AutoIndexCoordinator = class {
|
|
|
4432
4432
|
clearTimeout(this.batteryRetryTimer);
|
|
4433
4433
|
this.batteryRetryTimer = null;
|
|
4434
4434
|
}
|
|
4435
|
-
const
|
|
4435
|
+
const resolve17 = this.resolveBatteryRetry;
|
|
4436
4436
|
this.resolveBatteryRetry = null;
|
|
4437
|
-
|
|
4437
|
+
resolve17?.();
|
|
4438
4438
|
}
|
|
4439
4439
|
finishBatteryCheck(batteryCheck) {
|
|
4440
4440
|
if (this.batteryCheck !== batteryCheck) return;
|
|
@@ -4639,7 +4639,7 @@ function pTimeout(promise, options) {
|
|
|
4639
4639
|
} = options;
|
|
4640
4640
|
let timer;
|
|
4641
4641
|
let abortHandler;
|
|
4642
|
-
const wrappedPromise = new Promise((
|
|
4642
|
+
const wrappedPromise = new Promise((resolve17, reject) => {
|
|
4643
4643
|
if (typeof milliseconds !== "number" || Math.sign(milliseconds) !== 1) {
|
|
4644
4644
|
throw new TypeError(`Expected \`milliseconds\` to be a positive number, got \`${milliseconds}\``);
|
|
4645
4645
|
}
|
|
@@ -4653,7 +4653,7 @@ function pTimeout(promise, options) {
|
|
|
4653
4653
|
};
|
|
4654
4654
|
signal.addEventListener("abort", abortHandler, { once: true });
|
|
4655
4655
|
}
|
|
4656
|
-
promise.then(
|
|
4656
|
+
promise.then(resolve17, reject);
|
|
4657
4657
|
if (milliseconds === Number.POSITIVE_INFINITY) {
|
|
4658
4658
|
return;
|
|
4659
4659
|
}
|
|
@@ -4661,7 +4661,7 @@ function pTimeout(promise, options) {
|
|
|
4661
4661
|
timer = customTimers.setTimeout.call(void 0, () => {
|
|
4662
4662
|
if (fallback) {
|
|
4663
4663
|
try {
|
|
4664
|
-
|
|
4664
|
+
resolve17(fallback());
|
|
4665
4665
|
} catch (error) {
|
|
4666
4666
|
reject(error);
|
|
4667
4667
|
}
|
|
@@ -4671,7 +4671,7 @@ function pTimeout(promise, options) {
|
|
|
4671
4671
|
promise.cancel();
|
|
4672
4672
|
}
|
|
4673
4673
|
if (message === false) {
|
|
4674
|
-
|
|
4674
|
+
resolve17();
|
|
4675
4675
|
} else if (message instanceof Error) {
|
|
4676
4676
|
reject(message);
|
|
4677
4677
|
} else {
|
|
@@ -5073,7 +5073,7 @@ var PQueue = class extends import_index.default {
|
|
|
5073
5073
|
// Assign unique ID if not provided
|
|
5074
5074
|
id: options.id ?? (this.#idAssigner++).toString()
|
|
5075
5075
|
};
|
|
5076
|
-
return new Promise((
|
|
5076
|
+
return new Promise((resolve17, reject) => {
|
|
5077
5077
|
const taskSymbol = /* @__PURE__ */ Symbol(`task-${options.id}`);
|
|
5078
5078
|
let cleanupQueueAbortHandler = () => void 0;
|
|
5079
5079
|
const run = async () => {
|
|
@@ -5113,7 +5113,7 @@ var PQueue = class extends import_index.default {
|
|
|
5113
5113
|
})]);
|
|
5114
5114
|
}
|
|
5115
5115
|
const result = await operation;
|
|
5116
|
-
|
|
5116
|
+
resolve17(result);
|
|
5117
5117
|
this.emit("completed", result);
|
|
5118
5118
|
} catch (error) {
|
|
5119
5119
|
reject(error);
|
|
@@ -5301,13 +5301,13 @@ var PQueue = class extends import_index.default {
|
|
|
5301
5301
|
});
|
|
5302
5302
|
}
|
|
5303
5303
|
async #onEvent(event, filter) {
|
|
5304
|
-
return new Promise((
|
|
5304
|
+
return new Promise((resolve17) => {
|
|
5305
5305
|
const listener = () => {
|
|
5306
5306
|
if (filter && !filter()) {
|
|
5307
5307
|
return;
|
|
5308
5308
|
}
|
|
5309
5309
|
this.off(event, listener);
|
|
5310
|
-
|
|
5310
|
+
resolve17();
|
|
5311
5311
|
};
|
|
5312
5312
|
this.on(event, listener);
|
|
5313
5313
|
});
|
|
@@ -5593,7 +5593,7 @@ async function onAttemptFailure({ error, attemptNumber, retriesConsumed, startTi
|
|
|
5593
5593
|
const finalDelay = Math.min(delayTime, remainingTime);
|
|
5594
5594
|
options.signal?.throwIfAborted();
|
|
5595
5595
|
if (finalDelay > 0) {
|
|
5596
|
-
await new Promise((
|
|
5596
|
+
await new Promise((resolve17, reject) => {
|
|
5597
5597
|
const onAbort = () => {
|
|
5598
5598
|
clearTimeout(timeoutToken);
|
|
5599
5599
|
options.signal?.removeEventListener("abort", onAbort);
|
|
@@ -5601,7 +5601,7 @@ async function onAttemptFailure({ error, attemptNumber, retriesConsumed, startTi
|
|
|
5601
5601
|
};
|
|
5602
5602
|
const timeoutToken = setTimeout(() => {
|
|
5603
5603
|
options.signal?.removeEventListener("abort", onAbort);
|
|
5604
|
-
|
|
5604
|
+
resolve17();
|
|
5605
5605
|
}, finalDelay);
|
|
5606
5606
|
if (options.unref) {
|
|
5607
5607
|
timeoutToken.unref?.();
|
|
@@ -6407,85 +6407,6 @@ function createEmbeddingProvider(configuredProviderInfo) {
|
|
|
6407
6407
|
}
|
|
6408
6408
|
}
|
|
6409
6409
|
|
|
6410
|
-
// src/rerank/index.ts
|
|
6411
|
-
function createReranker(config) {
|
|
6412
|
-
if (!config.enabled) {
|
|
6413
|
-
return new NoOpReranker();
|
|
6414
|
-
}
|
|
6415
|
-
return new SiliconFlowReranker(config);
|
|
6416
|
-
}
|
|
6417
|
-
var NoOpReranker = class {
|
|
6418
|
-
isAvailable() {
|
|
6419
|
-
return false;
|
|
6420
|
-
}
|
|
6421
|
-
async rerank(_query, documents, _topN) {
|
|
6422
|
-
return {
|
|
6423
|
-
results: documents.map((_, index) => ({ index, relevanceScore: 0 }))
|
|
6424
|
-
};
|
|
6425
|
-
}
|
|
6426
|
-
};
|
|
6427
|
-
var SiliconFlowReranker = class {
|
|
6428
|
-
config;
|
|
6429
|
-
constructor(config) {
|
|
6430
|
-
this.config = config;
|
|
6431
|
-
}
|
|
6432
|
-
isAvailable() {
|
|
6433
|
-
return this.config.enabled && !!this.config.baseUrl && !!this.config.model;
|
|
6434
|
-
}
|
|
6435
|
-
async rerank(query, documents, topN) {
|
|
6436
|
-
if (documents.length === 0) {
|
|
6437
|
-
return { results: [] };
|
|
6438
|
-
}
|
|
6439
|
-
const headers = {
|
|
6440
|
-
"Content-Type": "application/json"
|
|
6441
|
-
};
|
|
6442
|
-
if (this.config.apiKey) {
|
|
6443
|
-
headers["Authorization"] = `Bearer ${this.config.apiKey}`;
|
|
6444
|
-
}
|
|
6445
|
-
const baseUrl = this.config.baseUrl;
|
|
6446
|
-
if (!baseUrl) {
|
|
6447
|
-
throw new Error("Reranker baseUrl is required. Configure reranker.baseUrl in your codebase-index.json.");
|
|
6448
|
-
}
|
|
6449
|
-
const timeoutMs = this.config.timeoutMs ?? 3e4;
|
|
6450
|
-
const controller = new AbortController();
|
|
6451
|
-
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
6452
|
-
try {
|
|
6453
|
-
const response = await fetch(`${baseUrl}/rerank`, {
|
|
6454
|
-
method: "POST",
|
|
6455
|
-
headers,
|
|
6456
|
-
body: JSON.stringify({
|
|
6457
|
-
model: this.config.model,
|
|
6458
|
-
query,
|
|
6459
|
-
documents,
|
|
6460
|
-
top_n: topN ?? this.config.topN ?? 20,
|
|
6461
|
-
return_documents: false
|
|
6462
|
-
}),
|
|
6463
|
-
signal: controller.signal
|
|
6464
|
-
});
|
|
6465
|
-
clearTimeout(timeout);
|
|
6466
|
-
if (!response.ok) {
|
|
6467
|
-
const errorText = await response.text();
|
|
6468
|
-
throw new Error(`Rerank API error: ${response.status} - ${errorText}`);
|
|
6469
|
-
}
|
|
6470
|
-
const data = await response.json();
|
|
6471
|
-
return {
|
|
6472
|
-
results: data.results.map((r) => ({
|
|
6473
|
-
index: r.index,
|
|
6474
|
-
relevanceScore: r.relevance_score,
|
|
6475
|
-
document: r.document?.text
|
|
6476
|
-
})),
|
|
6477
|
-
tokensUsed: data.meta?.tokens?.input_tokens
|
|
6478
|
-
};
|
|
6479
|
-
} catch (error) {
|
|
6480
|
-
clearTimeout(timeout);
|
|
6481
|
-
if (error instanceof Error && error.name === "AbortError") {
|
|
6482
|
-
throw new Error(`Rerank API request timed out after ${timeoutMs}ms`);
|
|
6483
|
-
}
|
|
6484
|
-
throw error;
|
|
6485
|
-
}
|
|
6486
|
-
}
|
|
6487
|
-
};
|
|
6488
|
-
|
|
6489
6410
|
// src/utils/cost.ts
|
|
6490
6411
|
function estimateChunksFromFiles(files) {
|
|
6491
6412
|
let totalChunks = 0;
|
|
@@ -8046,8 +7967,8 @@ async function isWorktreeRegistered(projectRoot, worktreePath) {
|
|
|
8046
7967
|
return false;
|
|
8047
7968
|
}
|
|
8048
7969
|
function isPathWithinRoot(filePath, rootPath) {
|
|
8049
|
-
const
|
|
8050
|
-
return
|
|
7970
|
+
const relative14 = path15.relative(path15.resolve(rootPath), path15.resolve(filePath));
|
|
7971
|
+
return relative14 === "" || !relative14.startsWith(`..${path15.sep}`) && relative14 !== ".." && !path15.isAbsolute(relative14);
|
|
8051
7972
|
}
|
|
8052
7973
|
async function pruneExactMissingWorktreeRegistration(projectRoot, worktreePath) {
|
|
8053
7974
|
if (await pathExists(worktreePath)) return false;
|
|
@@ -8424,11 +8345,11 @@ function normalizeFiles(rawFiles, projectRoot) {
|
|
|
8424
8345
|
for (const raw of rawFiles) {
|
|
8425
8346
|
if (raw.length === 0) continue;
|
|
8426
8347
|
const absolute = path16.resolve(root, raw);
|
|
8427
|
-
const
|
|
8428
|
-
if (path16.isAbsolute(raw) ||
|
|
8348
|
+
const relative14 = path16.relative(root, absolute);
|
|
8349
|
+
if (path16.isAbsolute(raw) || relative14 === ".." || relative14.startsWith(`..${path16.sep}`) || path16.isAbsolute(relative14)) {
|
|
8429
8350
|
throw new Error(`Changed file escapes the project root: ${JSON.stringify(raw)}`);
|
|
8430
8351
|
}
|
|
8431
|
-
const cleaned =
|
|
8352
|
+
const cleaned = relative14.startsWith(`.${path16.sep}`) ? relative14.slice(2) : relative14;
|
|
8432
8353
|
if (!seen.has(cleaned)) {
|
|
8433
8354
|
seen.add(cleaned);
|
|
8434
8355
|
result.push(cleaned);
|
|
@@ -8660,7 +8581,8 @@ function rankHybridResults(query, semanticResults, keywordResults, options) {
|
|
|
8660
8581
|
return cached;
|
|
8661
8582
|
}
|
|
8662
8583
|
}
|
|
8663
|
-
const
|
|
8584
|
+
const overfetchFactor = prioritizeSourcePaths ? 12 : 4;
|
|
8585
|
+
const overfetchLimit = Math.max(options.limit * overfetchFactor, options.limit);
|
|
8664
8586
|
const fused = options.fusionStrategy === "rrf" ? fuseResultsRrf(semanticResults, keywordResults, options.rrfK, overfetchLimit) : fuseResultsWeighted(semanticResults, keywordResults, options.hybridWeight, overfetchLimit);
|
|
8665
8587
|
const rerankPoolLimit = Math.max(overfetchLimit, options.rerankTopN * 3, options.limit * 6);
|
|
8666
8588
|
const rerankPool = fused.slice(0, rerankPoolLimit);
|
|
@@ -9046,6 +8968,29 @@ function extractPrimaryIdentifierQueryHint(query) {
|
|
|
9046
8968
|
const best = codeTerms.find((term) => term.length >= 6);
|
|
9047
8969
|
return best ?? null;
|
|
9048
8970
|
}
|
|
8971
|
+
function pathSegmentsForAffinityMatch(filePath) {
|
|
8972
|
+
const normalizedPath2 = normalizeRankingText(filePath).replace(/\\/g, "/");
|
|
8973
|
+
const segments = normalizedPath2.split("/").filter((segment) => segment.length > 0);
|
|
8974
|
+
if (segments.length === 0) {
|
|
8975
|
+
return [];
|
|
8976
|
+
}
|
|
8977
|
+
const basename9 = segments[segments.length - 1] ?? "";
|
|
8978
|
+
const basenameWithoutExt = basename9.replace(/\.[^/.]+$/u, "");
|
|
8979
|
+
const normalizedSegments = segments.map((segment) => segment.toLowerCase());
|
|
8980
|
+
return Array.from(/* @__PURE__ */ new Set([
|
|
8981
|
+
...normalizedSegments,
|
|
8982
|
+
basenameWithoutExt.toLowerCase()
|
|
8983
|
+
]));
|
|
8984
|
+
}
|
|
8985
|
+
function hasModuleAffinity(filePath, exactIdentifierVariants) {
|
|
8986
|
+
const haystack = pathSegmentsForAffinityMatch(filePath);
|
|
8987
|
+
return exactIdentifierVariants.some((variant) => {
|
|
8988
|
+
if (!variant || variant.length < 2) {
|
|
8989
|
+
return false;
|
|
8990
|
+
}
|
|
8991
|
+
return haystack.includes(variant);
|
|
8992
|
+
});
|
|
8993
|
+
}
|
|
9049
8994
|
var FILE_PATH_HINT_EXTENSIONS = [
|
|
9050
8995
|
"ts",
|
|
9051
8996
|
"tsx",
|
|
@@ -9121,10 +9066,13 @@ function buildDeterministicIdentifierPass(query, candidates, limit, prioritizeSo
|
|
|
9121
9066
|
).map((candidate) => {
|
|
9122
9067
|
const nameLower = (candidate.metadata.name ?? "").toLowerCase();
|
|
9123
9068
|
const pathLower = candidate.metadata.filePath.toLowerCase();
|
|
9124
|
-
|
|
9125
|
-
const
|
|
9069
|
+
const exactIdentifierVariants = primaryVariants.filter((value) => value.length >= 2);
|
|
9070
|
+
const exactMatch = exactIdentifierVariants.some(
|
|
9126
9071
|
(variant) => nameLower === variant || nameLower.replace(/[^a-z0-9]/g, "") === variant.replace(/[^a-z0-9]/g, "")
|
|
9127
9072
|
);
|
|
9073
|
+
let maxMatch = 0;
|
|
9074
|
+
const nameMatchesPrimary = exactMatch;
|
|
9075
|
+
const pathAffinity = exactMatch ? hasModuleAffinity(candidate.metadata.filePath, exactIdentifierVariants) : false;
|
|
9128
9076
|
const pathMatchesFileHint = filePathHint ? pathMatchesHint(candidate.metadata.filePath, filePathHint) : false;
|
|
9129
9077
|
for (const hint of hints) {
|
|
9130
9078
|
const variants = normalizeIdentifierVariants(hint);
|
|
@@ -9145,12 +9093,17 @@ function buildDeterministicIdentifierPass(query, candidates, limit, prioritizeSo
|
|
|
9145
9093
|
candidate,
|
|
9146
9094
|
maxMatch,
|
|
9147
9095
|
pathMatchesFileHint,
|
|
9148
|
-
nameMatchesPrimary
|
|
9096
|
+
nameMatchesPrimary,
|
|
9097
|
+
pathAffinity
|
|
9149
9098
|
};
|
|
9150
9099
|
}).filter((entry) => entry.maxMatch >= 0.7).sort((a, b) => {
|
|
9151
9100
|
const aAnchored = a.pathMatchesFileHint && a.nameMatchesPrimary ? 1 : 0;
|
|
9152
9101
|
const bAnchored = b.pathMatchesFileHint && b.nameMatchesPrimary ? 1 : 0;
|
|
9153
9102
|
if (aAnchored !== bAnchored) return bAnchored - aAnchored;
|
|
9103
|
+
if (a.nameMatchesPrimary !== b.nameMatchesPrimary) {
|
|
9104
|
+
return b.nameMatchesPrimary ? 1 : -1;
|
|
9105
|
+
}
|
|
9106
|
+
if (a.pathAffinity !== b.pathAffinity) return b.pathAffinity ? 1 : -1;
|
|
9154
9107
|
if (b.maxMatch !== a.maxMatch) return b.maxMatch - a.maxMatch;
|
|
9155
9108
|
if (b.candidate.score !== a.candidate.score) return b.candidate.score - a.candidate.score;
|
|
9156
9109
|
return a.candidate.id.localeCompare(b.candidate.id);
|
|
@@ -10140,7 +10093,6 @@ var Indexer = class _Indexer {
|
|
|
10140
10093
|
database = null;
|
|
10141
10094
|
provider = null;
|
|
10142
10095
|
configuredProviderInfo = null;
|
|
10143
|
-
reranker = null;
|
|
10144
10096
|
fileHashCache = /* @__PURE__ */ new Map();
|
|
10145
10097
|
fileHashCachePath = "";
|
|
10146
10098
|
failedBatchesPath = "";
|
|
@@ -10300,7 +10252,6 @@ var Indexer = class _Indexer {
|
|
|
10300
10252
|
this.database = null;
|
|
10301
10253
|
this.provider = null;
|
|
10302
10254
|
this.configuredProviderInfo = null;
|
|
10303
|
-
this.reranker = null;
|
|
10304
10255
|
this.indexCompatibility = null;
|
|
10305
10256
|
this.initializationMode = "none";
|
|
10306
10257
|
this.readIssues = [];
|
|
@@ -11030,7 +10981,7 @@ var Indexer = class _Indexer {
|
|
|
11030
10981
|
await options.queue.onSizeLessThan(Math.max(1, options.providerRateLimits.concurrency));
|
|
11031
10982
|
const task = options.queue.add(async () => {
|
|
11032
10983
|
if (options.rateLimitState.backoffMs > 0) {
|
|
11033
|
-
await new Promise((
|
|
10984
|
+
await new Promise((resolve17) => setTimeout(resolve17, options.rateLimitState.backoffMs));
|
|
11034
10985
|
}
|
|
11035
10986
|
try {
|
|
11036
10987
|
const embeddingResult = await pRetry(
|
|
@@ -11597,15 +11548,6 @@ var Indexer = class _Indexer {
|
|
|
11597
11548
|
rerankerEnabled: this.config.reranker?.enabled ?? false
|
|
11598
11549
|
});
|
|
11599
11550
|
this.provider = createEmbeddingProvider(this.configuredProviderInfo);
|
|
11600
|
-
if (this.config.reranker?.enabled) {
|
|
11601
|
-
this.reranker = createReranker(this.config.reranker);
|
|
11602
|
-
if (this.reranker.isAvailable()) {
|
|
11603
|
-
this.logger.info("Reranker initialized", {
|
|
11604
|
-
model: this.config.reranker.model,
|
|
11605
|
-
baseUrl: this.config.reranker.baseUrl
|
|
11606
|
-
});
|
|
11607
|
-
}
|
|
11608
|
-
}
|
|
11609
11551
|
const dimensions = this.configuredProviderInfo.modelInfo.dimensions;
|
|
11610
11552
|
const storePath = path19.join(this.indexPath, "vectors");
|
|
11611
11553
|
const vectorMetadataPath = `${storePath}.meta.json`;
|
|
@@ -13010,6 +12952,7 @@ var Indexer = class _Indexer {
|
|
|
13010
12952
|
const filterByBranch = options?.filterByBranch ?? true;
|
|
13011
12953
|
const sourceIntent = options?.definitionIntent === true || classifyQueryIntentRaw(query) === "source";
|
|
13012
12954
|
const identifierHints = extractIdentifierHints(query);
|
|
12955
|
+
const candidateLimit = maxResults * (sourceIntent ? 12 : 4);
|
|
13013
12956
|
this.logger.search("debug", "Starting search", {
|
|
13014
12957
|
query,
|
|
13015
12958
|
maxResults,
|
|
@@ -13046,7 +12989,7 @@ var Indexer = class _Indexer {
|
|
|
13046
12989
|
const semanticCandidates = embedding ? this.searchSemanticCandidates(
|
|
13047
12990
|
store,
|
|
13048
12991
|
embedding,
|
|
13049
|
-
|
|
12992
|
+
candidateLimit,
|
|
13050
12993
|
branchChunkIds,
|
|
13051
12994
|
shouldPrefilterByBranch
|
|
13052
12995
|
) : [];
|
|
@@ -13054,7 +12997,7 @@ var Indexer = class _Indexer {
|
|
|
13054
12997
|
const keywordStartTime = import_perf_hooks.performance.now();
|
|
13055
12998
|
const keywordCandidates = await this.keywordSearch(
|
|
13056
12999
|
query,
|
|
13057
|
-
|
|
13000
|
+
candidateLimit,
|
|
13058
13001
|
store,
|
|
13059
13002
|
invertedIndex,
|
|
13060
13003
|
branchChunkIds,
|
|
@@ -13812,9 +13755,9 @@ var Indexer = class _Indexer {
|
|
|
13812
13755
|
this.requireReadableComponents(readIssues, "database");
|
|
13813
13756
|
let shortest = [];
|
|
13814
13757
|
for (const branchKey of this.getBranchCatalogKeys()) {
|
|
13815
|
-
const
|
|
13816
|
-
if (
|
|
13817
|
-
shortest =
|
|
13758
|
+
const path30 = database.findShortestPath(fromName, toName, branchKey, maxDepth);
|
|
13759
|
+
if (path30.length > 0 && (shortest.length === 0 || path30.length < shortest.length)) {
|
|
13760
|
+
shortest = path30;
|
|
13818
13761
|
}
|
|
13819
13762
|
}
|
|
13820
13763
|
return shortest.map((hop) => this.resolveFilePathRecord(hop));
|
|
@@ -13862,13 +13805,13 @@ var Indexer = class _Indexer {
|
|
|
13862
13805
|
}
|
|
13863
13806
|
}
|
|
13864
13807
|
if (!found) continue;
|
|
13865
|
-
const
|
|
13808
|
+
const path30 = [];
|
|
13866
13809
|
let currentSymbolId = toSymbolId;
|
|
13867
13810
|
while (true) {
|
|
13868
13811
|
const symbol = symbolsById.get(currentSymbolId);
|
|
13869
13812
|
if (!symbol) break;
|
|
13870
13813
|
const parent = parentBySymbolId.get(currentSymbolId);
|
|
13871
|
-
|
|
13814
|
+
path30.push({
|
|
13872
13815
|
symbolId: symbol.id,
|
|
13873
13816
|
symbolName: symbol.name,
|
|
13874
13817
|
filePath: symbol.filePath,
|
|
@@ -13878,9 +13821,9 @@ var Indexer = class _Indexer {
|
|
|
13878
13821
|
if (!parent) break;
|
|
13879
13822
|
currentSymbolId = parent.parentId;
|
|
13880
13823
|
}
|
|
13881
|
-
|
|
13882
|
-
if (
|
|
13883
|
-
shortest =
|
|
13824
|
+
path30.reverse();
|
|
13825
|
+
if (path30.length > 0 && (shortest.length === 0 || path30.length < shortest.length)) {
|
|
13826
|
+
shortest = path30;
|
|
13884
13827
|
}
|
|
13885
13828
|
}
|
|
13886
13829
|
return shortest.map((hop) => this.resolveFilePathRecord(hop));
|
|
@@ -14216,7 +14159,6 @@ var Indexer = class _Indexer {
|
|
|
14216
14159
|
this.store = null;
|
|
14217
14160
|
this.invertedIndex = null;
|
|
14218
14161
|
this.provider = null;
|
|
14219
|
-
this.reranker = null;
|
|
14220
14162
|
this.configuredProviderInfo = null;
|
|
14221
14163
|
this.indexCompatibility = null;
|
|
14222
14164
|
this.initializationMode = "none";
|
|
@@ -14541,12 +14483,12 @@ async function getCallGraphPath(projectRoot, host, from, to, maxDepth, fromFileP
|
|
|
14541
14483
|
if (fromResolution.status !== "resolved" || toResolution.status !== "resolved") {
|
|
14542
14484
|
return { from: fromResolution, to: toResolution, path: [] };
|
|
14543
14485
|
}
|
|
14544
|
-
const
|
|
14486
|
+
const path30 = await indexer.findCallPathBySymbolIds(
|
|
14545
14487
|
fromResolution.symbolId,
|
|
14546
14488
|
toResolution.symbolId,
|
|
14547
14489
|
maxDepth
|
|
14548
14490
|
);
|
|
14549
|
-
return { from: fromResolution, to: toResolution, path:
|
|
14491
|
+
return { from: fromResolution, to: toResolution, path: path30 };
|
|
14550
14492
|
}
|
|
14551
14493
|
async function runIndexCodebase(projectRoot, host, args, onProgress) {
|
|
14552
14494
|
const root = getProjectRoot(projectRoot, host);
|
|
@@ -14772,8 +14714,8 @@ function addKnowledgeBase(projectRoot, host, knowledgeBasePath) {
|
|
|
14772
14714
|
}
|
|
14773
14715
|
}
|
|
14774
14716
|
try {
|
|
14775
|
-
const
|
|
14776
|
-
if (!
|
|
14717
|
+
const stat5 = (0, import_fs13.statSync)(normalizedPath2);
|
|
14718
|
+
if (!stat5.isDirectory()) {
|
|
14777
14719
|
return `Error: Path is not a directory: ${normalizedPath2}`;
|
|
14778
14720
|
}
|
|
14779
14721
|
} catch (error) {
|
|
@@ -14821,8 +14763,8 @@ function listKnowledgeBases(projectRoot, host) {
|
|
|
14821
14763
|
`;
|
|
14822
14764
|
if (exists) {
|
|
14823
14765
|
try {
|
|
14824
|
-
const
|
|
14825
|
-
result += ` Type: ${
|
|
14766
|
+
const stat5 = (0, import_fs13.statSync)(resolvedPath);
|
|
14767
|
+
result += ` Type: ${stat5.isDirectory() ? "Directory" : "File"}
|
|
14826
14768
|
`;
|
|
14827
14769
|
} catch {
|
|
14828
14770
|
}
|
|
@@ -14955,7 +14897,7 @@ var ReaddirpStream = class extends import_node_stream.Readable {
|
|
|
14955
14897
|
this._directoryFilter = normalizeFilter(opts.directoryFilter);
|
|
14956
14898
|
const statMethod = opts.lstat ? import_promises.lstat : import_promises.stat;
|
|
14957
14899
|
if (wantBigintFsStats) {
|
|
14958
|
-
this._stat = (
|
|
14900
|
+
this._stat = (path30) => statMethod(path30, { bigint: true });
|
|
14959
14901
|
} else {
|
|
14960
14902
|
this._stat = statMethod;
|
|
14961
14903
|
}
|
|
@@ -14980,8 +14922,8 @@ var ReaddirpStream = class extends import_node_stream.Readable {
|
|
|
14980
14922
|
const par = this.parent;
|
|
14981
14923
|
const fil = par && par.files;
|
|
14982
14924
|
if (fil && fil.length > 0) {
|
|
14983
|
-
const { path:
|
|
14984
|
-
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent,
|
|
14925
|
+
const { path: path30, depth } = par;
|
|
14926
|
+
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path30));
|
|
14985
14927
|
const awaited = await Promise.all(slice);
|
|
14986
14928
|
for (const entry of awaited) {
|
|
14987
14929
|
if (!entry)
|
|
@@ -15021,20 +14963,20 @@ var ReaddirpStream = class extends import_node_stream.Readable {
|
|
|
15021
14963
|
this.reading = false;
|
|
15022
14964
|
}
|
|
15023
14965
|
}
|
|
15024
|
-
async _exploreDir(
|
|
14966
|
+
async _exploreDir(path30, depth) {
|
|
15025
14967
|
let files;
|
|
15026
14968
|
try {
|
|
15027
|
-
files = await (0, import_promises.readdir)(
|
|
14969
|
+
files = await (0, import_promises.readdir)(path30, this._rdOptions);
|
|
15028
14970
|
} catch (error) {
|
|
15029
14971
|
this._onError(error);
|
|
15030
14972
|
}
|
|
15031
|
-
return { files, depth, path:
|
|
14973
|
+
return { files, depth, path: path30 };
|
|
15032
14974
|
}
|
|
15033
|
-
async _formatEntry(dirent,
|
|
14975
|
+
async _formatEntry(dirent, path30) {
|
|
15034
14976
|
let entry;
|
|
15035
14977
|
const basename9 = this._isDirent ? dirent.name : dirent;
|
|
15036
14978
|
try {
|
|
15037
|
-
const fullPath = (0, import_node_path.resolve)((0, import_node_path.join)(
|
|
14979
|
+
const fullPath = (0, import_node_path.resolve)((0, import_node_path.join)(path30, basename9));
|
|
15038
14980
|
entry = { path: (0, import_node_path.relative)(this._root, fullPath), fullPath, basename: basename9 };
|
|
15039
14981
|
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
15040
14982
|
} catch (err) {
|
|
@@ -15434,16 +15376,16 @@ var delFromSet = (main, prop, item) => {
|
|
|
15434
15376
|
};
|
|
15435
15377
|
var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
|
|
15436
15378
|
var FsWatchInstances = /* @__PURE__ */ new Map();
|
|
15437
|
-
function createFsWatchInstance(
|
|
15379
|
+
function createFsWatchInstance(path30, options, listener, errHandler, emitRaw) {
|
|
15438
15380
|
const handleEvent = (rawEvent, evPath) => {
|
|
15439
|
-
listener(
|
|
15440
|
-
emitRaw(rawEvent, evPath, { watchedPath:
|
|
15441
|
-
if (evPath &&
|
|
15442
|
-
fsWatchBroadcast(sp.resolve(
|
|
15381
|
+
listener(path30);
|
|
15382
|
+
emitRaw(rawEvent, evPath, { watchedPath: path30 });
|
|
15383
|
+
if (evPath && path30 !== evPath) {
|
|
15384
|
+
fsWatchBroadcast(sp.resolve(path30, evPath), KEY_LISTENERS, sp.join(path30, evPath));
|
|
15443
15385
|
}
|
|
15444
15386
|
};
|
|
15445
15387
|
try {
|
|
15446
|
-
return (0, import_node_fs.watch)(
|
|
15388
|
+
return (0, import_node_fs.watch)(path30, {
|
|
15447
15389
|
persistent: options.persistent
|
|
15448
15390
|
}, handleEvent);
|
|
15449
15391
|
} catch (error) {
|
|
@@ -15459,12 +15401,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
|
|
|
15459
15401
|
listener(val1, val2, val3);
|
|
15460
15402
|
});
|
|
15461
15403
|
};
|
|
15462
|
-
var setFsWatchListener = (
|
|
15404
|
+
var setFsWatchListener = (path30, fullPath, options, handlers) => {
|
|
15463
15405
|
const { listener, errHandler, rawEmitter } = handlers;
|
|
15464
15406
|
let cont = FsWatchInstances.get(fullPath);
|
|
15465
15407
|
let watcher;
|
|
15466
15408
|
if (!options.persistent) {
|
|
15467
|
-
watcher = createFsWatchInstance(
|
|
15409
|
+
watcher = createFsWatchInstance(path30, options, listener, errHandler, rawEmitter);
|
|
15468
15410
|
if (!watcher)
|
|
15469
15411
|
return;
|
|
15470
15412
|
return watcher.close.bind(watcher);
|
|
@@ -15475,7 +15417,7 @@ var setFsWatchListener = (path28, fullPath, options, handlers) => {
|
|
|
15475
15417
|
addAndConvert(cont, KEY_RAW, rawEmitter);
|
|
15476
15418
|
} else {
|
|
15477
15419
|
watcher = createFsWatchInstance(
|
|
15478
|
-
|
|
15420
|
+
path30,
|
|
15479
15421
|
options,
|
|
15480
15422
|
fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
|
|
15481
15423
|
errHandler,
|
|
@@ -15490,7 +15432,7 @@ var setFsWatchListener = (path28, fullPath, options, handlers) => {
|
|
|
15490
15432
|
cont.watcherUnusable = true;
|
|
15491
15433
|
if (isWindows && error.code === "EPERM") {
|
|
15492
15434
|
try {
|
|
15493
|
-
const fd = await (0, import_promises2.open)(
|
|
15435
|
+
const fd = await (0, import_promises2.open)(path30, "r");
|
|
15494
15436
|
await fd.close();
|
|
15495
15437
|
broadcastErr(error);
|
|
15496
15438
|
} catch (err) {
|
|
@@ -15521,7 +15463,7 @@ var setFsWatchListener = (path28, fullPath, options, handlers) => {
|
|
|
15521
15463
|
};
|
|
15522
15464
|
};
|
|
15523
15465
|
var FsWatchFileInstances = /* @__PURE__ */ new Map();
|
|
15524
|
-
var setFsWatchFileListener = (
|
|
15466
|
+
var setFsWatchFileListener = (path30, fullPath, options, handlers) => {
|
|
15525
15467
|
const { listener, rawEmitter } = handlers;
|
|
15526
15468
|
let cont = FsWatchFileInstances.get(fullPath);
|
|
15527
15469
|
const copts = cont && cont.options;
|
|
@@ -15543,7 +15485,7 @@ var setFsWatchFileListener = (path28, fullPath, options, handlers) => {
|
|
|
15543
15485
|
});
|
|
15544
15486
|
const currmtime = curr.mtimeMs;
|
|
15545
15487
|
if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
|
|
15546
|
-
foreach(cont.listeners, (listener2) => listener2(
|
|
15488
|
+
foreach(cont.listeners, (listener2) => listener2(path30, curr));
|
|
15547
15489
|
}
|
|
15548
15490
|
})
|
|
15549
15491
|
};
|
|
@@ -15573,13 +15515,13 @@ var NodeFsHandler = class {
|
|
|
15573
15515
|
* @param listener on fs change
|
|
15574
15516
|
* @returns closer for the watcher instance
|
|
15575
15517
|
*/
|
|
15576
|
-
_watchWithNodeFs(
|
|
15518
|
+
_watchWithNodeFs(path30, listener) {
|
|
15577
15519
|
const opts = this.fsw.options;
|
|
15578
|
-
const directory = sp.dirname(
|
|
15579
|
-
const basename9 = sp.basename(
|
|
15520
|
+
const directory = sp.dirname(path30);
|
|
15521
|
+
const basename9 = sp.basename(path30);
|
|
15580
15522
|
const parent = this.fsw._getWatchedDir(directory);
|
|
15581
15523
|
parent.add(basename9);
|
|
15582
|
-
const absolutePath = sp.resolve(
|
|
15524
|
+
const absolutePath = sp.resolve(path30);
|
|
15583
15525
|
const options = {
|
|
15584
15526
|
persistent: opts.persistent
|
|
15585
15527
|
};
|
|
@@ -15589,12 +15531,12 @@ var NodeFsHandler = class {
|
|
|
15589
15531
|
if (opts.usePolling) {
|
|
15590
15532
|
const enableBin = opts.interval !== opts.binaryInterval;
|
|
15591
15533
|
options.interval = enableBin && isBinaryPath(basename9) ? opts.binaryInterval : opts.interval;
|
|
15592
|
-
closer = setFsWatchFileListener(
|
|
15534
|
+
closer = setFsWatchFileListener(path30, absolutePath, options, {
|
|
15593
15535
|
listener,
|
|
15594
15536
|
rawEmitter: this.fsw._emitRaw
|
|
15595
15537
|
});
|
|
15596
15538
|
} else {
|
|
15597
|
-
closer = setFsWatchListener(
|
|
15539
|
+
closer = setFsWatchListener(path30, absolutePath, options, {
|
|
15598
15540
|
listener,
|
|
15599
15541
|
errHandler: this._boundHandleError,
|
|
15600
15542
|
rawEmitter: this.fsw._emitRaw
|
|
@@ -15616,7 +15558,7 @@ var NodeFsHandler = class {
|
|
|
15616
15558
|
let prevStats = stats;
|
|
15617
15559
|
if (parent.has(basename9))
|
|
15618
15560
|
return;
|
|
15619
|
-
const listener = async (
|
|
15561
|
+
const listener = async (path30, newStats) => {
|
|
15620
15562
|
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
|
|
15621
15563
|
return;
|
|
15622
15564
|
if (!newStats || newStats.mtimeMs === 0) {
|
|
@@ -15630,11 +15572,11 @@ var NodeFsHandler = class {
|
|
|
15630
15572
|
this.fsw._emit(EV.CHANGE, file, newStats2);
|
|
15631
15573
|
}
|
|
15632
15574
|
if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
|
|
15633
|
-
this.fsw._closeFile(
|
|
15575
|
+
this.fsw._closeFile(path30);
|
|
15634
15576
|
prevStats = newStats2;
|
|
15635
15577
|
const closer2 = this._watchWithNodeFs(file, listener);
|
|
15636
15578
|
if (closer2)
|
|
15637
|
-
this.fsw._addPathCloser(
|
|
15579
|
+
this.fsw._addPathCloser(path30, closer2);
|
|
15638
15580
|
} else {
|
|
15639
15581
|
prevStats = newStats2;
|
|
15640
15582
|
}
|
|
@@ -15666,7 +15608,7 @@ var NodeFsHandler = class {
|
|
|
15666
15608
|
* @param item basename of this item
|
|
15667
15609
|
* @returns true if no more processing is needed for this entry.
|
|
15668
15610
|
*/
|
|
15669
|
-
async _handleSymlink(entry, directory,
|
|
15611
|
+
async _handleSymlink(entry, directory, path30, item) {
|
|
15670
15612
|
if (this.fsw.closed) {
|
|
15671
15613
|
return;
|
|
15672
15614
|
}
|
|
@@ -15676,7 +15618,7 @@ var NodeFsHandler = class {
|
|
|
15676
15618
|
this.fsw._incrReadyCount();
|
|
15677
15619
|
let linkPath;
|
|
15678
15620
|
try {
|
|
15679
|
-
linkPath = await (0, import_promises2.realpath)(
|
|
15621
|
+
linkPath = await (0, import_promises2.realpath)(path30);
|
|
15680
15622
|
} catch (e) {
|
|
15681
15623
|
this.fsw._emitReady();
|
|
15682
15624
|
return true;
|
|
@@ -15686,12 +15628,12 @@ var NodeFsHandler = class {
|
|
|
15686
15628
|
if (dir.has(item)) {
|
|
15687
15629
|
if (this.fsw._symlinkPaths.get(full) !== linkPath) {
|
|
15688
15630
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
15689
|
-
this.fsw._emit(EV.CHANGE,
|
|
15631
|
+
this.fsw._emit(EV.CHANGE, path30, entry.stats);
|
|
15690
15632
|
}
|
|
15691
15633
|
} else {
|
|
15692
15634
|
dir.add(item);
|
|
15693
15635
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
15694
|
-
this.fsw._emit(EV.ADD,
|
|
15636
|
+
this.fsw._emit(EV.ADD, path30, entry.stats);
|
|
15695
15637
|
}
|
|
15696
15638
|
this.fsw._emitReady();
|
|
15697
15639
|
return true;
|
|
@@ -15721,9 +15663,9 @@ var NodeFsHandler = class {
|
|
|
15721
15663
|
return;
|
|
15722
15664
|
}
|
|
15723
15665
|
const item = entry.path;
|
|
15724
|
-
let
|
|
15666
|
+
let path30 = sp.join(directory, item);
|
|
15725
15667
|
current.add(item);
|
|
15726
|
-
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory,
|
|
15668
|
+
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path30, item)) {
|
|
15727
15669
|
return;
|
|
15728
15670
|
}
|
|
15729
15671
|
if (this.fsw.closed) {
|
|
@@ -15732,11 +15674,11 @@ var NodeFsHandler = class {
|
|
|
15732
15674
|
}
|
|
15733
15675
|
if (item === target || !target && !previous.has(item)) {
|
|
15734
15676
|
this.fsw._incrReadyCount();
|
|
15735
|
-
|
|
15736
|
-
this._addToNodeFs(
|
|
15677
|
+
path30 = sp.join(dir, sp.relative(dir, path30));
|
|
15678
|
+
this._addToNodeFs(path30, initialAdd, wh, depth + 1);
|
|
15737
15679
|
}
|
|
15738
15680
|
}).on(EV.ERROR, this._boundHandleError);
|
|
15739
|
-
return new Promise((
|
|
15681
|
+
return new Promise((resolve17, reject) => {
|
|
15740
15682
|
if (!stream)
|
|
15741
15683
|
return reject();
|
|
15742
15684
|
stream.once(STR_END, () => {
|
|
@@ -15745,7 +15687,7 @@ var NodeFsHandler = class {
|
|
|
15745
15687
|
return;
|
|
15746
15688
|
}
|
|
15747
15689
|
const wasThrottled = throttler ? throttler.clear() : false;
|
|
15748
|
-
|
|
15690
|
+
resolve17(void 0);
|
|
15749
15691
|
previous.getChildren().filter((item) => {
|
|
15750
15692
|
return item !== directory && !current.has(item);
|
|
15751
15693
|
}).forEach((item) => {
|
|
@@ -15802,13 +15744,13 @@ var NodeFsHandler = class {
|
|
|
15802
15744
|
* @param depth Child path actually targeted for watch
|
|
15803
15745
|
* @param target Child path actually targeted for watch
|
|
15804
15746
|
*/
|
|
15805
|
-
async _addToNodeFs(
|
|
15747
|
+
async _addToNodeFs(path30, initialAdd, priorWh, depth, target) {
|
|
15806
15748
|
const ready = this.fsw._emitReady;
|
|
15807
|
-
if (this.fsw._isIgnored(
|
|
15749
|
+
if (this.fsw._isIgnored(path30) || this.fsw.closed) {
|
|
15808
15750
|
ready();
|
|
15809
15751
|
return false;
|
|
15810
15752
|
}
|
|
15811
|
-
const wh = this.fsw._getWatchHelpers(
|
|
15753
|
+
const wh = this.fsw._getWatchHelpers(path30);
|
|
15812
15754
|
if (priorWh) {
|
|
15813
15755
|
wh.filterPath = (entry) => priorWh.filterPath(entry);
|
|
15814
15756
|
wh.filterDir = (entry) => priorWh.filterDir(entry);
|
|
@@ -15824,8 +15766,8 @@ var NodeFsHandler = class {
|
|
|
15824
15766
|
const follow = this.fsw.options.followSymlinks;
|
|
15825
15767
|
let closer;
|
|
15826
15768
|
if (stats.isDirectory()) {
|
|
15827
|
-
const absPath = sp.resolve(
|
|
15828
|
-
const targetPath = follow ? await (0, import_promises2.realpath)(
|
|
15769
|
+
const absPath = sp.resolve(path30);
|
|
15770
|
+
const targetPath = follow ? await (0, import_promises2.realpath)(path30) : path30;
|
|
15829
15771
|
if (this.fsw.closed)
|
|
15830
15772
|
return;
|
|
15831
15773
|
closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
|
|
@@ -15835,29 +15777,29 @@ var NodeFsHandler = class {
|
|
|
15835
15777
|
this.fsw._symlinkPaths.set(absPath, targetPath);
|
|
15836
15778
|
}
|
|
15837
15779
|
} else if (stats.isSymbolicLink()) {
|
|
15838
|
-
const targetPath = follow ? await (0, import_promises2.realpath)(
|
|
15780
|
+
const targetPath = follow ? await (0, import_promises2.realpath)(path30) : path30;
|
|
15839
15781
|
if (this.fsw.closed)
|
|
15840
15782
|
return;
|
|
15841
15783
|
const parent = sp.dirname(wh.watchPath);
|
|
15842
15784
|
this.fsw._getWatchedDir(parent).add(wh.watchPath);
|
|
15843
15785
|
this.fsw._emit(EV.ADD, wh.watchPath, stats);
|
|
15844
|
-
closer = await this._handleDir(parent, stats, initialAdd, depth,
|
|
15786
|
+
closer = await this._handleDir(parent, stats, initialAdd, depth, path30, wh, targetPath);
|
|
15845
15787
|
if (this.fsw.closed)
|
|
15846
15788
|
return;
|
|
15847
15789
|
if (targetPath !== void 0) {
|
|
15848
|
-
this.fsw._symlinkPaths.set(sp.resolve(
|
|
15790
|
+
this.fsw._symlinkPaths.set(sp.resolve(path30), targetPath);
|
|
15849
15791
|
}
|
|
15850
15792
|
} else {
|
|
15851
15793
|
closer = this._handleFile(wh.watchPath, stats, initialAdd);
|
|
15852
15794
|
}
|
|
15853
15795
|
ready();
|
|
15854
15796
|
if (closer)
|
|
15855
|
-
this.fsw._addPathCloser(
|
|
15797
|
+
this.fsw._addPathCloser(path30, closer);
|
|
15856
15798
|
return false;
|
|
15857
15799
|
} catch (error) {
|
|
15858
15800
|
if (this.fsw._handleError(error)) {
|
|
15859
15801
|
ready();
|
|
15860
|
-
return
|
|
15802
|
+
return path30;
|
|
15861
15803
|
}
|
|
15862
15804
|
}
|
|
15863
15805
|
}
|
|
@@ -15889,35 +15831,35 @@ function createPattern(matcher) {
|
|
|
15889
15831
|
if (matcher.path === string)
|
|
15890
15832
|
return true;
|
|
15891
15833
|
if (matcher.recursive) {
|
|
15892
|
-
const
|
|
15893
|
-
if (!
|
|
15834
|
+
const relative14 = sp2.relative(matcher.path, string);
|
|
15835
|
+
if (!relative14) {
|
|
15894
15836
|
return false;
|
|
15895
15837
|
}
|
|
15896
|
-
return !
|
|
15838
|
+
return !relative14.startsWith("..") && !sp2.isAbsolute(relative14);
|
|
15897
15839
|
}
|
|
15898
15840
|
return false;
|
|
15899
15841
|
};
|
|
15900
15842
|
}
|
|
15901
15843
|
return () => false;
|
|
15902
15844
|
}
|
|
15903
|
-
function normalizePath2(
|
|
15904
|
-
if (typeof
|
|
15845
|
+
function normalizePath2(path30) {
|
|
15846
|
+
if (typeof path30 !== "string")
|
|
15905
15847
|
throw new Error("string expected");
|
|
15906
|
-
|
|
15907
|
-
|
|
15848
|
+
path30 = sp2.normalize(path30);
|
|
15849
|
+
path30 = path30.replace(/\\/g, "/");
|
|
15908
15850
|
let prepend = false;
|
|
15909
|
-
if (
|
|
15851
|
+
if (path30.startsWith("//"))
|
|
15910
15852
|
prepend = true;
|
|
15911
|
-
|
|
15853
|
+
path30 = path30.replace(DOUBLE_SLASH_RE, "/");
|
|
15912
15854
|
if (prepend)
|
|
15913
|
-
|
|
15914
|
-
return
|
|
15855
|
+
path30 = "/" + path30;
|
|
15856
|
+
return path30;
|
|
15915
15857
|
}
|
|
15916
15858
|
function matchPatterns(patterns, testString, stats) {
|
|
15917
|
-
const
|
|
15859
|
+
const path30 = normalizePath2(testString);
|
|
15918
15860
|
for (let index = 0; index < patterns.length; index++) {
|
|
15919
15861
|
const pattern = patterns[index];
|
|
15920
|
-
if (pattern(
|
|
15862
|
+
if (pattern(path30, stats)) {
|
|
15921
15863
|
return true;
|
|
15922
15864
|
}
|
|
15923
15865
|
}
|
|
@@ -15955,19 +15897,19 @@ var toUnix = (string) => {
|
|
|
15955
15897
|
}
|
|
15956
15898
|
return str;
|
|
15957
15899
|
};
|
|
15958
|
-
var normalizePathToUnix = (
|
|
15959
|
-
var normalizeIgnored = (cwd = "") => (
|
|
15960
|
-
if (typeof
|
|
15961
|
-
return normalizePathToUnix(sp2.isAbsolute(
|
|
15900
|
+
var normalizePathToUnix = (path30) => toUnix(sp2.normalize(toUnix(path30)));
|
|
15901
|
+
var normalizeIgnored = (cwd = "") => (path30) => {
|
|
15902
|
+
if (typeof path30 === "string") {
|
|
15903
|
+
return normalizePathToUnix(sp2.isAbsolute(path30) ? path30 : sp2.join(cwd, path30));
|
|
15962
15904
|
} else {
|
|
15963
|
-
return
|
|
15905
|
+
return path30;
|
|
15964
15906
|
}
|
|
15965
15907
|
};
|
|
15966
|
-
var getAbsolutePath = (
|
|
15967
|
-
if (sp2.isAbsolute(
|
|
15968
|
-
return
|
|
15908
|
+
var getAbsolutePath = (path30, cwd) => {
|
|
15909
|
+
if (sp2.isAbsolute(path30)) {
|
|
15910
|
+
return path30;
|
|
15969
15911
|
}
|
|
15970
|
-
return sp2.join(cwd,
|
|
15912
|
+
return sp2.join(cwd, path30);
|
|
15971
15913
|
};
|
|
15972
15914
|
var EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
|
|
15973
15915
|
var DirEntry = class {
|
|
@@ -16032,10 +15974,10 @@ var WatchHelper = class {
|
|
|
16032
15974
|
dirParts;
|
|
16033
15975
|
followSymlinks;
|
|
16034
15976
|
statMethod;
|
|
16035
|
-
constructor(
|
|
15977
|
+
constructor(path30, follow, fsw) {
|
|
16036
15978
|
this.fsw = fsw;
|
|
16037
|
-
const watchPath =
|
|
16038
|
-
this.path =
|
|
15979
|
+
const watchPath = path30;
|
|
15980
|
+
this.path = path30 = path30.replace(REPLACER_RE, "");
|
|
16039
15981
|
this.watchPath = watchPath;
|
|
16040
15982
|
this.fullWatchPath = sp2.resolve(watchPath);
|
|
16041
15983
|
this.dirParts = [];
|
|
@@ -16175,20 +16117,20 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
16175
16117
|
this._closePromise = void 0;
|
|
16176
16118
|
let paths = unifyPaths(paths_);
|
|
16177
16119
|
if (cwd) {
|
|
16178
|
-
paths = paths.map((
|
|
16179
|
-
const absPath = getAbsolutePath(
|
|
16120
|
+
paths = paths.map((path30) => {
|
|
16121
|
+
const absPath = getAbsolutePath(path30, cwd);
|
|
16180
16122
|
return absPath;
|
|
16181
16123
|
});
|
|
16182
16124
|
}
|
|
16183
|
-
paths.forEach((
|
|
16184
|
-
this._removeIgnoredPath(
|
|
16125
|
+
paths.forEach((path30) => {
|
|
16126
|
+
this._removeIgnoredPath(path30);
|
|
16185
16127
|
});
|
|
16186
16128
|
this._userIgnored = void 0;
|
|
16187
16129
|
if (!this._readyCount)
|
|
16188
16130
|
this._readyCount = 0;
|
|
16189
16131
|
this._readyCount += paths.length;
|
|
16190
|
-
Promise.all(paths.map(async (
|
|
16191
|
-
const res = await this._nodeFsHandler._addToNodeFs(
|
|
16132
|
+
Promise.all(paths.map(async (path30) => {
|
|
16133
|
+
const res = await this._nodeFsHandler._addToNodeFs(path30, !_internal, void 0, 0, _origAdd);
|
|
16192
16134
|
if (res)
|
|
16193
16135
|
this._emitReady();
|
|
16194
16136
|
return res;
|
|
@@ -16210,17 +16152,17 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
16210
16152
|
return this;
|
|
16211
16153
|
const paths = unifyPaths(paths_);
|
|
16212
16154
|
const { cwd } = this.options;
|
|
16213
|
-
paths.forEach((
|
|
16214
|
-
if (!sp2.isAbsolute(
|
|
16155
|
+
paths.forEach((path30) => {
|
|
16156
|
+
if (!sp2.isAbsolute(path30) && !this._closers.has(path30)) {
|
|
16215
16157
|
if (cwd)
|
|
16216
|
-
|
|
16217
|
-
|
|
16158
|
+
path30 = sp2.join(cwd, path30);
|
|
16159
|
+
path30 = sp2.resolve(path30);
|
|
16218
16160
|
}
|
|
16219
|
-
this._closePath(
|
|
16220
|
-
this._addIgnoredPath(
|
|
16221
|
-
if (this._watched.has(
|
|
16161
|
+
this._closePath(path30);
|
|
16162
|
+
this._addIgnoredPath(path30);
|
|
16163
|
+
if (this._watched.has(path30)) {
|
|
16222
16164
|
this._addIgnoredPath({
|
|
16223
|
-
path:
|
|
16165
|
+
path: path30,
|
|
16224
16166
|
recursive: true
|
|
16225
16167
|
});
|
|
16226
16168
|
}
|
|
@@ -16284,38 +16226,38 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
16284
16226
|
* @param stats arguments to be passed with event
|
|
16285
16227
|
* @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
|
|
16286
16228
|
*/
|
|
16287
|
-
async _emit(event,
|
|
16229
|
+
async _emit(event, path30, stats) {
|
|
16288
16230
|
if (this.closed)
|
|
16289
16231
|
return;
|
|
16290
16232
|
const opts = this.options;
|
|
16291
16233
|
if (isWindows)
|
|
16292
|
-
|
|
16234
|
+
path30 = sp2.normalize(path30);
|
|
16293
16235
|
if (opts.cwd)
|
|
16294
|
-
|
|
16295
|
-
const args = [
|
|
16236
|
+
path30 = sp2.relative(opts.cwd, path30);
|
|
16237
|
+
const args = [path30];
|
|
16296
16238
|
if (stats != null)
|
|
16297
16239
|
args.push(stats);
|
|
16298
16240
|
const awf = opts.awaitWriteFinish;
|
|
16299
16241
|
let pw;
|
|
16300
|
-
if (awf && (pw = this._pendingWrites.get(
|
|
16242
|
+
if (awf && (pw = this._pendingWrites.get(path30))) {
|
|
16301
16243
|
pw.lastChange = /* @__PURE__ */ new Date();
|
|
16302
16244
|
return this;
|
|
16303
16245
|
}
|
|
16304
16246
|
if (opts.atomic) {
|
|
16305
16247
|
if (event === EVENTS.UNLINK) {
|
|
16306
|
-
this._pendingUnlinks.set(
|
|
16248
|
+
this._pendingUnlinks.set(path30, [event, ...args]);
|
|
16307
16249
|
setTimeout(() => {
|
|
16308
|
-
this._pendingUnlinks.forEach((entry,
|
|
16250
|
+
this._pendingUnlinks.forEach((entry, path31) => {
|
|
16309
16251
|
this.emit(...entry);
|
|
16310
16252
|
this.emit(EVENTS.ALL, ...entry);
|
|
16311
|
-
this._pendingUnlinks.delete(
|
|
16253
|
+
this._pendingUnlinks.delete(path31);
|
|
16312
16254
|
});
|
|
16313
16255
|
}, typeof opts.atomic === "number" ? opts.atomic : 100);
|
|
16314
16256
|
return this;
|
|
16315
16257
|
}
|
|
16316
|
-
if (event === EVENTS.ADD && this._pendingUnlinks.has(
|
|
16258
|
+
if (event === EVENTS.ADD && this._pendingUnlinks.has(path30)) {
|
|
16317
16259
|
event = EVENTS.CHANGE;
|
|
16318
|
-
this._pendingUnlinks.delete(
|
|
16260
|
+
this._pendingUnlinks.delete(path30);
|
|
16319
16261
|
}
|
|
16320
16262
|
}
|
|
16321
16263
|
if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
|
|
@@ -16333,16 +16275,16 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
16333
16275
|
this.emitWithAll(event, args);
|
|
16334
16276
|
}
|
|
16335
16277
|
};
|
|
16336
|
-
this._awaitWriteFinish(
|
|
16278
|
+
this._awaitWriteFinish(path30, awf.stabilityThreshold, event, awfEmit);
|
|
16337
16279
|
return this;
|
|
16338
16280
|
}
|
|
16339
16281
|
if (event === EVENTS.CHANGE) {
|
|
16340
|
-
const isThrottled = !this._throttle(EVENTS.CHANGE,
|
|
16282
|
+
const isThrottled = !this._throttle(EVENTS.CHANGE, path30, 50);
|
|
16341
16283
|
if (isThrottled)
|
|
16342
16284
|
return this;
|
|
16343
16285
|
}
|
|
16344
16286
|
if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
|
|
16345
|
-
const fullPath = opts.cwd ? sp2.join(opts.cwd,
|
|
16287
|
+
const fullPath = opts.cwd ? sp2.join(opts.cwd, path30) : path30;
|
|
16346
16288
|
let stats2;
|
|
16347
16289
|
try {
|
|
16348
16290
|
stats2 = await (0, import_promises3.stat)(fullPath);
|
|
@@ -16373,23 +16315,23 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
16373
16315
|
* @param timeout duration of time to suppress duplicate actions
|
|
16374
16316
|
* @returns tracking object or false if action should be suppressed
|
|
16375
16317
|
*/
|
|
16376
|
-
_throttle(actionType,
|
|
16318
|
+
_throttle(actionType, path30, timeout) {
|
|
16377
16319
|
if (!this._throttled.has(actionType)) {
|
|
16378
16320
|
this._throttled.set(actionType, /* @__PURE__ */ new Map());
|
|
16379
16321
|
}
|
|
16380
16322
|
const action = this._throttled.get(actionType);
|
|
16381
16323
|
if (!action)
|
|
16382
16324
|
throw new Error("invalid throttle");
|
|
16383
|
-
const actionPath = action.get(
|
|
16325
|
+
const actionPath = action.get(path30);
|
|
16384
16326
|
if (actionPath) {
|
|
16385
16327
|
actionPath.count++;
|
|
16386
16328
|
return false;
|
|
16387
16329
|
}
|
|
16388
16330
|
let timeoutObject;
|
|
16389
16331
|
const clear = () => {
|
|
16390
|
-
const item = action.get(
|
|
16332
|
+
const item = action.get(path30);
|
|
16391
16333
|
const count = item ? item.count : 0;
|
|
16392
|
-
action.delete(
|
|
16334
|
+
action.delete(path30);
|
|
16393
16335
|
clearTimeout(timeoutObject);
|
|
16394
16336
|
if (item)
|
|
16395
16337
|
clearTimeout(item.timeoutObject);
|
|
@@ -16397,7 +16339,7 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
16397
16339
|
};
|
|
16398
16340
|
timeoutObject = setTimeout(clear, timeout);
|
|
16399
16341
|
const thr = { timeoutObject, clear, count: 0 };
|
|
16400
|
-
action.set(
|
|
16342
|
+
action.set(path30, thr);
|
|
16401
16343
|
return thr;
|
|
16402
16344
|
}
|
|
16403
16345
|
_incrReadyCount() {
|
|
@@ -16411,44 +16353,44 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
16411
16353
|
* @param event
|
|
16412
16354
|
* @param awfEmit Callback to be called when ready for event to be emitted.
|
|
16413
16355
|
*/
|
|
16414
|
-
_awaitWriteFinish(
|
|
16356
|
+
_awaitWriteFinish(path30, threshold, event, awfEmit) {
|
|
16415
16357
|
const awf = this.options.awaitWriteFinish;
|
|
16416
16358
|
if (typeof awf !== "object")
|
|
16417
16359
|
return;
|
|
16418
16360
|
const pollInterval = awf.pollInterval;
|
|
16419
16361
|
let timeoutHandler;
|
|
16420
|
-
let fullPath =
|
|
16421
|
-
if (this.options.cwd && !sp2.isAbsolute(
|
|
16422
|
-
fullPath = sp2.join(this.options.cwd,
|
|
16362
|
+
let fullPath = path30;
|
|
16363
|
+
if (this.options.cwd && !sp2.isAbsolute(path30)) {
|
|
16364
|
+
fullPath = sp2.join(this.options.cwd, path30);
|
|
16423
16365
|
}
|
|
16424
16366
|
const now2 = /* @__PURE__ */ new Date();
|
|
16425
16367
|
const writes = this._pendingWrites;
|
|
16426
16368
|
function awaitWriteFinishFn(prevStat) {
|
|
16427
16369
|
(0, import_node_fs2.stat)(fullPath, (err, curStat) => {
|
|
16428
|
-
if (err || !writes.has(
|
|
16370
|
+
if (err || !writes.has(path30)) {
|
|
16429
16371
|
if (err && err.code !== "ENOENT")
|
|
16430
16372
|
awfEmit(err);
|
|
16431
16373
|
return;
|
|
16432
16374
|
}
|
|
16433
16375
|
const now3 = Number(/* @__PURE__ */ new Date());
|
|
16434
16376
|
if (prevStat && curStat.size !== prevStat.size) {
|
|
16435
|
-
writes.get(
|
|
16377
|
+
writes.get(path30).lastChange = now3;
|
|
16436
16378
|
}
|
|
16437
|
-
const pw = writes.get(
|
|
16379
|
+
const pw = writes.get(path30);
|
|
16438
16380
|
const df = now3 - pw.lastChange;
|
|
16439
16381
|
if (df >= threshold) {
|
|
16440
|
-
writes.delete(
|
|
16382
|
+
writes.delete(path30);
|
|
16441
16383
|
awfEmit(void 0, curStat);
|
|
16442
16384
|
} else {
|
|
16443
16385
|
timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
|
|
16444
16386
|
}
|
|
16445
16387
|
});
|
|
16446
16388
|
}
|
|
16447
|
-
if (!writes.has(
|
|
16448
|
-
writes.set(
|
|
16389
|
+
if (!writes.has(path30)) {
|
|
16390
|
+
writes.set(path30, {
|
|
16449
16391
|
lastChange: now2,
|
|
16450
16392
|
cancelWait: () => {
|
|
16451
|
-
writes.delete(
|
|
16393
|
+
writes.delete(path30);
|
|
16452
16394
|
clearTimeout(timeoutHandler);
|
|
16453
16395
|
return event;
|
|
16454
16396
|
}
|
|
@@ -16459,8 +16401,8 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
16459
16401
|
/**
|
|
16460
16402
|
* Determines whether user has asked to ignore this path.
|
|
16461
16403
|
*/
|
|
16462
|
-
_isIgnored(
|
|
16463
|
-
if (this.options.atomic && DOT_RE.test(
|
|
16404
|
+
_isIgnored(path30, stats) {
|
|
16405
|
+
if (this.options.atomic && DOT_RE.test(path30))
|
|
16464
16406
|
return true;
|
|
16465
16407
|
if (!this._userIgnored) {
|
|
16466
16408
|
const { cwd } = this.options;
|
|
@@ -16470,17 +16412,17 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
16470
16412
|
const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
|
|
16471
16413
|
this._userIgnored = anymatch(list, void 0);
|
|
16472
16414
|
}
|
|
16473
|
-
return this._userIgnored(
|
|
16415
|
+
return this._userIgnored(path30, stats);
|
|
16474
16416
|
}
|
|
16475
|
-
_isntIgnored(
|
|
16476
|
-
return !this._isIgnored(
|
|
16417
|
+
_isntIgnored(path30, stat5) {
|
|
16418
|
+
return !this._isIgnored(path30, stat5);
|
|
16477
16419
|
}
|
|
16478
16420
|
/**
|
|
16479
16421
|
* Provides a set of common helpers and properties relating to symlink handling.
|
|
16480
16422
|
* @param path file or directory pattern being watched
|
|
16481
16423
|
*/
|
|
16482
|
-
_getWatchHelpers(
|
|
16483
|
-
return new WatchHelper(
|
|
16424
|
+
_getWatchHelpers(path30) {
|
|
16425
|
+
return new WatchHelper(path30, this.options.followSymlinks, this);
|
|
16484
16426
|
}
|
|
16485
16427
|
// Directory helpers
|
|
16486
16428
|
// -----------------
|
|
@@ -16512,63 +16454,63 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
16512
16454
|
* @param item base path of item/directory
|
|
16513
16455
|
*/
|
|
16514
16456
|
_remove(directory, item, isDirectory) {
|
|
16515
|
-
const
|
|
16516
|
-
const fullPath = sp2.resolve(
|
|
16517
|
-
isDirectory = isDirectory != null ? isDirectory : this._watched.has(
|
|
16518
|
-
if (!this._throttle("remove",
|
|
16457
|
+
const path30 = sp2.join(directory, item);
|
|
16458
|
+
const fullPath = sp2.resolve(path30);
|
|
16459
|
+
isDirectory = isDirectory != null ? isDirectory : this._watched.has(path30) || this._watched.has(fullPath);
|
|
16460
|
+
if (!this._throttle("remove", path30, 100))
|
|
16519
16461
|
return;
|
|
16520
16462
|
if (!isDirectory && this._watched.size === 1) {
|
|
16521
16463
|
this.add(directory, item, true);
|
|
16522
16464
|
}
|
|
16523
|
-
const wp = this._getWatchedDir(
|
|
16465
|
+
const wp = this._getWatchedDir(path30);
|
|
16524
16466
|
const nestedDirectoryChildren = wp.getChildren();
|
|
16525
|
-
nestedDirectoryChildren.forEach((nested) => this._remove(
|
|
16467
|
+
nestedDirectoryChildren.forEach((nested) => this._remove(path30, nested));
|
|
16526
16468
|
const parent = this._getWatchedDir(directory);
|
|
16527
16469
|
const wasTracked = parent.has(item);
|
|
16528
16470
|
parent.remove(item);
|
|
16529
16471
|
if (this._symlinkPaths.has(fullPath)) {
|
|
16530
16472
|
this._symlinkPaths.delete(fullPath);
|
|
16531
16473
|
}
|
|
16532
|
-
let relPath =
|
|
16474
|
+
let relPath = path30;
|
|
16533
16475
|
if (this.options.cwd)
|
|
16534
|
-
relPath = sp2.relative(this.options.cwd,
|
|
16476
|
+
relPath = sp2.relative(this.options.cwd, path30);
|
|
16535
16477
|
if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
|
|
16536
16478
|
const event = this._pendingWrites.get(relPath).cancelWait();
|
|
16537
16479
|
if (event === EVENTS.ADD)
|
|
16538
16480
|
return;
|
|
16539
16481
|
}
|
|
16540
|
-
this._watched.delete(
|
|
16482
|
+
this._watched.delete(path30);
|
|
16541
16483
|
this._watched.delete(fullPath);
|
|
16542
16484
|
const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
|
|
16543
|
-
if (wasTracked && !this._isIgnored(
|
|
16544
|
-
this._emit(eventName,
|
|
16545
|
-
this._closePath(
|
|
16485
|
+
if (wasTracked && !this._isIgnored(path30))
|
|
16486
|
+
this._emit(eventName, path30);
|
|
16487
|
+
this._closePath(path30);
|
|
16546
16488
|
}
|
|
16547
16489
|
/**
|
|
16548
16490
|
* Closes all watchers for a path
|
|
16549
16491
|
*/
|
|
16550
|
-
_closePath(
|
|
16551
|
-
this._closeFile(
|
|
16552
|
-
const dir = sp2.dirname(
|
|
16553
|
-
this._getWatchedDir(dir).remove(sp2.basename(
|
|
16492
|
+
_closePath(path30) {
|
|
16493
|
+
this._closeFile(path30);
|
|
16494
|
+
const dir = sp2.dirname(path30);
|
|
16495
|
+
this._getWatchedDir(dir).remove(sp2.basename(path30));
|
|
16554
16496
|
}
|
|
16555
16497
|
/**
|
|
16556
16498
|
* Closes only file-specific watchers
|
|
16557
16499
|
*/
|
|
16558
|
-
_closeFile(
|
|
16559
|
-
const closers = this._closers.get(
|
|
16500
|
+
_closeFile(path30) {
|
|
16501
|
+
const closers = this._closers.get(path30);
|
|
16560
16502
|
if (!closers)
|
|
16561
16503
|
return;
|
|
16562
16504
|
closers.forEach((closer) => closer());
|
|
16563
|
-
this._closers.delete(
|
|
16505
|
+
this._closers.delete(path30);
|
|
16564
16506
|
}
|
|
16565
|
-
_addPathCloser(
|
|
16507
|
+
_addPathCloser(path30, closer) {
|
|
16566
16508
|
if (!closer)
|
|
16567
16509
|
return;
|
|
16568
|
-
let list = this._closers.get(
|
|
16510
|
+
let list = this._closers.get(path30);
|
|
16569
16511
|
if (!list) {
|
|
16570
16512
|
list = [];
|
|
16571
|
-
this._closers.set(
|
|
16513
|
+
this._closers.set(path30, list);
|
|
16572
16514
|
}
|
|
16573
16515
|
list.push(closer);
|
|
16574
16516
|
}
|
|
@@ -16598,12 +16540,291 @@ function watch(paths, options = {}) {
|
|
|
16598
16540
|
var chokidar_default = { watch, FSWatcher };
|
|
16599
16541
|
|
|
16600
16542
|
// src/watcher/file-watcher.ts
|
|
16543
|
+
var path23 = __toESM(require("path"), 1);
|
|
16544
|
+
|
|
16545
|
+
// src/watcher/native-recursive-watcher.ts
|
|
16546
|
+
var import_node_fs3 = require("fs");
|
|
16601
16547
|
var path21 = __toESM(require("path"), 1);
|
|
16548
|
+
var NativeRecursiveWatcher = class {
|
|
16549
|
+
constructor(root, onChange, options = {}) {
|
|
16550
|
+
this.root = root;
|
|
16551
|
+
this.onChange = onChange;
|
|
16552
|
+
this.watchFactory = options.watchFactory ?? this.defaultWatchFactory;
|
|
16553
|
+
this.onError = options.onError;
|
|
16554
|
+
}
|
|
16555
|
+
root;
|
|
16556
|
+
onChange;
|
|
16557
|
+
watcher = null;
|
|
16558
|
+
listenerToken = 0;
|
|
16559
|
+
watchFactory;
|
|
16560
|
+
onError;
|
|
16561
|
+
start() {
|
|
16562
|
+
if (this.watcher) return;
|
|
16563
|
+
const token = ++this.listenerToken;
|
|
16564
|
+
const listener = (_eventType, filename) => {
|
|
16565
|
+
if (this.watcher === null || this.listenerToken !== token) return;
|
|
16566
|
+
const absolutePath = this.toAbsolutePath(filename);
|
|
16567
|
+
const nextResult = this.onChange(absolutePath);
|
|
16568
|
+
if (nextResult instanceof Promise) {
|
|
16569
|
+
void nextResult.catch((error) => {
|
|
16570
|
+
console.error("[codebase-index] Error handling native watcher event:", error);
|
|
16571
|
+
});
|
|
16572
|
+
}
|
|
16573
|
+
};
|
|
16574
|
+
const watcher = this.watchFactory(this.root, listener, {
|
|
16575
|
+
persistent: true,
|
|
16576
|
+
recursive: true
|
|
16577
|
+
});
|
|
16578
|
+
watcher.on?.("error", (error) => {
|
|
16579
|
+
if (this.watcher === watcher && this.listenerToken === token) {
|
|
16580
|
+
this.onError?.(error);
|
|
16581
|
+
}
|
|
16582
|
+
});
|
|
16583
|
+
this.watcher = watcher;
|
|
16584
|
+
}
|
|
16585
|
+
async stop() {
|
|
16586
|
+
const watcher = this.watcher;
|
|
16587
|
+
this.watcher = null;
|
|
16588
|
+
this.listenerToken += 1;
|
|
16589
|
+
if (!watcher) return;
|
|
16590
|
+
await watcher.close();
|
|
16591
|
+
}
|
|
16592
|
+
toAbsolutePath(filename) {
|
|
16593
|
+
if (filename == null) return null;
|
|
16594
|
+
const normalizedFilename = typeof filename === "string" ? filename : filename.toString();
|
|
16595
|
+
const absolutePath = path21.resolve(this.root, normalizedFilename);
|
|
16596
|
+
const relativePath = path21.relative(this.root, absolutePath);
|
|
16597
|
+
const outsideRoot = relativePath === ".." || relativePath.startsWith(`..${path21.sep}`) || path21.isAbsolute(relativePath);
|
|
16598
|
+
return outsideRoot ? null : absolutePath;
|
|
16599
|
+
}
|
|
16600
|
+
defaultWatchFactory = (root, listener, options) => (0, import_node_fs3.watch)(root, options, listener);
|
|
16601
|
+
};
|
|
16602
|
+
|
|
16603
|
+
// src/watcher/snapshot.ts
|
|
16604
|
+
var fsPromises4 = __toESM(require("fs/promises"), 1);
|
|
16605
|
+
var path22 = __toESM(require("path"), 1);
|
|
16606
|
+
async function buildFileSnapshotScan(projectRoot, config, configPaths = []) {
|
|
16607
|
+
const normalizedProjectRoot = path22.resolve(projectRoot);
|
|
16608
|
+
const ignoreFilter = createIgnoreFilter(normalizedProjectRoot);
|
|
16609
|
+
const includePatterns = [...config.include, ...config.additionalInclude ?? []];
|
|
16610
|
+
const maxDepth = config.indexing?.maxDepth ?? -1;
|
|
16611
|
+
const snapshot = /* @__PURE__ */ new Map();
|
|
16612
|
+
const unreadablePrefixes = /* @__PURE__ */ new Set();
|
|
16613
|
+
const includeFile = async (filePath) => {
|
|
16614
|
+
const normalizedPath2 = path22.resolve(filePath);
|
|
16615
|
+
if (!shouldIncludeFile(normalizedPath2, normalizedProjectRoot, includePatterns, config.exclude, ignoreFilter)) return;
|
|
16616
|
+
const stat5 = await readStatIfFile(normalizedPath2, unreadablePrefixes);
|
|
16617
|
+
if (stat5) snapshot.set(normalizedPath2, { size: stat5.size, mtimeMs: stat5.mtimeMs });
|
|
16618
|
+
};
|
|
16619
|
+
const walk = async (directoryPath, depth) => {
|
|
16620
|
+
let entries;
|
|
16621
|
+
try {
|
|
16622
|
+
entries = await fsPromises4.readdir(directoryPath, { withFileTypes: true });
|
|
16623
|
+
} catch (error) {
|
|
16624
|
+
if (isMissingFsError(error)) return;
|
|
16625
|
+
if (isPermissionFsError(error)) {
|
|
16626
|
+
unreadablePrefixes.add(path22.resolve(directoryPath));
|
|
16627
|
+
return;
|
|
16628
|
+
}
|
|
16629
|
+
throw error;
|
|
16630
|
+
}
|
|
16631
|
+
for (const entry of entries) {
|
|
16632
|
+
const fullPath = path22.join(directoryPath, entry.name);
|
|
16633
|
+
const relativePath = path22.relative(normalizedProjectRoot, fullPath);
|
|
16634
|
+
if (entry.isDirectory()) {
|
|
16635
|
+
if (hasFilteredPathSegment(relativePath, path22.sep) || isRestrictedDirectory(relativePath, path22.sep)) continue;
|
|
16636
|
+
if (ignoreFilter.ignores(relativePath)) continue;
|
|
16637
|
+
if (maxDepth === -1 || depth < maxDepth) await walk(fullPath, depth + 1);
|
|
16638
|
+
} else if (entry.isFile()) {
|
|
16639
|
+
await includeFile(fullPath);
|
|
16640
|
+
}
|
|
16641
|
+
}
|
|
16642
|
+
};
|
|
16643
|
+
await walk(normalizedProjectRoot, 0);
|
|
16644
|
+
await includeExplicitConfigPaths(snapshot, unreadablePrefixes, configPaths);
|
|
16645
|
+
return { entries: snapshot, unreadablePrefixes };
|
|
16646
|
+
}
|
|
16647
|
+
async function buildFileSnapshotForPathScan(projectRoot, config, configPaths, targetPath) {
|
|
16648
|
+
const normalizedProjectRoot = path22.resolve(projectRoot);
|
|
16649
|
+
const normalizedTargetPath = path22.resolve(targetPath);
|
|
16650
|
+
if (!isWithinPath(normalizedProjectRoot, normalizedTargetPath)) {
|
|
16651
|
+
return { entries: /* @__PURE__ */ new Map(), unreadablePrefixes: /* @__PURE__ */ new Set() };
|
|
16652
|
+
}
|
|
16653
|
+
const ignoreFilter = createIgnoreFilter(normalizedProjectRoot);
|
|
16654
|
+
const includePatterns = [...config.include, ...config.additionalInclude ?? []];
|
|
16655
|
+
const maxDepth = config.indexing?.maxDepth ?? -1;
|
|
16656
|
+
const explicitConfigPaths = new Set(configPaths.map((configPath) => path22.resolve(configPath)));
|
|
16657
|
+
const snapshot = /* @__PURE__ */ new Map();
|
|
16658
|
+
const unreadablePrefixes = /* @__PURE__ */ new Set();
|
|
16659
|
+
const includeFile = async (filePath) => {
|
|
16660
|
+
const normalizedPath2 = path22.resolve(filePath);
|
|
16661
|
+
if (!explicitConfigPaths.has(normalizedPath2) && !shouldIncludeFile(
|
|
16662
|
+
normalizedPath2,
|
|
16663
|
+
normalizedProjectRoot,
|
|
16664
|
+
includePatterns,
|
|
16665
|
+
config.exclude,
|
|
16666
|
+
ignoreFilter
|
|
16667
|
+
)) return;
|
|
16668
|
+
const stat5 = await readStatIfFile(normalizedPath2, unreadablePrefixes);
|
|
16669
|
+
if (stat5) snapshot.set(normalizedPath2, { size: stat5.size, mtimeMs: stat5.mtimeMs });
|
|
16670
|
+
};
|
|
16671
|
+
const walk = async (directoryPath, depth) => {
|
|
16672
|
+
let entries;
|
|
16673
|
+
try {
|
|
16674
|
+
entries = await fsPromises4.readdir(directoryPath, { withFileTypes: true });
|
|
16675
|
+
} catch (error) {
|
|
16676
|
+
if (isMissingFsError(error)) return;
|
|
16677
|
+
if (isPermissionFsError(error)) {
|
|
16678
|
+
unreadablePrefixes.add(path22.resolve(directoryPath));
|
|
16679
|
+
return;
|
|
16680
|
+
}
|
|
16681
|
+
throw error;
|
|
16682
|
+
}
|
|
16683
|
+
for (const entry of entries) {
|
|
16684
|
+
const fullPath = path22.join(directoryPath, entry.name);
|
|
16685
|
+
const relativePath = path22.relative(normalizedProjectRoot, fullPath);
|
|
16686
|
+
if (entry.isDirectory()) {
|
|
16687
|
+
if (hasFilteredPathSegment(relativePath, path22.sep) || isRestrictedDirectory(relativePath, path22.sep)) continue;
|
|
16688
|
+
if (ignoreFilter.ignores(relativePath)) continue;
|
|
16689
|
+
if (maxDepth === -1 || depth < maxDepth) await walk(fullPath, depth + 1);
|
|
16690
|
+
} else if (entry.isFile()) {
|
|
16691
|
+
await includeFile(fullPath);
|
|
16692
|
+
}
|
|
16693
|
+
}
|
|
16694
|
+
};
|
|
16695
|
+
const targetStat = await readStatIfFile(normalizedTargetPath, unreadablePrefixes);
|
|
16696
|
+
if (targetStat) await includeFile(normalizedTargetPath);
|
|
16697
|
+
else await walk(normalizedTargetPath, 0);
|
|
16698
|
+
await includeExplicitConfigPathsInPath(snapshot, unreadablePrefixes, configPaths, normalizedTargetPath);
|
|
16699
|
+
return { entries: snapshot, unreadablePrefixes };
|
|
16700
|
+
}
|
|
16701
|
+
function completeFileSnapshot(previous, scan) {
|
|
16702
|
+
const completed = new Map(scan.entries);
|
|
16703
|
+
for (const unreadablePrefix of scan.unreadablePrefixes) {
|
|
16704
|
+
for (const [entryPath, entry] of previous) {
|
|
16705
|
+
if (isWithinPath(unreadablePrefix, entryPath) && !completed.has(entryPath)) completed.set(entryPath, entry);
|
|
16706
|
+
}
|
|
16707
|
+
}
|
|
16708
|
+
return completed;
|
|
16709
|
+
}
|
|
16710
|
+
async function includeExplicitConfigPaths(snapshot, unreadablePrefixes, configPaths) {
|
|
16711
|
+
for (const configPath of [...new Set(configPaths.map((value) => path22.resolve(value)))]) {
|
|
16712
|
+
if (snapshot.has(configPath)) continue;
|
|
16713
|
+
const stat5 = await readStatIfFile(configPath, unreadablePrefixes);
|
|
16714
|
+
if (stat5) snapshot.set(configPath, { size: stat5.size, mtimeMs: stat5.mtimeMs });
|
|
16715
|
+
}
|
|
16716
|
+
}
|
|
16717
|
+
async function includeExplicitConfigPathsInPath(snapshot, unreadablePrefixes, configPaths, targetPath) {
|
|
16718
|
+
await includeExplicitConfigPaths(
|
|
16719
|
+
snapshot,
|
|
16720
|
+
unreadablePrefixes,
|
|
16721
|
+
configPaths.filter((configPath) => isWithinPath(targetPath, path22.resolve(configPath)))
|
|
16722
|
+
);
|
|
16723
|
+
}
|
|
16724
|
+
function isWithinPath(parentPath, childPath) {
|
|
16725
|
+
const relativePath = path22.relative(parentPath, childPath);
|
|
16726
|
+
return relativePath === "" || !relativePath.startsWith(`..${path22.sep}`) && relativePath !== ".." && !path22.isAbsolute(relativePath);
|
|
16727
|
+
}
|
|
16728
|
+
async function readStatIfFile(filePath, unreadablePrefixes) {
|
|
16729
|
+
try {
|
|
16730
|
+
const stat5 = await fsPromises4.stat(filePath);
|
|
16731
|
+
return stat5.isFile() ? stat5 : null;
|
|
16732
|
+
} catch (error) {
|
|
16733
|
+
if (isMissingFsError(error)) return null;
|
|
16734
|
+
if (isPermissionFsError(error)) {
|
|
16735
|
+
unreadablePrefixes.add(path22.resolve(filePath));
|
|
16736
|
+
return null;
|
|
16737
|
+
}
|
|
16738
|
+
throw error;
|
|
16739
|
+
}
|
|
16740
|
+
}
|
|
16741
|
+
function isMissingFsError(error) {
|
|
16742
|
+
return error instanceof Error && ["ENOENT", "ENOTDIR"].includes(error.code ?? "");
|
|
16743
|
+
}
|
|
16744
|
+
function isPermissionFsError(error) {
|
|
16745
|
+
return error instanceof Error && ["EACCES", "EPERM"].includes(error.code ?? "");
|
|
16746
|
+
}
|
|
16747
|
+
var diffTypeOrder = { add: 0, change: 1, unlink: 2 };
|
|
16748
|
+
function diffFileSnapshots(previous, current, forcedChanges = /* @__PURE__ */ new Set()) {
|
|
16749
|
+
const changes = [];
|
|
16750
|
+
for (const [filePath, previousEntry] of previous) {
|
|
16751
|
+
const currentEntry = current.get(filePath);
|
|
16752
|
+
if (!currentEntry) changes.push({ type: "unlink", path: filePath });
|
|
16753
|
+
else if (forcedChanges.has(filePath) || currentEntry.size !== previousEntry.size || currentEntry.mtimeMs !== previousEntry.mtimeMs) {
|
|
16754
|
+
changes.push({ type: "change", path: filePath });
|
|
16755
|
+
}
|
|
16756
|
+
}
|
|
16757
|
+
for (const [filePath] of current) {
|
|
16758
|
+
if (!previous.has(filePath)) changes.push({ type: "add", path: filePath });
|
|
16759
|
+
}
|
|
16760
|
+
return changes.sort((left, right) => left.path.localeCompare(right.path) || diffTypeOrder[left.type] - diffTypeOrder[right.type]);
|
|
16761
|
+
}
|
|
16762
|
+
|
|
16763
|
+
// src/watcher/snapshot-reconciler.ts
|
|
16764
|
+
var FileSnapshotReconciler = class {
|
|
16765
|
+
constructor(projectRoot, config, configPaths) {
|
|
16766
|
+
this.projectRoot = projectRoot;
|
|
16767
|
+
this.config = config;
|
|
16768
|
+
this.configPaths = configPaths;
|
|
16769
|
+
}
|
|
16770
|
+
projectRoot;
|
|
16771
|
+
config;
|
|
16772
|
+
configPaths;
|
|
16773
|
+
snapshot = null;
|
|
16774
|
+
reconciliationTail = Promise.resolve();
|
|
16775
|
+
async initialize() {
|
|
16776
|
+
this.snapshot = (await buildFileSnapshotScan(this.projectRoot, this.config, this.configPaths)).entries;
|
|
16777
|
+
}
|
|
16778
|
+
async reconcile(invalidations = []) {
|
|
16779
|
+
if (this.snapshot === null) {
|
|
16780
|
+
throw new Error("FileSnapshotReconciler is not initialized. Call initialize() before reconcile().");
|
|
16781
|
+
}
|
|
16782
|
+
const reconciliation = this.reconciliationTail.then(async () => {
|
|
16783
|
+
const previousSnapshot = this.snapshot;
|
|
16784
|
+
if (previousSnapshot === null) {
|
|
16785
|
+
throw new Error("FileSnapshotReconciler is not initialized. Call initialize() before reconcile().");
|
|
16786
|
+
}
|
|
16787
|
+
const normalizedInvalidations = invalidations.map((invalidation) => typeof invalidation === "string" || invalidation === null ? { path: invalidation, forceChange: false } : { path: invalidation.path, forceChange: invalidation.forceChange === true });
|
|
16788
|
+
const scopedPaths = normalizedInvalidations.map((invalidation) => invalidation.path).filter((filePath) => filePath !== null);
|
|
16789
|
+
const scan = scopedPaths.length === 0 || scopedPaths.length !== normalizedInvalidations.length ? await buildFileSnapshotScan(this.projectRoot, this.config, this.configPaths) : await this.reconcilePaths(previousSnapshot, scopedPaths);
|
|
16790
|
+
const nextSnapshot = completeFileSnapshot(previousSnapshot, scan);
|
|
16791
|
+
const forcedChanges = new Set(normalizedInvalidations.filter((invalidation) => invalidation.path !== null && invalidation.forceChange).map((invalidation) => invalidation.path));
|
|
16792
|
+
const changes = diffFileSnapshots(previousSnapshot, nextSnapshot, forcedChanges);
|
|
16793
|
+
this.snapshot = nextSnapshot;
|
|
16794
|
+
return changes;
|
|
16795
|
+
});
|
|
16796
|
+
this.reconciliationTail = reconciliation.then(() => void 0, () => void 0);
|
|
16797
|
+
return reconciliation;
|
|
16798
|
+
}
|
|
16799
|
+
async reconcilePaths(previousSnapshot, invalidatedPaths) {
|
|
16800
|
+
const scopes = this.getScopes(invalidatedPaths);
|
|
16801
|
+
const entries = new Map(previousSnapshot);
|
|
16802
|
+
const unreadablePrefixes = /* @__PURE__ */ new Set();
|
|
16803
|
+
for (const scope of scopes) {
|
|
16804
|
+
for (const previousPath of entries.keys()) {
|
|
16805
|
+
if (isWithinPath(scope, previousPath)) entries.delete(previousPath);
|
|
16806
|
+
}
|
|
16807
|
+
const scopedScan = await buildFileSnapshotForPathScan(this.projectRoot, this.config, this.configPaths, scope);
|
|
16808
|
+
for (const [filePath, entry] of scopedScan.entries) entries.set(filePath, entry);
|
|
16809
|
+
for (const unreadablePrefix of scopedScan.unreadablePrefixes) unreadablePrefixes.add(unreadablePrefix);
|
|
16810
|
+
}
|
|
16811
|
+
return { entries, unreadablePrefixes };
|
|
16812
|
+
}
|
|
16813
|
+
getScopes(invalidatedPaths) {
|
|
16814
|
+
const uniquePaths = [...new Set(invalidatedPaths)].sort((left, right) => left.length - right.length);
|
|
16815
|
+
return uniquePaths.filter((candidate, index) => !uniquePaths.slice(0, index).some(
|
|
16816
|
+
(ancestor) => isWithinPath(ancestor, candidate)
|
|
16817
|
+
));
|
|
16818
|
+
}
|
|
16819
|
+
};
|
|
16820
|
+
|
|
16821
|
+
// src/watcher/file-watcher.ts
|
|
16602
16822
|
var FileWatcher = class {
|
|
16603
16823
|
watcher = null;
|
|
16604
16824
|
projectRoot;
|
|
16605
16825
|
config;
|
|
16606
16826
|
configPath;
|
|
16827
|
+
backend;
|
|
16607
16828
|
projectConfigPaths;
|
|
16608
16829
|
pendingChanges = /* @__PURE__ */ new Map();
|
|
16609
16830
|
debounceTimer = null;
|
|
@@ -16613,44 +16834,74 @@ var FileWatcher = class {
|
|
|
16613
16834
|
resolveReady = null;
|
|
16614
16835
|
pollingFallbackAttempted = false;
|
|
16615
16836
|
pendingClose = null;
|
|
16837
|
+
startupReadySignals = 1;
|
|
16838
|
+
nativeWatcher = null;
|
|
16839
|
+
nativeReconciler = null;
|
|
16840
|
+
nativeSetupGeneration = 0;
|
|
16841
|
+
nativeStarting = false;
|
|
16842
|
+
nativeInitializing = false;
|
|
16843
|
+
nativeReconcileTimer = null;
|
|
16844
|
+
nativeInvalidatedPaths = /* @__PURE__ */ new Map();
|
|
16845
|
+
configPathStates = /* @__PURE__ */ new Map();
|
|
16616
16846
|
constructor(projectRoot, config, host, options = {}) {
|
|
16617
16847
|
this.projectRoot = projectRoot;
|
|
16618
16848
|
this.config = config;
|
|
16849
|
+
this.backend = options.backend ?? "auto";
|
|
16619
16850
|
this.configPath = options.configPath;
|
|
16620
16851
|
this.projectConfigPaths = options.configPath ? [options.configPath] : getProjectConfigCandidatePaths(projectRoot, host);
|
|
16621
16852
|
}
|
|
16622
16853
|
start(handler) {
|
|
16623
|
-
if (this.watcher) {
|
|
16854
|
+
if (this.watcher || this.nativeWatcher || this.nativeStarting) {
|
|
16624
16855
|
return;
|
|
16625
16856
|
}
|
|
16626
16857
|
this.onChanges = handler;
|
|
16627
16858
|
this.pollingFallbackAttempted = false;
|
|
16628
16859
|
this.resetReady();
|
|
16860
|
+
if (this.shouldUseNativeWatcher()) {
|
|
16861
|
+
if (this.hasExternalConfigWatchTarget()) {
|
|
16862
|
+
this.setStartupReadySignals(2);
|
|
16863
|
+
this.startExternalConfigWatcher();
|
|
16864
|
+
}
|
|
16865
|
+
this.nativeStarting = true;
|
|
16866
|
+
void this.createNativeWatcher();
|
|
16867
|
+
return;
|
|
16868
|
+
}
|
|
16629
16869
|
this.createWatcher();
|
|
16630
16870
|
}
|
|
16631
16871
|
resetReady() {
|
|
16632
|
-
this.readyPromise = new Promise((
|
|
16633
|
-
this.resolveReady =
|
|
16872
|
+
this.readyPromise = new Promise((resolve17) => {
|
|
16873
|
+
this.resolveReady = resolve17;
|
|
16634
16874
|
});
|
|
16875
|
+
this.startupReadySignals = 1;
|
|
16635
16876
|
}
|
|
16636
|
-
|
|
16637
|
-
|
|
16638
|
-
|
|
16639
|
-
|
|
16640
|
-
|
|
16641
|
-
|
|
16642
|
-
|
|
16643
|
-
|
|
16644
|
-
|
|
16645
|
-
}).map((projectConfigPath) => (0, import_fs14.existsSync)(projectConfigPath) ? projectConfigPath : this.getNearestExistingDirectory(path21.dirname(projectConfigPath)));
|
|
16646
|
-
const uniqueExternalConfigTargets = [...new Set(externalConfigTargets)];
|
|
16647
|
-
if (uniqueExternalConfigTargets.length > 0) {
|
|
16648
|
-
watchTargets = [this.projectRoot, ...uniqueExternalConfigTargets];
|
|
16649
|
-
}
|
|
16877
|
+
setStartupReadySignals(expectedSignals) {
|
|
16878
|
+
if (!this.readyPromise) {
|
|
16879
|
+
return;
|
|
16880
|
+
}
|
|
16881
|
+
this.startupReadySignals = Math.max(0, expectedSignals);
|
|
16882
|
+
}
|
|
16883
|
+
reportStartupReadySignal() {
|
|
16884
|
+
if (!this.readyPromise || !this.resolveReady) {
|
|
16885
|
+
return;
|
|
16650
16886
|
}
|
|
16887
|
+
if (this.startupReadySignals <= 0) {
|
|
16888
|
+
return;
|
|
16889
|
+
}
|
|
16890
|
+
this.startupReadySignals -= 1;
|
|
16891
|
+
if (this.startupReadySignals !== 0) {
|
|
16892
|
+
return;
|
|
16893
|
+
}
|
|
16894
|
+
this.resolveReady();
|
|
16895
|
+
this.resolveReady = null;
|
|
16896
|
+
}
|
|
16897
|
+
createWatcher(watchTargets, usePolling = false, reportsStartupReady = true) {
|
|
16898
|
+
let reportedStartupReady = false;
|
|
16899
|
+
this.configPathStates = this.getConfigPathStates();
|
|
16900
|
+
const ignoreFilter = createIgnoreFilter(this.projectRoot);
|
|
16901
|
+
const resolvedWatchTargets = watchTargets ?? this.getFullChokidarWatchTargets();
|
|
16651
16902
|
const watcherOptions = {
|
|
16652
16903
|
ignored: (filePath) => {
|
|
16653
|
-
const relativePath =
|
|
16904
|
+
const relativePath = path23.relative(this.projectRoot, filePath);
|
|
16654
16905
|
if (!relativePath) return false;
|
|
16655
16906
|
if (this.isProjectConfigPathOrAncestor(relativePath)) {
|
|
16656
16907
|
return false;
|
|
@@ -16658,10 +16909,10 @@ var FileWatcher = class {
|
|
|
16658
16909
|
if (this.isOutsideProjectPath(relativePath)) {
|
|
16659
16910
|
return true;
|
|
16660
16911
|
}
|
|
16661
|
-
if (hasFilteredPathSegment(relativePath,
|
|
16912
|
+
if (hasFilteredPathSegment(relativePath, path23.sep)) {
|
|
16662
16913
|
return true;
|
|
16663
16914
|
}
|
|
16664
|
-
if (isRestrictedDirectory(relativePath,
|
|
16915
|
+
if (isRestrictedDirectory(relativePath, path23.sep)) {
|
|
16665
16916
|
return true;
|
|
16666
16917
|
}
|
|
16667
16918
|
if (ignoreFilter.ignores(relativePath)) {
|
|
@@ -16694,10 +16945,13 @@ var FileWatcher = class {
|
|
|
16694
16945
|
watcher = new FSWatcher(watcherOptions);
|
|
16695
16946
|
}
|
|
16696
16947
|
this.watcher = watcher;
|
|
16697
|
-
watcher.
|
|
16948
|
+
watcher.on("ready", () => {
|
|
16698
16949
|
if (this.watcher !== watcher) return;
|
|
16699
|
-
this.
|
|
16700
|
-
|
|
16950
|
+
this.reconcileConfigPathStates();
|
|
16951
|
+
if (reportsStartupReady) {
|
|
16952
|
+
this.reportStartupReadySignal();
|
|
16953
|
+
reportedStartupReady = true;
|
|
16954
|
+
}
|
|
16701
16955
|
});
|
|
16702
16956
|
watcher.on("error", (error) => {
|
|
16703
16957
|
const err = error instanceof Error ? error : null;
|
|
@@ -16711,10 +16965,13 @@ var FileWatcher = class {
|
|
|
16711
16965
|
console.error("[codebase-index] Failed to close exhausted file watcher:", closeError);
|
|
16712
16966
|
});
|
|
16713
16967
|
if (this.onChanges) {
|
|
16968
|
+
const replacementReportsStartupReady = reportsStartupReady || reportedStartupReady;
|
|
16714
16969
|
if (!this.resolveReady) {
|
|
16715
16970
|
this.resetReady();
|
|
16971
|
+
} else if (reportedStartupReady) {
|
|
16972
|
+
this.startupReadySignals += 1;
|
|
16716
16973
|
}
|
|
16717
|
-
this.createWatcher(true);
|
|
16974
|
+
this.createWatcher(resolvedWatchTargets, true, replacementReportsStartupReady);
|
|
16718
16975
|
} else {
|
|
16719
16976
|
this.watcher = null;
|
|
16720
16977
|
}
|
|
@@ -16725,13 +16982,166 @@ var FileWatcher = class {
|
|
|
16725
16982
|
watcher.on("add", (filePath) => this.handleChange(watcher, "add", filePath));
|
|
16726
16983
|
watcher.on("change", (filePath) => this.handleChange(watcher, "change", filePath));
|
|
16727
16984
|
watcher.on("unlink", (filePath) => this.handleChange(watcher, "unlink", filePath));
|
|
16728
|
-
watcher.add(
|
|
16985
|
+
watcher.add(resolvedWatchTargets);
|
|
16986
|
+
}
|
|
16987
|
+
shouldUseNativeWatcher() {
|
|
16988
|
+
if (this.backend === "chokidar") {
|
|
16989
|
+
return false;
|
|
16990
|
+
}
|
|
16991
|
+
return true;
|
|
16992
|
+
}
|
|
16993
|
+
getFullChokidarWatchTargets() {
|
|
16994
|
+
if (this.configPath) {
|
|
16995
|
+
return [this.projectRoot, this.configPath];
|
|
16996
|
+
}
|
|
16997
|
+
const externalConfigTargets = this.getExternalConfigWatchTargets();
|
|
16998
|
+
if (externalConfigTargets.length === 0) {
|
|
16999
|
+
return this.projectRoot;
|
|
17000
|
+
}
|
|
17001
|
+
return [this.projectRoot, ...externalConfigTargets];
|
|
17002
|
+
}
|
|
17003
|
+
getExternalConfigWatchTargets() {
|
|
17004
|
+
return [...new Set(
|
|
17005
|
+
this.projectConfigPaths.filter((projectConfigPath) => {
|
|
17006
|
+
const relativeConfigPath = path23.relative(this.projectRoot, projectConfigPath);
|
|
17007
|
+
return this.isOutsideProjectPath(relativeConfigPath);
|
|
17008
|
+
}).map((projectConfigPath) => {
|
|
17009
|
+
if ((0, import_fs14.existsSync)(projectConfigPath)) {
|
|
17010
|
+
return projectConfigPath;
|
|
17011
|
+
}
|
|
17012
|
+
return this.getNearestExistingDirectory(path23.dirname(projectConfigPath));
|
|
17013
|
+
})
|
|
17014
|
+
)];
|
|
17015
|
+
}
|
|
17016
|
+
hasExternalConfigWatchTarget() {
|
|
17017
|
+
return this.getExternalConfigWatchTargets().length > 0;
|
|
17018
|
+
}
|
|
17019
|
+
startExternalConfigWatcher(usePolling = false) {
|
|
17020
|
+
const externalTargets = this.getExternalConfigWatchTargets();
|
|
17021
|
+
if (externalTargets.length === 0) {
|
|
17022
|
+
return;
|
|
17023
|
+
}
|
|
17024
|
+
this.createWatcher(externalTargets, usePolling);
|
|
17025
|
+
}
|
|
17026
|
+
async createNativeWatcher() {
|
|
17027
|
+
const generation = ++this.nativeSetupGeneration;
|
|
17028
|
+
const reconciler = new FileSnapshotReconciler(this.projectRoot, this.config, this.projectConfigPaths);
|
|
17029
|
+
const watcher = new NativeRecursiveWatcher(
|
|
17030
|
+
this.projectRoot,
|
|
17031
|
+
(filePath) => this.scheduleNativeReconciliation(generation, filePath),
|
|
17032
|
+
{ onError: (error) => void this.fallbackFromNativeWatcher(generation, error) }
|
|
17033
|
+
);
|
|
17034
|
+
this.nativeReconciler = reconciler;
|
|
17035
|
+
this.nativeWatcher = watcher;
|
|
17036
|
+
this.nativeInitializing = true;
|
|
17037
|
+
try {
|
|
17038
|
+
watcher.start();
|
|
17039
|
+
if (!this.isCurrentNativeSetup(generation)) {
|
|
17040
|
+
await watcher.stop();
|
|
17041
|
+
return;
|
|
17042
|
+
}
|
|
17043
|
+
await reconciler.initialize();
|
|
17044
|
+
if (!this.isCurrentNativeSetup(generation) || this.nativeWatcher !== watcher) {
|
|
17045
|
+
await watcher.stop();
|
|
17046
|
+
return;
|
|
17047
|
+
}
|
|
17048
|
+
this.nativeStarting = false;
|
|
17049
|
+
this.nativeInitializing = false;
|
|
17050
|
+
await this.reconcileNativeWatcherWithPendingInvalidations(generation);
|
|
17051
|
+
this.reportStartupReadySignal();
|
|
17052
|
+
} catch (error) {
|
|
17053
|
+
if (!this.isCurrentNativeSetup(generation)) return;
|
|
17054
|
+
this.nativeInitializing = false;
|
|
17055
|
+
if (this.nativeWatcher) {
|
|
17056
|
+
await this.fallbackFromNativeWatcher(generation, error);
|
|
17057
|
+
return;
|
|
17058
|
+
}
|
|
17059
|
+
this.nativeStarting = false;
|
|
17060
|
+
const externalWatcher = this.watcher;
|
|
17061
|
+
this.watcher = null;
|
|
17062
|
+
this.nativeReconciler = null;
|
|
17063
|
+
await externalWatcher?.close();
|
|
17064
|
+
console.warn("[codebase-index] Native recursive watcher unavailable; using Chokidar fallback.", error);
|
|
17065
|
+
this.setStartupReadySignals(1);
|
|
17066
|
+
this.createWatcher();
|
|
17067
|
+
}
|
|
17068
|
+
}
|
|
17069
|
+
isCurrentNativeSetup(generation) {
|
|
17070
|
+
return this.nativeSetupGeneration === generation && this.onChanges !== null;
|
|
17071
|
+
}
|
|
17072
|
+
scheduleNativeReconciliation(generation, filePath) {
|
|
17073
|
+
if (!this.isCurrentNativeSetup(generation)) return;
|
|
17074
|
+
const requiresFullReconciliation = filePath === path23.join(this.projectRoot, ".gitignore");
|
|
17075
|
+
const invalidatedPath = requiresFullReconciliation ? null : filePath;
|
|
17076
|
+
this.nativeInvalidatedPaths.set(invalidatedPath, invalidatedPath !== null);
|
|
17077
|
+
if (this.nativeReconcileTimer) {
|
|
17078
|
+
clearTimeout(this.nativeReconcileTimer);
|
|
17079
|
+
}
|
|
17080
|
+
this.nativeReconcileTimer = setTimeout(() => {
|
|
17081
|
+
this.nativeReconcileTimer = null;
|
|
17082
|
+
void this.reconcileNativeWatcherFromQueue(generation);
|
|
17083
|
+
}, 100);
|
|
17084
|
+
}
|
|
17085
|
+
reconcileNativeWatcherFromQueue(generation) {
|
|
17086
|
+
if (!this.isCurrentNativeSetup(generation) || this.nativeInitializing) return;
|
|
17087
|
+
const invalidatedPaths = this.popNativeInvalidations();
|
|
17088
|
+
if (invalidatedPaths.length === 0) return;
|
|
17089
|
+
void this.reconcileNativeWatcher(generation, invalidatedPaths);
|
|
17090
|
+
}
|
|
17091
|
+
async reconcileNativeWatcher(generation, invalidatedPaths) {
|
|
17092
|
+
if (!this.isCurrentNativeSetup(generation) || !this.nativeReconciler) return;
|
|
17093
|
+
try {
|
|
17094
|
+
const reconciler = this.nativeReconciler;
|
|
17095
|
+
const changes = await reconciler.reconcile(invalidatedPaths);
|
|
17096
|
+
if (!this.isCurrentNativeSetup(generation) || this.nativeReconciler !== reconciler) return;
|
|
17097
|
+
this.recordChanges(changes);
|
|
17098
|
+
} catch (error) {
|
|
17099
|
+
await this.fallbackFromNativeWatcher(generation, error);
|
|
17100
|
+
}
|
|
17101
|
+
}
|
|
17102
|
+
async reconcileNativeWatcherWithPendingInvalidations(generation) {
|
|
17103
|
+
const invalidatedPaths = this.popNativeInvalidations();
|
|
17104
|
+
if (invalidatedPaths.length === 0) return;
|
|
17105
|
+
await this.reconcileNativeWatcher(generation, invalidatedPaths);
|
|
17106
|
+
}
|
|
17107
|
+
popNativeInvalidations() {
|
|
17108
|
+
if (this.nativeInvalidatedPaths.size === 0) return [];
|
|
17109
|
+
const invalidations = [...this.nativeInvalidatedPaths].map(([invalidatedPath, forceChange]) => ({
|
|
17110
|
+
path: invalidatedPath,
|
|
17111
|
+
forceChange
|
|
17112
|
+
}));
|
|
17113
|
+
this.nativeInvalidatedPaths.clear();
|
|
17114
|
+
return invalidations;
|
|
17115
|
+
}
|
|
17116
|
+
async fallbackFromNativeWatcher(generation, error) {
|
|
17117
|
+
if (!this.isCurrentNativeSetup(generation)) return;
|
|
17118
|
+
const watcher = this.nativeWatcher;
|
|
17119
|
+
const externalWatcher = this.watcher;
|
|
17120
|
+
this.nativeWatcher = null;
|
|
17121
|
+
this.watcher = null;
|
|
17122
|
+
this.nativeReconciler = null;
|
|
17123
|
+
this.nativeStarting = false;
|
|
17124
|
+
this.nativeInitializing = false;
|
|
17125
|
+
this.nativeSetupGeneration += 1;
|
|
17126
|
+
if (this.nativeReconcileTimer) {
|
|
17127
|
+
clearTimeout(this.nativeReconcileTimer);
|
|
17128
|
+
this.nativeReconcileTimer = null;
|
|
17129
|
+
}
|
|
17130
|
+
this.nativeInvalidatedPaths.clear();
|
|
17131
|
+
this.setStartupReadySignals(1);
|
|
17132
|
+
console.warn("[codebase-index] Native recursive watcher failed; using Chokidar fallback.", error);
|
|
17133
|
+
await watcher?.stop();
|
|
17134
|
+
await externalWatcher?.close();
|
|
17135
|
+
if (this.onChanges) {
|
|
17136
|
+
this.createWatcher();
|
|
17137
|
+
}
|
|
16729
17138
|
}
|
|
16730
17139
|
handleChange(watcher, type, filePath) {
|
|
16731
17140
|
if (this.watcher !== watcher) {
|
|
16732
17141
|
return;
|
|
16733
17142
|
}
|
|
16734
17143
|
if (this.isProjectConfigPath(filePath)) {
|
|
17144
|
+
this.updateConfigPathState(filePath);
|
|
16735
17145
|
this.pendingChanges.set(filePath, type);
|
|
16736
17146
|
this.scheduleFlush();
|
|
16737
17147
|
return;
|
|
@@ -16746,27 +17156,33 @@ var FileWatcher = class {
|
|
|
16746
17156
|
)) {
|
|
16747
17157
|
return;
|
|
16748
17158
|
}
|
|
16749
|
-
this.
|
|
17159
|
+
this.recordChanges([{ path: filePath, type }]);
|
|
17160
|
+
}
|
|
17161
|
+
recordChanges(changes) {
|
|
17162
|
+
if (changes.length === 0) return;
|
|
17163
|
+
for (const change of changes) {
|
|
17164
|
+
this.pendingChanges.set(change.path, change.type);
|
|
17165
|
+
}
|
|
16750
17166
|
this.scheduleFlush();
|
|
16751
17167
|
}
|
|
16752
17168
|
isProjectConfigPath(filePath) {
|
|
16753
|
-
const relativePath =
|
|
16754
|
-
const normalizedRelativePath =
|
|
17169
|
+
const relativePath = path23.relative(this.projectRoot, filePath);
|
|
17170
|
+
const normalizedRelativePath = path23.normalize(relativePath);
|
|
16755
17171
|
return this.getProjectConfigRelativePaths().some((configPath) => configPath === normalizedRelativePath);
|
|
16756
17172
|
}
|
|
16757
17173
|
isProjectConfigPathOrAncestor(relativePath) {
|
|
16758
|
-
const normalizedRelativePath =
|
|
17174
|
+
const normalizedRelativePath = path23.normalize(relativePath);
|
|
16759
17175
|
return this.getProjectConfigRelativePaths().some(
|
|
16760
|
-
(configPath) => configPath === normalizedRelativePath || configPath.startsWith(`${normalizedRelativePath}${
|
|
17176
|
+
(configPath) => configPath === normalizedRelativePath || configPath.startsWith(`${normalizedRelativePath}${path23.sep}`)
|
|
16761
17177
|
);
|
|
16762
17178
|
}
|
|
16763
17179
|
isOutsideProjectPath(relativePath) {
|
|
16764
|
-
return relativePath === ".." || relativePath.startsWith(`..${
|
|
17180
|
+
return relativePath === ".." || relativePath.startsWith(`..${path23.sep}`) || path23.isAbsolute(relativePath);
|
|
16765
17181
|
}
|
|
16766
17182
|
getNearestExistingDirectory(directoryPath) {
|
|
16767
17183
|
let candidate = directoryPath;
|
|
16768
17184
|
while (!(0, import_fs14.existsSync)(candidate)) {
|
|
16769
|
-
const parent =
|
|
17185
|
+
const parent = path23.dirname(candidate);
|
|
16770
17186
|
if (parent === candidate) break;
|
|
16771
17187
|
candidate = parent;
|
|
16772
17188
|
}
|
|
@@ -16774,9 +17190,51 @@ var FileWatcher = class {
|
|
|
16774
17190
|
}
|
|
16775
17191
|
getProjectConfigRelativePaths() {
|
|
16776
17192
|
return this.projectConfigPaths.map(
|
|
16777
|
-
(configPath) =>
|
|
17193
|
+
(configPath) => path23.normalize(path23.relative(this.projectRoot, configPath))
|
|
16778
17194
|
);
|
|
16779
17195
|
}
|
|
17196
|
+
getConfigPathStates() {
|
|
17197
|
+
const states = /* @__PURE__ */ new Map();
|
|
17198
|
+
for (const configPath of this.projectConfigPaths) {
|
|
17199
|
+
const state = this.getConfigPathState(configPath);
|
|
17200
|
+
if (state) states.set(configPath, state);
|
|
17201
|
+
}
|
|
17202
|
+
return states;
|
|
17203
|
+
}
|
|
17204
|
+
getConfigPathState(configPath) {
|
|
17205
|
+
try {
|
|
17206
|
+
const stats = (0, import_fs14.statSync)(configPath);
|
|
17207
|
+
return stats.isFile() ? { mtimeMs: stats.mtimeMs, size: stats.size } : void 0;
|
|
17208
|
+
} catch (error) {
|
|
17209
|
+
void error;
|
|
17210
|
+
return void 0;
|
|
17211
|
+
}
|
|
17212
|
+
}
|
|
17213
|
+
updateConfigPathState(configPath) {
|
|
17214
|
+
const state = this.getConfigPathState(configPath);
|
|
17215
|
+
if (state) {
|
|
17216
|
+
this.configPathStates.set(configPath, state);
|
|
17217
|
+
} else {
|
|
17218
|
+
this.configPathStates.delete(configPath);
|
|
17219
|
+
}
|
|
17220
|
+
}
|
|
17221
|
+
reconcileConfigPathStates() {
|
|
17222
|
+
const nextStates = this.getConfigPathStates();
|
|
17223
|
+
const changes = [];
|
|
17224
|
+
for (const configPath of this.projectConfigPaths) {
|
|
17225
|
+
const previous = this.configPathStates.get(configPath);
|
|
17226
|
+
const next = nextStates.get(configPath);
|
|
17227
|
+
if (!previous && next) {
|
|
17228
|
+
changes.push({ path: configPath, type: "add" });
|
|
17229
|
+
} else if (previous && !next) {
|
|
17230
|
+
changes.push({ path: configPath, type: "unlink" });
|
|
17231
|
+
} else if (previous && next && (previous.size !== next.size || previous.mtimeMs !== next.mtimeMs)) {
|
|
17232
|
+
changes.push({ path: configPath, type: "change" });
|
|
17233
|
+
}
|
|
17234
|
+
}
|
|
17235
|
+
this.configPathStates = nextStates;
|
|
17236
|
+
this.recordChanges(changes);
|
|
17237
|
+
}
|
|
16780
17238
|
scheduleFlush() {
|
|
16781
17239
|
if (this.debounceTimer) {
|
|
16782
17240
|
clearTimeout(this.debounceTimer);
|
|
@@ -16790,7 +17248,7 @@ var FileWatcher = class {
|
|
|
16790
17248
|
return;
|
|
16791
17249
|
}
|
|
16792
17250
|
const changes = Array.from(this.pendingChanges.entries()).map(
|
|
16793
|
-
([
|
|
17251
|
+
([path30, type]) => ({ path: path30, type })
|
|
16794
17252
|
);
|
|
16795
17253
|
this.pendingChanges.clear();
|
|
16796
17254
|
try {
|
|
@@ -16804,20 +17262,31 @@ var FileWatcher = class {
|
|
|
16804
17262
|
clearTimeout(this.debounceTimer);
|
|
16805
17263
|
this.debounceTimer = null;
|
|
16806
17264
|
}
|
|
17265
|
+
if (this.nativeReconcileTimer) {
|
|
17266
|
+
clearTimeout(this.nativeReconcileTimer);
|
|
17267
|
+
this.nativeReconcileTimer = null;
|
|
17268
|
+
}
|
|
17269
|
+
this.nativeInvalidatedPaths.clear();
|
|
16807
17270
|
const watcher = this.watcher;
|
|
17271
|
+
const nativeWatcher = this.nativeWatcher;
|
|
16808
17272
|
const pendingClose = this.pendingClose;
|
|
16809
17273
|
const resolveReady = this.resolveReady;
|
|
16810
17274
|
this.watcher = null;
|
|
17275
|
+
this.nativeWatcher = null;
|
|
17276
|
+
this.nativeReconciler = null;
|
|
17277
|
+
this.nativeStarting = false;
|
|
17278
|
+
this.nativeInitializing = false;
|
|
17279
|
+
this.nativeSetupGeneration += 1;
|
|
16811
17280
|
this.pendingClose = null;
|
|
16812
17281
|
this.resolveReady = null;
|
|
16813
17282
|
this.readyPromise = null;
|
|
16814
17283
|
this.pendingChanges.clear();
|
|
16815
17284
|
this.onChanges = null;
|
|
16816
|
-
await Promise.all([watcher?.close(), pendingClose]);
|
|
17285
|
+
await Promise.all([watcher?.close(), nativeWatcher?.stop(), pendingClose]);
|
|
16817
17286
|
resolveReady?.();
|
|
16818
17287
|
}
|
|
16819
17288
|
isRunning() {
|
|
16820
|
-
return this.watcher !== null;
|
|
17289
|
+
return this.watcher !== null || this.nativeWatcher !== null || this.nativeStarting;
|
|
16821
17290
|
}
|
|
16822
17291
|
async waitUntilReady() {
|
|
16823
17292
|
await (this.readyPromise ?? Promise.resolve());
|
|
@@ -16825,7 +17294,7 @@ var FileWatcher = class {
|
|
|
16825
17294
|
};
|
|
16826
17295
|
|
|
16827
17296
|
// src/watcher/git-head-watcher.ts
|
|
16828
|
-
var
|
|
17297
|
+
var path24 = __toESM(require("path"), 1);
|
|
16829
17298
|
var GitHeadWatcher = class {
|
|
16830
17299
|
watcher = null;
|
|
16831
17300
|
projectRoot;
|
|
@@ -16847,13 +17316,13 @@ var GitHeadWatcher = class {
|
|
|
16847
17316
|
this.readyPromise = Promise.resolve();
|
|
16848
17317
|
return;
|
|
16849
17318
|
}
|
|
16850
|
-
this.readyPromise = new Promise((
|
|
16851
|
-
this.resolveReady =
|
|
17319
|
+
this.readyPromise = new Promise((resolve17) => {
|
|
17320
|
+
this.resolveReady = resolve17;
|
|
16852
17321
|
});
|
|
16853
17322
|
this.onBranchChange = handler;
|
|
16854
17323
|
this.currentBranch = getCurrentBranch(this.projectRoot);
|
|
16855
17324
|
const headPath = getHeadPath(this.projectRoot);
|
|
16856
|
-
const refsPath =
|
|
17325
|
+
const refsPath = path24.join(this.projectRoot, ".git", "refs", "heads");
|
|
16857
17326
|
this.watcher = chokidar_default.watch([headPath, refsPath], {
|
|
16858
17327
|
persistent: true,
|
|
16859
17328
|
ignoreInitial: true,
|
|
@@ -17709,7 +18178,7 @@ async function resolveCodebaseContextUnmeasured(projectRoot, host, input) {
|
|
|
17709
18178
|
const directory = input.directory ?? void 0;
|
|
17710
18179
|
const tokenBudget = input.tokenBudget ?? void 0;
|
|
17711
18180
|
if (from && to) {
|
|
17712
|
-
const
|
|
18181
|
+
const path30 = await getCallGraphPath(
|
|
17713
18182
|
projectRoot,
|
|
17714
18183
|
host,
|
|
17715
18184
|
from,
|
|
@@ -17718,25 +18187,25 @@ async function resolveCodebaseContextUnmeasured(projectRoot, host, input) {
|
|
|
17718
18187
|
fromFilePath,
|
|
17719
18188
|
toFilePath
|
|
17720
18189
|
);
|
|
17721
|
-
const pathText = formatCallGraphPathResult(
|
|
17722
|
-
if (
|
|
18190
|
+
const pathText = formatCallGraphPathResult(path30);
|
|
18191
|
+
if (path30.path.length > 0) {
|
|
17723
18192
|
const fitted2 = fitTextToContextBudget(
|
|
17724
18193
|
pathText,
|
|
17725
18194
|
tokenBudget
|
|
17726
18195
|
);
|
|
17727
18196
|
return {
|
|
17728
18197
|
text: fitted2.text,
|
|
17729
|
-
details: fittedDetails("path", fitted2,
|
|
18198
|
+
details: fittedDetails("path", fitted2, path30.path.length)
|
|
17730
18199
|
};
|
|
17731
18200
|
}
|
|
17732
|
-
if (
|
|
18201
|
+
if (path30.from.status !== "resolved" || path30.to.status !== "resolved") {
|
|
17733
18202
|
const fitted2 = fitTextToContextBudget(pathText, tokenBudget);
|
|
17734
18203
|
return {
|
|
17735
18204
|
text: fitted2.text,
|
|
17736
18205
|
details: fittedDetails("path", fitted2, 0)
|
|
17737
18206
|
};
|
|
17738
18207
|
}
|
|
17739
|
-
const resolvedFrom =
|
|
18208
|
+
const resolvedFrom = path30.from;
|
|
17740
18209
|
const { callers } = await getCallGraphData(projectRoot, host, {
|
|
17741
18210
|
name: to,
|
|
17742
18211
|
direction: "callers",
|
|
@@ -17895,7 +18364,7 @@ async function executeCallGraph(projectRoot, host, args) {
|
|
|
17895
18364
|
return { text: formatCallGraphResult(await getCallGraphData(projectRoot, host, args)) };
|
|
17896
18365
|
}
|
|
17897
18366
|
async function executeCallGraphPath(projectRoot, host, args) {
|
|
17898
|
-
const
|
|
18367
|
+
const path30 = await getCallGraphPath(
|
|
17899
18368
|
projectRoot,
|
|
17900
18369
|
host,
|
|
17901
18370
|
args.from,
|
|
@@ -17904,7 +18373,7 @@ async function executeCallGraphPath(projectRoot, host, args) {
|
|
|
17904
18373
|
args.fromFilePath,
|
|
17905
18374
|
args.toFilePath
|
|
17906
18375
|
);
|
|
17907
|
-
return { text: formatCallGraphPathResult(
|
|
18376
|
+
return { text: formatCallGraphPathResult(path30) };
|
|
17908
18377
|
}
|
|
17909
18378
|
async function executeCodeCommunities(projectRoot, host, args) {
|
|
17910
18379
|
const result = await getCodeCommunities(projectRoot, host, args);
|
|
@@ -17914,11 +18383,11 @@ async function executeCodeCommunities(projectRoot, host, args) {
|
|
|
17914
18383
|
// src/adapters/opencode/tools.ts
|
|
17915
18384
|
var import_fs15 = require("fs");
|
|
17916
18385
|
var os7 = __toESM(require("os"), 1);
|
|
17917
|
-
var
|
|
18386
|
+
var path27 = __toESM(require("path"), 1);
|
|
17918
18387
|
|
|
17919
18388
|
// src/tools/visualize/activity.ts
|
|
17920
18389
|
var import_child_process5 = require("child_process");
|
|
17921
|
-
var
|
|
18390
|
+
var path25 = __toESM(require("path"), 1);
|
|
17922
18391
|
function attachRecentActivity(data, projectRoot) {
|
|
17923
18392
|
const activity = readGitActivity(projectRoot);
|
|
17924
18393
|
const changes = activity.size > 0 ? buildGitChanges(data, activity, projectRoot) : buildGraphChanges(data);
|
|
@@ -18080,7 +18549,7 @@ function normalizePath3(filePath) {
|
|
|
18080
18549
|
return filePath.replace(/\\/g, "/");
|
|
18081
18550
|
}
|
|
18082
18551
|
function toGitRelativePath(projectRoot, filePath) {
|
|
18083
|
-
const relativePath =
|
|
18552
|
+
const relativePath = path25.isAbsolute(filePath) ? path25.relative(projectRoot, filePath) : filePath;
|
|
18084
18553
|
return normalizePath3(relativePath);
|
|
18085
18554
|
}
|
|
18086
18555
|
|
|
@@ -18338,7 +18807,7 @@ render();
|
|
|
18338
18807
|
}
|
|
18339
18808
|
|
|
18340
18809
|
// src/tools/visualize/transform.ts
|
|
18341
|
-
var
|
|
18810
|
+
var path26 = __toESM(require("path"), 1);
|
|
18342
18811
|
|
|
18343
18812
|
// src/tools/visualize/modules.ts
|
|
18344
18813
|
var MAX_MODULES = 18;
|
|
@@ -18471,8 +18940,8 @@ function compactModules(prefixToNodes) {
|
|
|
18471
18940
|
function deriveModules(nodes) {
|
|
18472
18941
|
const initial = /* @__PURE__ */ new Map();
|
|
18473
18942
|
for (const node of nodes) {
|
|
18474
|
-
const
|
|
18475
|
-
const prefix = modulePrefixFromRelativePath(
|
|
18943
|
+
const relative14 = stripToProjectRelative(node.filePath);
|
|
18944
|
+
const prefix = modulePrefixFromRelativePath(relative14);
|
|
18476
18945
|
if (!initial.has(prefix)) initial.set(prefix, []);
|
|
18477
18946
|
initial.get(prefix)?.push(node);
|
|
18478
18947
|
}
|
|
@@ -18598,7 +19067,7 @@ function transformForVisualization(symbols, edges, options = {}) {
|
|
|
18598
19067
|
filePath: s.filePath,
|
|
18599
19068
|
kind: s.kind,
|
|
18600
19069
|
line: s.startLine,
|
|
18601
|
-
directory:
|
|
19070
|
+
directory: path26.dirname(s.filePath),
|
|
18602
19071
|
moduleId: "",
|
|
18603
19072
|
moduleLabel: ""
|
|
18604
19073
|
}));
|
|
@@ -18918,7 +19387,7 @@ var index_visualize = tool({
|
|
|
18918
19387
|
return "No connected symbols found for visualization. Try including orphans with includeOrphans=true, or check that the call graph has resolved edges.";
|
|
18919
19388
|
}
|
|
18920
19389
|
const html = generateVisualizationHtml(vizData);
|
|
18921
|
-
const outputPath =
|
|
19390
|
+
const outputPath = path27.join(os7.tmpdir(), `call-graph-${Date.now()}.html`);
|
|
18922
19391
|
(0, import_fs15.writeFileSync)(outputPath, html, "utf-8");
|
|
18923
19392
|
let result = `Temporal call graph visualization generated: ${outputPath}
|
|
18924
19393
|
|
|
@@ -19025,7 +19494,7 @@ var PI_TOOL_NAMES = [
|
|
|
19025
19494
|
|
|
19026
19495
|
// src/commands/loader.ts
|
|
19027
19496
|
var import_fs16 = require("fs");
|
|
19028
|
-
var
|
|
19497
|
+
var path28 = __toESM(require("path"), 1);
|
|
19029
19498
|
function parseFrontmatter(content) {
|
|
19030
19499
|
const frontmatterRegex = /^---\s*\n([\s\S]*?)\n---\s*\n([\s\S]*)$/;
|
|
19031
19500
|
const match = content.match(frontmatterRegex);
|
|
@@ -19051,7 +19520,7 @@ function loadCommandsFromDirectory(commandsDir) {
|
|
|
19051
19520
|
}
|
|
19052
19521
|
const files = (0, import_fs16.readdirSync)(commandsDir).filter((f) => f.endsWith(".md"));
|
|
19053
19522
|
for (const file of files) {
|
|
19054
|
-
const filePath =
|
|
19523
|
+
const filePath = path28.join(commandsDir, file);
|
|
19055
19524
|
let content;
|
|
19056
19525
|
try {
|
|
19057
19526
|
content = (0, import_fs16.readFileSync)(filePath, "utf-8");
|
|
@@ -19060,7 +19529,7 @@ function loadCommandsFromDirectory(commandsDir) {
|
|
|
19060
19529
|
throw new Error(`Failed to load command file ${filePath}: ${message}`);
|
|
19061
19530
|
}
|
|
19062
19531
|
const { frontmatter, body } = parseFrontmatter(content);
|
|
19063
|
-
const name =
|
|
19532
|
+
const name = path28.basename(file, ".md");
|
|
19064
19533
|
const description = frontmatter.description || `Run the ${name} command`;
|
|
19065
19534
|
commands.set(name, {
|
|
19066
19535
|
description,
|
|
@@ -19395,23 +19864,41 @@ var RoutingHintController = class {
|
|
|
19395
19864
|
// src/adapters/opencode.ts
|
|
19396
19865
|
var import_meta2 = {};
|
|
19397
19866
|
var activeWatchers = /* @__PURE__ */ new Map();
|
|
19398
|
-
|
|
19399
|
-
|
|
19400
|
-
|
|
19401
|
-
existing.
|
|
19402
|
-
|
|
19403
|
-
|
|
19404
|
-
|
|
19405
|
-
|
|
19867
|
+
var watcherReplacementChains = /* @__PURE__ */ new Map();
|
|
19868
|
+
async function replaceActiveWatcher(projectRoot, createNextWatcher) {
|
|
19869
|
+
const chain = (watcherReplacementChains.get(projectRoot) ?? Promise.resolve()).catch(() => void 0).then(async () => {
|
|
19870
|
+
const existing = activeWatchers.get(projectRoot);
|
|
19871
|
+
if (existing) {
|
|
19872
|
+
try {
|
|
19873
|
+
await existing.stop();
|
|
19874
|
+
} catch (error) {
|
|
19875
|
+
console.error("[codebase-index] Failed to stop replaced watcher:", error);
|
|
19876
|
+
throw error;
|
|
19877
|
+
}
|
|
19878
|
+
if (activeWatchers.get(projectRoot) === existing) {
|
|
19879
|
+
activeWatchers.delete(projectRoot);
|
|
19880
|
+
}
|
|
19881
|
+
}
|
|
19882
|
+
if (createNextWatcher) {
|
|
19883
|
+
activeWatchers.set(projectRoot, createNextWatcher());
|
|
19884
|
+
}
|
|
19885
|
+
});
|
|
19886
|
+
watcherReplacementChains.set(projectRoot, chain);
|
|
19887
|
+
try {
|
|
19888
|
+
await chain;
|
|
19889
|
+
} finally {
|
|
19890
|
+
if (watcherReplacementChains.get(projectRoot) === chain) {
|
|
19891
|
+
watcherReplacementChains.delete(projectRoot);
|
|
19892
|
+
}
|
|
19406
19893
|
}
|
|
19407
19894
|
}
|
|
19408
19895
|
function getCommandsDir() {
|
|
19409
19896
|
let currentDir = process.cwd();
|
|
19410
19897
|
if (typeof import_meta2 !== "undefined" && import_meta2.url) {
|
|
19411
|
-
currentDir =
|
|
19898
|
+
currentDir = path29.dirname((0, import_url.fileURLToPath)(import_meta2.url));
|
|
19412
19899
|
}
|
|
19413
|
-
const packageRoot =
|
|
19414
|
-
return
|
|
19900
|
+
const packageRoot = path29.basename(currentDir) === "adapters" ? path29.join(currentDir, "..", "..") : path29.join(currentDir, "..");
|
|
19901
|
+
return path29.join(packageRoot, "commands");
|
|
19415
19902
|
}
|
|
19416
19903
|
function appendRoutingHints(output, hints, preferredRole) {
|
|
19417
19904
|
const preferredBucket = preferredRole === "developer" ? output.developer : output.system;
|
|
@@ -19452,9 +19939,12 @@ var plugin = async ({ directory, worktree }) => {
|
|
|
19452
19939
|
startAutoIndex(projectRoot, "opencode", "startup");
|
|
19453
19940
|
}
|
|
19454
19941
|
if (config.indexing.watchFiles && isValidProject) {
|
|
19455
|
-
replaceActiveWatcher(
|
|
19942
|
+
await replaceActiveWatcher(
|
|
19943
|
+
projectRoot,
|
|
19944
|
+
() => createWatcherWithIndexer(getProjectIndexer, projectRoot, config, "opencode")
|
|
19945
|
+
);
|
|
19456
19946
|
} else {
|
|
19457
|
-
replaceActiveWatcher(projectRoot, null);
|
|
19947
|
+
await replaceActiveWatcher(projectRoot, null);
|
|
19458
19948
|
}
|
|
19459
19949
|
return {
|
|
19460
19950
|
tool: {
|