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.js
CHANGED
|
@@ -328,7 +328,7 @@ var require_ignore = __commonJS({
|
|
|
328
328
|
// path matching.
|
|
329
329
|
// - check `string` either `MODE_IGNORE` or `MODE_CHECK_IGNORE`
|
|
330
330
|
// @returns {TestResult} true if a file is ignored
|
|
331
|
-
test(
|
|
331
|
+
test(path30, checkUnignored, mode) {
|
|
332
332
|
let ignored = false;
|
|
333
333
|
let unignored = false;
|
|
334
334
|
let matchedRule;
|
|
@@ -337,7 +337,7 @@ var require_ignore = __commonJS({
|
|
|
337
337
|
if (unignored === negative && ignored !== unignored || negative && !ignored && !unignored && !checkUnignored) {
|
|
338
338
|
return;
|
|
339
339
|
}
|
|
340
|
-
const matched = rule[mode].test(
|
|
340
|
+
const matched = rule[mode].test(path30);
|
|
341
341
|
if (!matched) {
|
|
342
342
|
return;
|
|
343
343
|
}
|
|
@@ -358,17 +358,17 @@ var require_ignore = __commonJS({
|
|
|
358
358
|
var throwError = (message, Ctor) => {
|
|
359
359
|
throw new Ctor(message);
|
|
360
360
|
};
|
|
361
|
-
var checkPath = (
|
|
362
|
-
if (!isString(
|
|
361
|
+
var checkPath = (path30, originalPath, doThrow) => {
|
|
362
|
+
if (!isString(path30)) {
|
|
363
363
|
return doThrow(
|
|
364
364
|
`path must be a string, but got \`${originalPath}\``,
|
|
365
365
|
TypeError
|
|
366
366
|
);
|
|
367
367
|
}
|
|
368
|
-
if (!
|
|
368
|
+
if (!path30) {
|
|
369
369
|
return doThrow(`path must not be empty`, TypeError);
|
|
370
370
|
}
|
|
371
|
-
if (checkPath.isNotRelative(
|
|
371
|
+
if (checkPath.isNotRelative(path30)) {
|
|
372
372
|
const r = "`path.relative()`d";
|
|
373
373
|
return doThrow(
|
|
374
374
|
`path should be a ${r} string, but got "${originalPath}"`,
|
|
@@ -377,7 +377,7 @@ var require_ignore = __commonJS({
|
|
|
377
377
|
}
|
|
378
378
|
return true;
|
|
379
379
|
};
|
|
380
|
-
var isNotRelative = (
|
|
380
|
+
var isNotRelative = (path30) => REGEX_TEST_INVALID_PATH.test(path30);
|
|
381
381
|
checkPath.isNotRelative = isNotRelative;
|
|
382
382
|
checkPath.convert = (p) => p;
|
|
383
383
|
var Ignore2 = class {
|
|
@@ -407,19 +407,19 @@ var require_ignore = __commonJS({
|
|
|
407
407
|
}
|
|
408
408
|
// @returns {TestResult}
|
|
409
409
|
_test(originalPath, cache, checkUnignored, slices) {
|
|
410
|
-
const
|
|
410
|
+
const path30 = originalPath && checkPath.convert(originalPath);
|
|
411
411
|
checkPath(
|
|
412
|
-
|
|
412
|
+
path30,
|
|
413
413
|
originalPath,
|
|
414
414
|
this._strictPathCheck ? throwError : RETURN_FALSE
|
|
415
415
|
);
|
|
416
|
-
return this._t(
|
|
416
|
+
return this._t(path30, cache, checkUnignored, slices);
|
|
417
417
|
}
|
|
418
|
-
checkIgnore(
|
|
419
|
-
if (!REGEX_TEST_TRAILING_SLASH.test(
|
|
420
|
-
return this.test(
|
|
418
|
+
checkIgnore(path30) {
|
|
419
|
+
if (!REGEX_TEST_TRAILING_SLASH.test(path30)) {
|
|
420
|
+
return this.test(path30);
|
|
421
421
|
}
|
|
422
|
-
const slices =
|
|
422
|
+
const slices = path30.split(SLASH2).filter(Boolean);
|
|
423
423
|
slices.pop();
|
|
424
424
|
if (slices.length) {
|
|
425
425
|
const parent = this._t(
|
|
@@ -432,18 +432,18 @@ var require_ignore = __commonJS({
|
|
|
432
432
|
return parent;
|
|
433
433
|
}
|
|
434
434
|
}
|
|
435
|
-
return this._rules.test(
|
|
435
|
+
return this._rules.test(path30, false, MODE_CHECK_IGNORE);
|
|
436
436
|
}
|
|
437
|
-
_t(
|
|
438
|
-
if (
|
|
439
|
-
return cache[
|
|
437
|
+
_t(path30, cache, checkUnignored, slices) {
|
|
438
|
+
if (path30 in cache) {
|
|
439
|
+
return cache[path30];
|
|
440
440
|
}
|
|
441
441
|
if (!slices) {
|
|
442
|
-
slices =
|
|
442
|
+
slices = path30.split(SLASH2).filter(Boolean);
|
|
443
443
|
}
|
|
444
444
|
slices.pop();
|
|
445
445
|
if (!slices.length) {
|
|
446
|
-
return cache[
|
|
446
|
+
return cache[path30] = this._rules.test(path30, checkUnignored, MODE_IGNORE);
|
|
447
447
|
}
|
|
448
448
|
const parent = this._t(
|
|
449
449
|
slices.join(SLASH2) + SLASH2,
|
|
@@ -451,29 +451,29 @@ var require_ignore = __commonJS({
|
|
|
451
451
|
checkUnignored,
|
|
452
452
|
slices
|
|
453
453
|
);
|
|
454
|
-
return cache[
|
|
454
|
+
return cache[path30] = parent.ignored ? parent : this._rules.test(path30, checkUnignored, MODE_IGNORE);
|
|
455
455
|
}
|
|
456
|
-
ignores(
|
|
457
|
-
return this._test(
|
|
456
|
+
ignores(path30) {
|
|
457
|
+
return this._test(path30, this._ignoreCache, false).ignored;
|
|
458
458
|
}
|
|
459
459
|
createFilter() {
|
|
460
|
-
return (
|
|
460
|
+
return (path30) => !this.ignores(path30);
|
|
461
461
|
}
|
|
462
462
|
filter(paths) {
|
|
463
463
|
return makeArray(paths).filter(this.createFilter());
|
|
464
464
|
}
|
|
465
465
|
// @returns {TestResult}
|
|
466
|
-
test(
|
|
467
|
-
return this._test(
|
|
466
|
+
test(path30) {
|
|
467
|
+
return this._test(path30, this._testCache, true);
|
|
468
468
|
}
|
|
469
469
|
};
|
|
470
470
|
var factory = (options) => new Ignore2(options);
|
|
471
|
-
var isPathValid = (
|
|
471
|
+
var isPathValid = (path30) => checkPath(path30 && checkPath.convert(path30), path30, RETURN_FALSE);
|
|
472
472
|
var setupWindows = () => {
|
|
473
473
|
const makePosix = (str) => /^\\\\\?\\/.test(str) || /["<>|\u0000-\u001F]+/u.test(str) ? str : str.replace(/\\/g, "/");
|
|
474
474
|
checkPath.convert = makePosix;
|
|
475
475
|
const REGEX_TEST_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i;
|
|
476
|
-
checkPath.isNotRelative = (
|
|
476
|
+
checkPath.isNotRelative = (path30) => REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path30) || isNotRelative(path30);
|
|
477
477
|
};
|
|
478
478
|
if (
|
|
479
479
|
// Detect `process` so that it can run in browsers.
|
|
@@ -651,7 +651,7 @@ var require_eventemitter3 = __commonJS({
|
|
|
651
651
|
});
|
|
652
652
|
|
|
653
653
|
// src/adapters/opencode.ts
|
|
654
|
-
import * as
|
|
654
|
+
import * as path29 from "path";
|
|
655
655
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
656
656
|
|
|
657
657
|
// src/config/constants.ts
|
|
@@ -1129,11 +1129,11 @@ function resolveGitDir(repoRoot) {
|
|
|
1129
1129
|
return null;
|
|
1130
1130
|
}
|
|
1131
1131
|
try {
|
|
1132
|
-
const
|
|
1133
|
-
if (
|
|
1132
|
+
const stat5 = statSync2(gitPath);
|
|
1133
|
+
if (stat5.isDirectory()) {
|
|
1134
1134
|
return gitPath;
|
|
1135
1135
|
}
|
|
1136
|
-
if (
|
|
1136
|
+
if (stat5.isFile()) {
|
|
1137
1137
|
const content = readFileSync2(gitPath, "utf-8").trim();
|
|
1138
1138
|
const match = content.match(/^gitdir:\s*(.+)$/);
|
|
1139
1139
|
if (match) {
|
|
@@ -2202,7 +2202,7 @@ function analyzeQueryIntent(query) {
|
|
|
2202
2202
|
}
|
|
2203
2203
|
function isTestPath(filePath) {
|
|
2204
2204
|
const normalized = normalizePath(filePath);
|
|
2205
|
-
return /(?:^|\/)(?:test|tests|__tests__|spec|specs)(?:\/|$)/u.test(normalized) ||
|
|
2205
|
+
return /(?:^|\/)(?:test|tests|__tests__|spec|specs)(?:\/|$)/u.test(normalized) || /(?:\.(?:test|spec)|_(?:test|spec))\.[^/]+$/u.test(normalized) || /(?:^|\/)(?:test|spec)_[^/]+\.[^/]+$/u.test(normalized);
|
|
2206
2206
|
}
|
|
2207
2207
|
function isFixturePath(filePath) {
|
|
2208
2208
|
const normalized = normalizePath(filePath);
|
|
@@ -2577,8 +2577,8 @@ function formatExactSearchHandoff(results) {
|
|
|
2577
2577
|
}
|
|
2578
2578
|
function formatContextEvidence(result, index) {
|
|
2579
2579
|
const symbol = result.name ? ` ${JSON.stringify(compactEvidenceValue(result.name, 80))}` : "";
|
|
2580
|
-
const
|
|
2581
|
-
return `[${index}] ${result.chunkType}${symbol} in ${
|
|
2580
|
+
const path30 = compactEvidenceValue(result.filePath, 120);
|
|
2581
|
+
return `[${index}] ${result.chunkType}${symbol} in ${path30}:${result.startLine}-${result.endLine} (score ${result.score.toFixed(2)})`;
|
|
2582
2582
|
}
|
|
2583
2583
|
function formatContextPack(heading, selected, candidateCount, duplicateCount, limitOmittedCount, budgetOmittedCount, includeExactSearchHandoff) {
|
|
2584
2584
|
const lines = selected.map((result, index) => formatContextEvidence(result, index + 1));
|
|
@@ -3741,8 +3741,8 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
|
|
|
3741
3741
|
if (entry.isDirectory()) {
|
|
3742
3742
|
subdirs.push({ fullPath, relativePath });
|
|
3743
3743
|
} else if (entry.isFile()) {
|
|
3744
|
-
const
|
|
3745
|
-
if (
|
|
3744
|
+
const stat5 = await fsPromises.stat(fullPath);
|
|
3745
|
+
if (stat5.size > maxFileSize) {
|
|
3746
3746
|
skipped.push({ path: relativePath, reason: "too_large" });
|
|
3747
3747
|
continue;
|
|
3748
3748
|
}
|
|
@@ -3760,7 +3760,7 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
|
|
|
3760
3760
|
}
|
|
3761
3761
|
}
|
|
3762
3762
|
if (matched) {
|
|
3763
|
-
filesInDir.push({ path: fullPath, size:
|
|
3763
|
+
filesInDir.push({ path: fullPath, size: stat5.size });
|
|
3764
3764
|
}
|
|
3765
3765
|
}
|
|
3766
3766
|
}
|
|
@@ -3817,8 +3817,8 @@ async function collectFiles(projectRoot, includePatterns, excludePatterns, maxFi
|
|
|
3817
3817
|
}
|
|
3818
3818
|
for (const resolvedKbRoot of normalizedRoots) {
|
|
3819
3819
|
try {
|
|
3820
|
-
const
|
|
3821
|
-
if (!
|
|
3820
|
+
const stat5 = await fsPromises.stat(resolvedKbRoot);
|
|
3821
|
+
if (!stat5.isDirectory()) {
|
|
3822
3822
|
skipped.push({ path: resolvedKbRoot, reason: "excluded" });
|
|
3823
3823
|
continue;
|
|
3824
3824
|
}
|
|
@@ -3852,7 +3852,7 @@ function getErrorMessage(error) {
|
|
|
3852
3852
|
return error instanceof Error ? error.message : String(error);
|
|
3853
3853
|
}
|
|
3854
3854
|
function runCommand(file, args, options) {
|
|
3855
|
-
return new Promise((
|
|
3855
|
+
return new Promise((resolve17, reject) => {
|
|
3856
3856
|
childProcess.execFile(
|
|
3857
3857
|
file,
|
|
3858
3858
|
args,
|
|
@@ -3862,7 +3862,7 @@ function runCommand(file, args, options) {
|
|
|
3862
3862
|
reject(error);
|
|
3863
3863
|
return;
|
|
3864
3864
|
}
|
|
3865
|
-
|
|
3865
|
+
resolve17(stdout);
|
|
3866
3866
|
}
|
|
3867
3867
|
);
|
|
3868
3868
|
});
|
|
@@ -4007,10 +4007,10 @@ function safeFailureMessage(error) {
|
|
|
4007
4007
|
}
|
|
4008
4008
|
function cancellableDelay(delayMs, signal) {
|
|
4009
4009
|
if (signal.aborted) return Promise.reject(new AutoIndexCancelledError());
|
|
4010
|
-
return new Promise((
|
|
4010
|
+
return new Promise((resolve17, reject) => {
|
|
4011
4011
|
const timer = setTimeout(() => {
|
|
4012
4012
|
signal.removeEventListener("abort", onAbort);
|
|
4013
|
-
|
|
4013
|
+
resolve17();
|
|
4014
4014
|
}, delayMs);
|
|
4015
4015
|
timer.unref?.();
|
|
4016
4016
|
const onAbort = () => {
|
|
@@ -4022,15 +4022,15 @@ function cancellableDelay(delayMs, signal) {
|
|
|
4022
4022
|
}
|
|
4023
4023
|
function withTimeout(promise, timeoutMs) {
|
|
4024
4024
|
if (timeoutMs <= 0) return Promise.resolve(void 0);
|
|
4025
|
-
return new Promise((
|
|
4026
|
-
const timer = setTimeout(() =>
|
|
4025
|
+
return new Promise((resolve17) => {
|
|
4026
|
+
const timer = setTimeout(() => resolve17(void 0), timeoutMs);
|
|
4027
4027
|
timer.unref?.();
|
|
4028
4028
|
void promise.then((value) => {
|
|
4029
4029
|
clearTimeout(timer);
|
|
4030
|
-
|
|
4030
|
+
resolve17(value);
|
|
4031
4031
|
}, () => {
|
|
4032
4032
|
clearTimeout(timer);
|
|
4033
|
-
|
|
4033
|
+
resolve17(void 0);
|
|
4034
4034
|
});
|
|
4035
4035
|
});
|
|
4036
4036
|
}
|
|
@@ -4412,17 +4412,17 @@ var AutoIndexCoordinator = class {
|
|
|
4412
4412
|
}
|
|
4413
4413
|
}
|
|
4414
4414
|
waitForBatteryRetry(delayMs) {
|
|
4415
|
-
return new Promise((
|
|
4415
|
+
return new Promise((resolve17) => {
|
|
4416
4416
|
const timer = setTimeout(() => {
|
|
4417
4417
|
if (this.batteryRetryTimer === timer) {
|
|
4418
4418
|
this.batteryRetryTimer = null;
|
|
4419
4419
|
this.resolveBatteryRetry = null;
|
|
4420
4420
|
}
|
|
4421
|
-
|
|
4421
|
+
resolve17();
|
|
4422
4422
|
}, delayMs);
|
|
4423
4423
|
timer.unref?.();
|
|
4424
4424
|
this.batteryRetryTimer = timer;
|
|
4425
|
-
this.resolveBatteryRetry =
|
|
4425
|
+
this.resolveBatteryRetry = resolve17;
|
|
4426
4426
|
});
|
|
4427
4427
|
}
|
|
4428
4428
|
cancelBatteryRetry() {
|
|
@@ -4430,9 +4430,9 @@ var AutoIndexCoordinator = class {
|
|
|
4430
4430
|
clearTimeout(this.batteryRetryTimer);
|
|
4431
4431
|
this.batteryRetryTimer = null;
|
|
4432
4432
|
}
|
|
4433
|
-
const
|
|
4433
|
+
const resolve17 = this.resolveBatteryRetry;
|
|
4434
4434
|
this.resolveBatteryRetry = null;
|
|
4435
|
-
|
|
4435
|
+
resolve17?.();
|
|
4436
4436
|
}
|
|
4437
4437
|
finishBatteryCheck(batteryCheck) {
|
|
4438
4438
|
if (this.batteryCheck !== batteryCheck) return;
|
|
@@ -4637,7 +4637,7 @@ function pTimeout(promise, options) {
|
|
|
4637
4637
|
} = options;
|
|
4638
4638
|
let timer;
|
|
4639
4639
|
let abortHandler;
|
|
4640
|
-
const wrappedPromise = new Promise((
|
|
4640
|
+
const wrappedPromise = new Promise((resolve17, reject) => {
|
|
4641
4641
|
if (typeof milliseconds !== "number" || Math.sign(milliseconds) !== 1) {
|
|
4642
4642
|
throw new TypeError(`Expected \`milliseconds\` to be a positive number, got \`${milliseconds}\``);
|
|
4643
4643
|
}
|
|
@@ -4651,7 +4651,7 @@ function pTimeout(promise, options) {
|
|
|
4651
4651
|
};
|
|
4652
4652
|
signal.addEventListener("abort", abortHandler, { once: true });
|
|
4653
4653
|
}
|
|
4654
|
-
promise.then(
|
|
4654
|
+
promise.then(resolve17, reject);
|
|
4655
4655
|
if (milliseconds === Number.POSITIVE_INFINITY) {
|
|
4656
4656
|
return;
|
|
4657
4657
|
}
|
|
@@ -4659,7 +4659,7 @@ function pTimeout(promise, options) {
|
|
|
4659
4659
|
timer = customTimers.setTimeout.call(void 0, () => {
|
|
4660
4660
|
if (fallback) {
|
|
4661
4661
|
try {
|
|
4662
|
-
|
|
4662
|
+
resolve17(fallback());
|
|
4663
4663
|
} catch (error) {
|
|
4664
4664
|
reject(error);
|
|
4665
4665
|
}
|
|
@@ -4669,7 +4669,7 @@ function pTimeout(promise, options) {
|
|
|
4669
4669
|
promise.cancel();
|
|
4670
4670
|
}
|
|
4671
4671
|
if (message === false) {
|
|
4672
|
-
|
|
4672
|
+
resolve17();
|
|
4673
4673
|
} else if (message instanceof Error) {
|
|
4674
4674
|
reject(message);
|
|
4675
4675
|
} else {
|
|
@@ -5071,7 +5071,7 @@ var PQueue = class extends import_index.default {
|
|
|
5071
5071
|
// Assign unique ID if not provided
|
|
5072
5072
|
id: options.id ?? (this.#idAssigner++).toString()
|
|
5073
5073
|
};
|
|
5074
|
-
return new Promise((
|
|
5074
|
+
return new Promise((resolve17, reject) => {
|
|
5075
5075
|
const taskSymbol = /* @__PURE__ */ Symbol(`task-${options.id}`);
|
|
5076
5076
|
let cleanupQueueAbortHandler = () => void 0;
|
|
5077
5077
|
const run = async () => {
|
|
@@ -5111,7 +5111,7 @@ var PQueue = class extends import_index.default {
|
|
|
5111
5111
|
})]);
|
|
5112
5112
|
}
|
|
5113
5113
|
const result = await operation;
|
|
5114
|
-
|
|
5114
|
+
resolve17(result);
|
|
5115
5115
|
this.emit("completed", result);
|
|
5116
5116
|
} catch (error) {
|
|
5117
5117
|
reject(error);
|
|
@@ -5299,13 +5299,13 @@ var PQueue = class extends import_index.default {
|
|
|
5299
5299
|
});
|
|
5300
5300
|
}
|
|
5301
5301
|
async #onEvent(event, filter) {
|
|
5302
|
-
return new Promise((
|
|
5302
|
+
return new Promise((resolve17) => {
|
|
5303
5303
|
const listener = () => {
|
|
5304
5304
|
if (filter && !filter()) {
|
|
5305
5305
|
return;
|
|
5306
5306
|
}
|
|
5307
5307
|
this.off(event, listener);
|
|
5308
|
-
|
|
5308
|
+
resolve17();
|
|
5309
5309
|
};
|
|
5310
5310
|
this.on(event, listener);
|
|
5311
5311
|
});
|
|
@@ -5591,7 +5591,7 @@ async function onAttemptFailure({ error, attemptNumber, retriesConsumed, startTi
|
|
|
5591
5591
|
const finalDelay = Math.min(delayTime, remainingTime);
|
|
5592
5592
|
options.signal?.throwIfAborted();
|
|
5593
5593
|
if (finalDelay > 0) {
|
|
5594
|
-
await new Promise((
|
|
5594
|
+
await new Promise((resolve17, reject) => {
|
|
5595
5595
|
const onAbort = () => {
|
|
5596
5596
|
clearTimeout(timeoutToken);
|
|
5597
5597
|
options.signal?.removeEventListener("abort", onAbort);
|
|
@@ -5599,7 +5599,7 @@ async function onAttemptFailure({ error, attemptNumber, retriesConsumed, startTi
|
|
|
5599
5599
|
};
|
|
5600
5600
|
const timeoutToken = setTimeout(() => {
|
|
5601
5601
|
options.signal?.removeEventListener("abort", onAbort);
|
|
5602
|
-
|
|
5602
|
+
resolve17();
|
|
5603
5603
|
}, finalDelay);
|
|
5604
5604
|
if (options.unref) {
|
|
5605
5605
|
timeoutToken.unref?.();
|
|
@@ -6405,85 +6405,6 @@ function createEmbeddingProvider(configuredProviderInfo) {
|
|
|
6405
6405
|
}
|
|
6406
6406
|
}
|
|
6407
6407
|
|
|
6408
|
-
// src/rerank/index.ts
|
|
6409
|
-
function createReranker(config) {
|
|
6410
|
-
if (!config.enabled) {
|
|
6411
|
-
return new NoOpReranker();
|
|
6412
|
-
}
|
|
6413
|
-
return new SiliconFlowReranker(config);
|
|
6414
|
-
}
|
|
6415
|
-
var NoOpReranker = class {
|
|
6416
|
-
isAvailable() {
|
|
6417
|
-
return false;
|
|
6418
|
-
}
|
|
6419
|
-
async rerank(_query, documents, _topN) {
|
|
6420
|
-
return {
|
|
6421
|
-
results: documents.map((_, index) => ({ index, relevanceScore: 0 }))
|
|
6422
|
-
};
|
|
6423
|
-
}
|
|
6424
|
-
};
|
|
6425
|
-
var SiliconFlowReranker = class {
|
|
6426
|
-
config;
|
|
6427
|
-
constructor(config) {
|
|
6428
|
-
this.config = config;
|
|
6429
|
-
}
|
|
6430
|
-
isAvailable() {
|
|
6431
|
-
return this.config.enabled && !!this.config.baseUrl && !!this.config.model;
|
|
6432
|
-
}
|
|
6433
|
-
async rerank(query, documents, topN) {
|
|
6434
|
-
if (documents.length === 0) {
|
|
6435
|
-
return { results: [] };
|
|
6436
|
-
}
|
|
6437
|
-
const headers = {
|
|
6438
|
-
"Content-Type": "application/json"
|
|
6439
|
-
};
|
|
6440
|
-
if (this.config.apiKey) {
|
|
6441
|
-
headers["Authorization"] = `Bearer ${this.config.apiKey}`;
|
|
6442
|
-
}
|
|
6443
|
-
const baseUrl = this.config.baseUrl;
|
|
6444
|
-
if (!baseUrl) {
|
|
6445
|
-
throw new Error("Reranker baseUrl is required. Configure reranker.baseUrl in your codebase-index.json.");
|
|
6446
|
-
}
|
|
6447
|
-
const timeoutMs = this.config.timeoutMs ?? 3e4;
|
|
6448
|
-
const controller = new AbortController();
|
|
6449
|
-
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
6450
|
-
try {
|
|
6451
|
-
const response = await fetch(`${baseUrl}/rerank`, {
|
|
6452
|
-
method: "POST",
|
|
6453
|
-
headers,
|
|
6454
|
-
body: JSON.stringify({
|
|
6455
|
-
model: this.config.model,
|
|
6456
|
-
query,
|
|
6457
|
-
documents,
|
|
6458
|
-
top_n: topN ?? this.config.topN ?? 20,
|
|
6459
|
-
return_documents: false
|
|
6460
|
-
}),
|
|
6461
|
-
signal: controller.signal
|
|
6462
|
-
});
|
|
6463
|
-
clearTimeout(timeout);
|
|
6464
|
-
if (!response.ok) {
|
|
6465
|
-
const errorText = await response.text();
|
|
6466
|
-
throw new Error(`Rerank API error: ${response.status} - ${errorText}`);
|
|
6467
|
-
}
|
|
6468
|
-
const data = await response.json();
|
|
6469
|
-
return {
|
|
6470
|
-
results: data.results.map((r) => ({
|
|
6471
|
-
index: r.index,
|
|
6472
|
-
relevanceScore: r.relevance_score,
|
|
6473
|
-
document: r.document?.text
|
|
6474
|
-
})),
|
|
6475
|
-
tokensUsed: data.meta?.tokens?.input_tokens
|
|
6476
|
-
};
|
|
6477
|
-
} catch (error) {
|
|
6478
|
-
clearTimeout(timeout);
|
|
6479
|
-
if (error instanceof Error && error.name === "AbortError") {
|
|
6480
|
-
throw new Error(`Rerank API request timed out after ${timeoutMs}ms`);
|
|
6481
|
-
}
|
|
6482
|
-
throw error;
|
|
6483
|
-
}
|
|
6484
|
-
}
|
|
6485
|
-
};
|
|
6486
|
-
|
|
6487
6408
|
// src/utils/cost.ts
|
|
6488
6409
|
function estimateChunksFromFiles(files) {
|
|
6489
6410
|
let totalChunks = 0;
|
|
@@ -8043,8 +7964,8 @@ async function isWorktreeRegistered(projectRoot, worktreePath) {
|
|
|
8043
7964
|
return false;
|
|
8044
7965
|
}
|
|
8045
7966
|
function isPathWithinRoot(filePath, rootPath) {
|
|
8046
|
-
const
|
|
8047
|
-
return
|
|
7967
|
+
const relative14 = path15.relative(path15.resolve(rootPath), path15.resolve(filePath));
|
|
7968
|
+
return relative14 === "" || !relative14.startsWith(`..${path15.sep}`) && relative14 !== ".." && !path15.isAbsolute(relative14);
|
|
8048
7969
|
}
|
|
8049
7970
|
async function pruneExactMissingWorktreeRegistration(projectRoot, worktreePath) {
|
|
8050
7971
|
if (await pathExists(worktreePath)) return false;
|
|
@@ -8421,11 +8342,11 @@ function normalizeFiles(rawFiles, projectRoot) {
|
|
|
8421
8342
|
for (const raw of rawFiles) {
|
|
8422
8343
|
if (raw.length === 0) continue;
|
|
8423
8344
|
const absolute = path16.resolve(root, raw);
|
|
8424
|
-
const
|
|
8425
|
-
if (path16.isAbsolute(raw) ||
|
|
8345
|
+
const relative14 = path16.relative(root, absolute);
|
|
8346
|
+
if (path16.isAbsolute(raw) || relative14 === ".." || relative14.startsWith(`..${path16.sep}`) || path16.isAbsolute(relative14)) {
|
|
8426
8347
|
throw new Error(`Changed file escapes the project root: ${JSON.stringify(raw)}`);
|
|
8427
8348
|
}
|
|
8428
|
-
const cleaned =
|
|
8349
|
+
const cleaned = relative14.startsWith(`.${path16.sep}`) ? relative14.slice(2) : relative14;
|
|
8429
8350
|
if (!seen.has(cleaned)) {
|
|
8430
8351
|
seen.add(cleaned);
|
|
8431
8352
|
result.push(cleaned);
|
|
@@ -8657,7 +8578,8 @@ function rankHybridResults(query, semanticResults, keywordResults, options) {
|
|
|
8657
8578
|
return cached;
|
|
8658
8579
|
}
|
|
8659
8580
|
}
|
|
8660
|
-
const
|
|
8581
|
+
const overfetchFactor = prioritizeSourcePaths ? 12 : 4;
|
|
8582
|
+
const overfetchLimit = Math.max(options.limit * overfetchFactor, options.limit);
|
|
8661
8583
|
const fused = options.fusionStrategy === "rrf" ? fuseResultsRrf(semanticResults, keywordResults, options.rrfK, overfetchLimit) : fuseResultsWeighted(semanticResults, keywordResults, options.hybridWeight, overfetchLimit);
|
|
8662
8584
|
const rerankPoolLimit = Math.max(overfetchLimit, options.rerankTopN * 3, options.limit * 6);
|
|
8663
8585
|
const rerankPool = fused.slice(0, rerankPoolLimit);
|
|
@@ -9043,6 +8965,29 @@ function extractPrimaryIdentifierQueryHint(query) {
|
|
|
9043
8965
|
const best = codeTerms.find((term) => term.length >= 6);
|
|
9044
8966
|
return best ?? null;
|
|
9045
8967
|
}
|
|
8968
|
+
function pathSegmentsForAffinityMatch(filePath) {
|
|
8969
|
+
const normalizedPath2 = normalizeRankingText(filePath).replace(/\\/g, "/");
|
|
8970
|
+
const segments = normalizedPath2.split("/").filter((segment) => segment.length > 0);
|
|
8971
|
+
if (segments.length === 0) {
|
|
8972
|
+
return [];
|
|
8973
|
+
}
|
|
8974
|
+
const basename9 = segments[segments.length - 1] ?? "";
|
|
8975
|
+
const basenameWithoutExt = basename9.replace(/\.[^/.]+$/u, "");
|
|
8976
|
+
const normalizedSegments = segments.map((segment) => segment.toLowerCase());
|
|
8977
|
+
return Array.from(/* @__PURE__ */ new Set([
|
|
8978
|
+
...normalizedSegments,
|
|
8979
|
+
basenameWithoutExt.toLowerCase()
|
|
8980
|
+
]));
|
|
8981
|
+
}
|
|
8982
|
+
function hasModuleAffinity(filePath, exactIdentifierVariants) {
|
|
8983
|
+
const haystack = pathSegmentsForAffinityMatch(filePath);
|
|
8984
|
+
return exactIdentifierVariants.some((variant) => {
|
|
8985
|
+
if (!variant || variant.length < 2) {
|
|
8986
|
+
return false;
|
|
8987
|
+
}
|
|
8988
|
+
return haystack.includes(variant);
|
|
8989
|
+
});
|
|
8990
|
+
}
|
|
9046
8991
|
var FILE_PATH_HINT_EXTENSIONS = [
|
|
9047
8992
|
"ts",
|
|
9048
8993
|
"tsx",
|
|
@@ -9118,10 +9063,13 @@ function buildDeterministicIdentifierPass(query, candidates, limit, prioritizeSo
|
|
|
9118
9063
|
).map((candidate) => {
|
|
9119
9064
|
const nameLower = (candidate.metadata.name ?? "").toLowerCase();
|
|
9120
9065
|
const pathLower = candidate.metadata.filePath.toLowerCase();
|
|
9121
|
-
|
|
9122
|
-
const
|
|
9066
|
+
const exactIdentifierVariants = primaryVariants.filter((value) => value.length >= 2);
|
|
9067
|
+
const exactMatch = exactIdentifierVariants.some(
|
|
9123
9068
|
(variant) => nameLower === variant || nameLower.replace(/[^a-z0-9]/g, "") === variant.replace(/[^a-z0-9]/g, "")
|
|
9124
9069
|
);
|
|
9070
|
+
let maxMatch = 0;
|
|
9071
|
+
const nameMatchesPrimary = exactMatch;
|
|
9072
|
+
const pathAffinity = exactMatch ? hasModuleAffinity(candidate.metadata.filePath, exactIdentifierVariants) : false;
|
|
9125
9073
|
const pathMatchesFileHint = filePathHint ? pathMatchesHint(candidate.metadata.filePath, filePathHint) : false;
|
|
9126
9074
|
for (const hint of hints) {
|
|
9127
9075
|
const variants = normalizeIdentifierVariants(hint);
|
|
@@ -9142,12 +9090,17 @@ function buildDeterministicIdentifierPass(query, candidates, limit, prioritizeSo
|
|
|
9142
9090
|
candidate,
|
|
9143
9091
|
maxMatch,
|
|
9144
9092
|
pathMatchesFileHint,
|
|
9145
|
-
nameMatchesPrimary
|
|
9093
|
+
nameMatchesPrimary,
|
|
9094
|
+
pathAffinity
|
|
9146
9095
|
};
|
|
9147
9096
|
}).filter((entry) => entry.maxMatch >= 0.7).sort((a, b) => {
|
|
9148
9097
|
const aAnchored = a.pathMatchesFileHint && a.nameMatchesPrimary ? 1 : 0;
|
|
9149
9098
|
const bAnchored = b.pathMatchesFileHint && b.nameMatchesPrimary ? 1 : 0;
|
|
9150
9099
|
if (aAnchored !== bAnchored) return bAnchored - aAnchored;
|
|
9100
|
+
if (a.nameMatchesPrimary !== b.nameMatchesPrimary) {
|
|
9101
|
+
return b.nameMatchesPrimary ? 1 : -1;
|
|
9102
|
+
}
|
|
9103
|
+
if (a.pathAffinity !== b.pathAffinity) return b.pathAffinity ? 1 : -1;
|
|
9151
9104
|
if (b.maxMatch !== a.maxMatch) return b.maxMatch - a.maxMatch;
|
|
9152
9105
|
if (b.candidate.score !== a.candidate.score) return b.candidate.score - a.candidate.score;
|
|
9153
9106
|
return a.candidate.id.localeCompare(b.candidate.id);
|
|
@@ -10137,7 +10090,6 @@ var Indexer = class _Indexer {
|
|
|
10137
10090
|
database = null;
|
|
10138
10091
|
provider = null;
|
|
10139
10092
|
configuredProviderInfo = null;
|
|
10140
|
-
reranker = null;
|
|
10141
10093
|
fileHashCache = /* @__PURE__ */ new Map();
|
|
10142
10094
|
fileHashCachePath = "";
|
|
10143
10095
|
failedBatchesPath = "";
|
|
@@ -10297,7 +10249,6 @@ var Indexer = class _Indexer {
|
|
|
10297
10249
|
this.database = null;
|
|
10298
10250
|
this.provider = null;
|
|
10299
10251
|
this.configuredProviderInfo = null;
|
|
10300
|
-
this.reranker = null;
|
|
10301
10252
|
this.indexCompatibility = null;
|
|
10302
10253
|
this.initializationMode = "none";
|
|
10303
10254
|
this.readIssues = [];
|
|
@@ -11027,7 +10978,7 @@ var Indexer = class _Indexer {
|
|
|
11027
10978
|
await options.queue.onSizeLessThan(Math.max(1, options.providerRateLimits.concurrency));
|
|
11028
10979
|
const task = options.queue.add(async () => {
|
|
11029
10980
|
if (options.rateLimitState.backoffMs > 0) {
|
|
11030
|
-
await new Promise((
|
|
10981
|
+
await new Promise((resolve17) => setTimeout(resolve17, options.rateLimitState.backoffMs));
|
|
11031
10982
|
}
|
|
11032
10983
|
try {
|
|
11033
10984
|
const embeddingResult = await pRetry(
|
|
@@ -11594,15 +11545,6 @@ var Indexer = class _Indexer {
|
|
|
11594
11545
|
rerankerEnabled: this.config.reranker?.enabled ?? false
|
|
11595
11546
|
});
|
|
11596
11547
|
this.provider = createEmbeddingProvider(this.configuredProviderInfo);
|
|
11597
|
-
if (this.config.reranker?.enabled) {
|
|
11598
|
-
this.reranker = createReranker(this.config.reranker);
|
|
11599
|
-
if (this.reranker.isAvailable()) {
|
|
11600
|
-
this.logger.info("Reranker initialized", {
|
|
11601
|
-
model: this.config.reranker.model,
|
|
11602
|
-
baseUrl: this.config.reranker.baseUrl
|
|
11603
|
-
});
|
|
11604
|
-
}
|
|
11605
|
-
}
|
|
11606
11548
|
const dimensions = this.configuredProviderInfo.modelInfo.dimensions;
|
|
11607
11549
|
const storePath = path19.join(this.indexPath, "vectors");
|
|
11608
11550
|
const vectorMetadataPath = `${storePath}.meta.json`;
|
|
@@ -13007,6 +12949,7 @@ var Indexer = class _Indexer {
|
|
|
13007
12949
|
const filterByBranch = options?.filterByBranch ?? true;
|
|
13008
12950
|
const sourceIntent = options?.definitionIntent === true || classifyQueryIntentRaw(query) === "source";
|
|
13009
12951
|
const identifierHints = extractIdentifierHints(query);
|
|
12952
|
+
const candidateLimit = maxResults * (sourceIntent ? 12 : 4);
|
|
13010
12953
|
this.logger.search("debug", "Starting search", {
|
|
13011
12954
|
query,
|
|
13012
12955
|
maxResults,
|
|
@@ -13043,7 +12986,7 @@ var Indexer = class _Indexer {
|
|
|
13043
12986
|
const semanticCandidates = embedding ? this.searchSemanticCandidates(
|
|
13044
12987
|
store,
|
|
13045
12988
|
embedding,
|
|
13046
|
-
|
|
12989
|
+
candidateLimit,
|
|
13047
12990
|
branchChunkIds,
|
|
13048
12991
|
shouldPrefilterByBranch
|
|
13049
12992
|
) : [];
|
|
@@ -13051,7 +12994,7 @@ var Indexer = class _Indexer {
|
|
|
13051
12994
|
const keywordStartTime = performance2.now();
|
|
13052
12995
|
const keywordCandidates = await this.keywordSearch(
|
|
13053
12996
|
query,
|
|
13054
|
-
|
|
12997
|
+
candidateLimit,
|
|
13055
12998
|
store,
|
|
13056
12999
|
invertedIndex,
|
|
13057
13000
|
branchChunkIds,
|
|
@@ -13809,9 +13752,9 @@ var Indexer = class _Indexer {
|
|
|
13809
13752
|
this.requireReadableComponents(readIssues, "database");
|
|
13810
13753
|
let shortest = [];
|
|
13811
13754
|
for (const branchKey of this.getBranchCatalogKeys()) {
|
|
13812
|
-
const
|
|
13813
|
-
if (
|
|
13814
|
-
shortest =
|
|
13755
|
+
const path30 = database.findShortestPath(fromName, toName, branchKey, maxDepth);
|
|
13756
|
+
if (path30.length > 0 && (shortest.length === 0 || path30.length < shortest.length)) {
|
|
13757
|
+
shortest = path30;
|
|
13815
13758
|
}
|
|
13816
13759
|
}
|
|
13817
13760
|
return shortest.map((hop) => this.resolveFilePathRecord(hop));
|
|
@@ -13859,13 +13802,13 @@ var Indexer = class _Indexer {
|
|
|
13859
13802
|
}
|
|
13860
13803
|
}
|
|
13861
13804
|
if (!found) continue;
|
|
13862
|
-
const
|
|
13805
|
+
const path30 = [];
|
|
13863
13806
|
let currentSymbolId = toSymbolId;
|
|
13864
13807
|
while (true) {
|
|
13865
13808
|
const symbol = symbolsById.get(currentSymbolId);
|
|
13866
13809
|
if (!symbol) break;
|
|
13867
13810
|
const parent = parentBySymbolId.get(currentSymbolId);
|
|
13868
|
-
|
|
13811
|
+
path30.push({
|
|
13869
13812
|
symbolId: symbol.id,
|
|
13870
13813
|
symbolName: symbol.name,
|
|
13871
13814
|
filePath: symbol.filePath,
|
|
@@ -13875,9 +13818,9 @@ var Indexer = class _Indexer {
|
|
|
13875
13818
|
if (!parent) break;
|
|
13876
13819
|
currentSymbolId = parent.parentId;
|
|
13877
13820
|
}
|
|
13878
|
-
|
|
13879
|
-
if (
|
|
13880
|
-
shortest =
|
|
13821
|
+
path30.reverse();
|
|
13822
|
+
if (path30.length > 0 && (shortest.length === 0 || path30.length < shortest.length)) {
|
|
13823
|
+
shortest = path30;
|
|
13881
13824
|
}
|
|
13882
13825
|
}
|
|
13883
13826
|
return shortest.map((hop) => this.resolveFilePathRecord(hop));
|
|
@@ -14213,7 +14156,6 @@ var Indexer = class _Indexer {
|
|
|
14213
14156
|
this.store = null;
|
|
14214
14157
|
this.invertedIndex = null;
|
|
14215
14158
|
this.provider = null;
|
|
14216
|
-
this.reranker = null;
|
|
14217
14159
|
this.configuredProviderInfo = null;
|
|
14218
14160
|
this.indexCompatibility = null;
|
|
14219
14161
|
this.initializationMode = "none";
|
|
@@ -14538,12 +14480,12 @@ async function getCallGraphPath(projectRoot, host, from, to, maxDepth, fromFileP
|
|
|
14538
14480
|
if (fromResolution.status !== "resolved" || toResolution.status !== "resolved") {
|
|
14539
14481
|
return { from: fromResolution, to: toResolution, path: [] };
|
|
14540
14482
|
}
|
|
14541
|
-
const
|
|
14483
|
+
const path30 = await indexer.findCallPathBySymbolIds(
|
|
14542
14484
|
fromResolution.symbolId,
|
|
14543
14485
|
toResolution.symbolId,
|
|
14544
14486
|
maxDepth
|
|
14545
14487
|
);
|
|
14546
|
-
return { from: fromResolution, to: toResolution, path:
|
|
14488
|
+
return { from: fromResolution, to: toResolution, path: path30 };
|
|
14547
14489
|
}
|
|
14548
14490
|
async function runIndexCodebase(projectRoot, host, args, onProgress) {
|
|
14549
14491
|
const root = getProjectRoot(projectRoot, host);
|
|
@@ -14769,8 +14711,8 @@ function addKnowledgeBase(projectRoot, host, knowledgeBasePath) {
|
|
|
14769
14711
|
}
|
|
14770
14712
|
}
|
|
14771
14713
|
try {
|
|
14772
|
-
const
|
|
14773
|
-
if (!
|
|
14714
|
+
const stat5 = statSync5(normalizedPath2);
|
|
14715
|
+
if (!stat5.isDirectory()) {
|
|
14774
14716
|
return `Error: Path is not a directory: ${normalizedPath2}`;
|
|
14775
14717
|
}
|
|
14776
14718
|
} catch (error) {
|
|
@@ -14818,8 +14760,8 @@ function listKnowledgeBases(projectRoot, host) {
|
|
|
14818
14760
|
`;
|
|
14819
14761
|
if (exists) {
|
|
14820
14762
|
try {
|
|
14821
|
-
const
|
|
14822
|
-
result += ` Type: ${
|
|
14763
|
+
const stat5 = statSync5(resolvedPath);
|
|
14764
|
+
result += ` Type: ${stat5.isDirectory() ? "Directory" : "File"}
|
|
14823
14765
|
`;
|
|
14824
14766
|
} catch {
|
|
14825
14767
|
}
|
|
@@ -14860,7 +14802,7 @@ Run /index to rebuild the index without the removed knowledge base.`;
|
|
|
14860
14802
|
}
|
|
14861
14803
|
|
|
14862
14804
|
// src/watcher/file-watcher.ts
|
|
14863
|
-
import { existsSync as existsSync13 } from "fs";
|
|
14805
|
+
import { existsSync as existsSync13, statSync as statSync6 } from "fs";
|
|
14864
14806
|
|
|
14865
14807
|
// node_modules/chokidar/index.js
|
|
14866
14808
|
import { EventEmitter as EventEmitter2 } from "events";
|
|
@@ -14952,7 +14894,7 @@ var ReaddirpStream = class extends Readable {
|
|
|
14952
14894
|
this._directoryFilter = normalizeFilter(opts.directoryFilter);
|
|
14953
14895
|
const statMethod = opts.lstat ? lstat : stat;
|
|
14954
14896
|
if (wantBigintFsStats) {
|
|
14955
|
-
this._stat = (
|
|
14897
|
+
this._stat = (path30) => statMethod(path30, { bigint: true });
|
|
14956
14898
|
} else {
|
|
14957
14899
|
this._stat = statMethod;
|
|
14958
14900
|
}
|
|
@@ -14977,8 +14919,8 @@ var ReaddirpStream = class extends Readable {
|
|
|
14977
14919
|
const par = this.parent;
|
|
14978
14920
|
const fil = par && par.files;
|
|
14979
14921
|
if (fil && fil.length > 0) {
|
|
14980
|
-
const { path:
|
|
14981
|
-
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent,
|
|
14922
|
+
const { path: path30, depth } = par;
|
|
14923
|
+
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path30));
|
|
14982
14924
|
const awaited = await Promise.all(slice);
|
|
14983
14925
|
for (const entry of awaited) {
|
|
14984
14926
|
if (!entry)
|
|
@@ -15018,20 +14960,20 @@ var ReaddirpStream = class extends Readable {
|
|
|
15018
14960
|
this.reading = false;
|
|
15019
14961
|
}
|
|
15020
14962
|
}
|
|
15021
|
-
async _exploreDir(
|
|
14963
|
+
async _exploreDir(path30, depth) {
|
|
15022
14964
|
let files;
|
|
15023
14965
|
try {
|
|
15024
|
-
files = await readdir(
|
|
14966
|
+
files = await readdir(path30, this._rdOptions);
|
|
15025
14967
|
} catch (error) {
|
|
15026
14968
|
this._onError(error);
|
|
15027
14969
|
}
|
|
15028
|
-
return { files, depth, path:
|
|
14970
|
+
return { files, depth, path: path30 };
|
|
15029
14971
|
}
|
|
15030
|
-
async _formatEntry(dirent,
|
|
14972
|
+
async _formatEntry(dirent, path30) {
|
|
15031
14973
|
let entry;
|
|
15032
14974
|
const basename9 = this._isDirent ? dirent.name : dirent;
|
|
15033
14975
|
try {
|
|
15034
|
-
const fullPath = presolve(pjoin(
|
|
14976
|
+
const fullPath = presolve(pjoin(path30, basename9));
|
|
15035
14977
|
entry = { path: prelative(this._root, fullPath), fullPath, basename: basename9 };
|
|
15036
14978
|
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
15037
14979
|
} catch (err) {
|
|
@@ -15431,16 +15373,16 @@ var delFromSet = (main, prop, item) => {
|
|
|
15431
15373
|
};
|
|
15432
15374
|
var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
|
|
15433
15375
|
var FsWatchInstances = /* @__PURE__ */ new Map();
|
|
15434
|
-
function createFsWatchInstance(
|
|
15376
|
+
function createFsWatchInstance(path30, options, listener, errHandler, emitRaw) {
|
|
15435
15377
|
const handleEvent = (rawEvent, evPath) => {
|
|
15436
|
-
listener(
|
|
15437
|
-
emitRaw(rawEvent, evPath, { watchedPath:
|
|
15438
|
-
if (evPath &&
|
|
15439
|
-
fsWatchBroadcast(sp.resolve(
|
|
15378
|
+
listener(path30);
|
|
15379
|
+
emitRaw(rawEvent, evPath, { watchedPath: path30 });
|
|
15380
|
+
if (evPath && path30 !== evPath) {
|
|
15381
|
+
fsWatchBroadcast(sp.resolve(path30, evPath), KEY_LISTENERS, sp.join(path30, evPath));
|
|
15440
15382
|
}
|
|
15441
15383
|
};
|
|
15442
15384
|
try {
|
|
15443
|
-
return fs_watch(
|
|
15385
|
+
return fs_watch(path30, {
|
|
15444
15386
|
persistent: options.persistent
|
|
15445
15387
|
}, handleEvent);
|
|
15446
15388
|
} catch (error) {
|
|
@@ -15456,12 +15398,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
|
|
|
15456
15398
|
listener(val1, val2, val3);
|
|
15457
15399
|
});
|
|
15458
15400
|
};
|
|
15459
|
-
var setFsWatchListener = (
|
|
15401
|
+
var setFsWatchListener = (path30, fullPath, options, handlers) => {
|
|
15460
15402
|
const { listener, errHandler, rawEmitter } = handlers;
|
|
15461
15403
|
let cont = FsWatchInstances.get(fullPath);
|
|
15462
15404
|
let watcher;
|
|
15463
15405
|
if (!options.persistent) {
|
|
15464
|
-
watcher = createFsWatchInstance(
|
|
15406
|
+
watcher = createFsWatchInstance(path30, options, listener, errHandler, rawEmitter);
|
|
15465
15407
|
if (!watcher)
|
|
15466
15408
|
return;
|
|
15467
15409
|
return watcher.close.bind(watcher);
|
|
@@ -15472,7 +15414,7 @@ var setFsWatchListener = (path28, fullPath, options, handlers) => {
|
|
|
15472
15414
|
addAndConvert(cont, KEY_RAW, rawEmitter);
|
|
15473
15415
|
} else {
|
|
15474
15416
|
watcher = createFsWatchInstance(
|
|
15475
|
-
|
|
15417
|
+
path30,
|
|
15476
15418
|
options,
|
|
15477
15419
|
fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
|
|
15478
15420
|
errHandler,
|
|
@@ -15487,7 +15429,7 @@ var setFsWatchListener = (path28, fullPath, options, handlers) => {
|
|
|
15487
15429
|
cont.watcherUnusable = true;
|
|
15488
15430
|
if (isWindows && error.code === "EPERM") {
|
|
15489
15431
|
try {
|
|
15490
|
-
const fd = await open(
|
|
15432
|
+
const fd = await open(path30, "r");
|
|
15491
15433
|
await fd.close();
|
|
15492
15434
|
broadcastErr(error);
|
|
15493
15435
|
} catch (err) {
|
|
@@ -15518,7 +15460,7 @@ var setFsWatchListener = (path28, fullPath, options, handlers) => {
|
|
|
15518
15460
|
};
|
|
15519
15461
|
};
|
|
15520
15462
|
var FsWatchFileInstances = /* @__PURE__ */ new Map();
|
|
15521
|
-
var setFsWatchFileListener = (
|
|
15463
|
+
var setFsWatchFileListener = (path30, fullPath, options, handlers) => {
|
|
15522
15464
|
const { listener, rawEmitter } = handlers;
|
|
15523
15465
|
let cont = FsWatchFileInstances.get(fullPath);
|
|
15524
15466
|
const copts = cont && cont.options;
|
|
@@ -15540,7 +15482,7 @@ var setFsWatchFileListener = (path28, fullPath, options, handlers) => {
|
|
|
15540
15482
|
});
|
|
15541
15483
|
const currmtime = curr.mtimeMs;
|
|
15542
15484
|
if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
|
|
15543
|
-
foreach(cont.listeners, (listener2) => listener2(
|
|
15485
|
+
foreach(cont.listeners, (listener2) => listener2(path30, curr));
|
|
15544
15486
|
}
|
|
15545
15487
|
})
|
|
15546
15488
|
};
|
|
@@ -15570,13 +15512,13 @@ var NodeFsHandler = class {
|
|
|
15570
15512
|
* @param listener on fs change
|
|
15571
15513
|
* @returns closer for the watcher instance
|
|
15572
15514
|
*/
|
|
15573
|
-
_watchWithNodeFs(
|
|
15515
|
+
_watchWithNodeFs(path30, listener) {
|
|
15574
15516
|
const opts = this.fsw.options;
|
|
15575
|
-
const directory = sp.dirname(
|
|
15576
|
-
const basename9 = sp.basename(
|
|
15517
|
+
const directory = sp.dirname(path30);
|
|
15518
|
+
const basename9 = sp.basename(path30);
|
|
15577
15519
|
const parent = this.fsw._getWatchedDir(directory);
|
|
15578
15520
|
parent.add(basename9);
|
|
15579
|
-
const absolutePath = sp.resolve(
|
|
15521
|
+
const absolutePath = sp.resolve(path30);
|
|
15580
15522
|
const options = {
|
|
15581
15523
|
persistent: opts.persistent
|
|
15582
15524
|
};
|
|
@@ -15586,12 +15528,12 @@ var NodeFsHandler = class {
|
|
|
15586
15528
|
if (opts.usePolling) {
|
|
15587
15529
|
const enableBin = opts.interval !== opts.binaryInterval;
|
|
15588
15530
|
options.interval = enableBin && isBinaryPath(basename9) ? opts.binaryInterval : opts.interval;
|
|
15589
|
-
closer = setFsWatchFileListener(
|
|
15531
|
+
closer = setFsWatchFileListener(path30, absolutePath, options, {
|
|
15590
15532
|
listener,
|
|
15591
15533
|
rawEmitter: this.fsw._emitRaw
|
|
15592
15534
|
});
|
|
15593
15535
|
} else {
|
|
15594
|
-
closer = setFsWatchListener(
|
|
15536
|
+
closer = setFsWatchListener(path30, absolutePath, options, {
|
|
15595
15537
|
listener,
|
|
15596
15538
|
errHandler: this._boundHandleError,
|
|
15597
15539
|
rawEmitter: this.fsw._emitRaw
|
|
@@ -15613,7 +15555,7 @@ var NodeFsHandler = class {
|
|
|
15613
15555
|
let prevStats = stats;
|
|
15614
15556
|
if (parent.has(basename9))
|
|
15615
15557
|
return;
|
|
15616
|
-
const listener = async (
|
|
15558
|
+
const listener = async (path30, newStats) => {
|
|
15617
15559
|
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
|
|
15618
15560
|
return;
|
|
15619
15561
|
if (!newStats || newStats.mtimeMs === 0) {
|
|
@@ -15627,11 +15569,11 @@ var NodeFsHandler = class {
|
|
|
15627
15569
|
this.fsw._emit(EV.CHANGE, file, newStats2);
|
|
15628
15570
|
}
|
|
15629
15571
|
if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
|
|
15630
|
-
this.fsw._closeFile(
|
|
15572
|
+
this.fsw._closeFile(path30);
|
|
15631
15573
|
prevStats = newStats2;
|
|
15632
15574
|
const closer2 = this._watchWithNodeFs(file, listener);
|
|
15633
15575
|
if (closer2)
|
|
15634
|
-
this.fsw._addPathCloser(
|
|
15576
|
+
this.fsw._addPathCloser(path30, closer2);
|
|
15635
15577
|
} else {
|
|
15636
15578
|
prevStats = newStats2;
|
|
15637
15579
|
}
|
|
@@ -15663,7 +15605,7 @@ var NodeFsHandler = class {
|
|
|
15663
15605
|
* @param item basename of this item
|
|
15664
15606
|
* @returns true if no more processing is needed for this entry.
|
|
15665
15607
|
*/
|
|
15666
|
-
async _handleSymlink(entry, directory,
|
|
15608
|
+
async _handleSymlink(entry, directory, path30, item) {
|
|
15667
15609
|
if (this.fsw.closed) {
|
|
15668
15610
|
return;
|
|
15669
15611
|
}
|
|
@@ -15673,7 +15615,7 @@ var NodeFsHandler = class {
|
|
|
15673
15615
|
this.fsw._incrReadyCount();
|
|
15674
15616
|
let linkPath;
|
|
15675
15617
|
try {
|
|
15676
|
-
linkPath = await fsrealpath(
|
|
15618
|
+
linkPath = await fsrealpath(path30);
|
|
15677
15619
|
} catch (e) {
|
|
15678
15620
|
this.fsw._emitReady();
|
|
15679
15621
|
return true;
|
|
@@ -15683,12 +15625,12 @@ var NodeFsHandler = class {
|
|
|
15683
15625
|
if (dir.has(item)) {
|
|
15684
15626
|
if (this.fsw._symlinkPaths.get(full) !== linkPath) {
|
|
15685
15627
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
15686
|
-
this.fsw._emit(EV.CHANGE,
|
|
15628
|
+
this.fsw._emit(EV.CHANGE, path30, entry.stats);
|
|
15687
15629
|
}
|
|
15688
15630
|
} else {
|
|
15689
15631
|
dir.add(item);
|
|
15690
15632
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
15691
|
-
this.fsw._emit(EV.ADD,
|
|
15633
|
+
this.fsw._emit(EV.ADD, path30, entry.stats);
|
|
15692
15634
|
}
|
|
15693
15635
|
this.fsw._emitReady();
|
|
15694
15636
|
return true;
|
|
@@ -15718,9 +15660,9 @@ var NodeFsHandler = class {
|
|
|
15718
15660
|
return;
|
|
15719
15661
|
}
|
|
15720
15662
|
const item = entry.path;
|
|
15721
|
-
let
|
|
15663
|
+
let path30 = sp.join(directory, item);
|
|
15722
15664
|
current.add(item);
|
|
15723
|
-
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory,
|
|
15665
|
+
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path30, item)) {
|
|
15724
15666
|
return;
|
|
15725
15667
|
}
|
|
15726
15668
|
if (this.fsw.closed) {
|
|
@@ -15729,11 +15671,11 @@ var NodeFsHandler = class {
|
|
|
15729
15671
|
}
|
|
15730
15672
|
if (item === target || !target && !previous.has(item)) {
|
|
15731
15673
|
this.fsw._incrReadyCount();
|
|
15732
|
-
|
|
15733
|
-
this._addToNodeFs(
|
|
15674
|
+
path30 = sp.join(dir, sp.relative(dir, path30));
|
|
15675
|
+
this._addToNodeFs(path30, initialAdd, wh, depth + 1);
|
|
15734
15676
|
}
|
|
15735
15677
|
}).on(EV.ERROR, this._boundHandleError);
|
|
15736
|
-
return new Promise((
|
|
15678
|
+
return new Promise((resolve17, reject) => {
|
|
15737
15679
|
if (!stream)
|
|
15738
15680
|
return reject();
|
|
15739
15681
|
stream.once(STR_END, () => {
|
|
@@ -15742,7 +15684,7 @@ var NodeFsHandler = class {
|
|
|
15742
15684
|
return;
|
|
15743
15685
|
}
|
|
15744
15686
|
const wasThrottled = throttler ? throttler.clear() : false;
|
|
15745
|
-
|
|
15687
|
+
resolve17(void 0);
|
|
15746
15688
|
previous.getChildren().filter((item) => {
|
|
15747
15689
|
return item !== directory && !current.has(item);
|
|
15748
15690
|
}).forEach((item) => {
|
|
@@ -15799,13 +15741,13 @@ var NodeFsHandler = class {
|
|
|
15799
15741
|
* @param depth Child path actually targeted for watch
|
|
15800
15742
|
* @param target Child path actually targeted for watch
|
|
15801
15743
|
*/
|
|
15802
|
-
async _addToNodeFs(
|
|
15744
|
+
async _addToNodeFs(path30, initialAdd, priorWh, depth, target) {
|
|
15803
15745
|
const ready = this.fsw._emitReady;
|
|
15804
|
-
if (this.fsw._isIgnored(
|
|
15746
|
+
if (this.fsw._isIgnored(path30) || this.fsw.closed) {
|
|
15805
15747
|
ready();
|
|
15806
15748
|
return false;
|
|
15807
15749
|
}
|
|
15808
|
-
const wh = this.fsw._getWatchHelpers(
|
|
15750
|
+
const wh = this.fsw._getWatchHelpers(path30);
|
|
15809
15751
|
if (priorWh) {
|
|
15810
15752
|
wh.filterPath = (entry) => priorWh.filterPath(entry);
|
|
15811
15753
|
wh.filterDir = (entry) => priorWh.filterDir(entry);
|
|
@@ -15821,8 +15763,8 @@ var NodeFsHandler = class {
|
|
|
15821
15763
|
const follow = this.fsw.options.followSymlinks;
|
|
15822
15764
|
let closer;
|
|
15823
15765
|
if (stats.isDirectory()) {
|
|
15824
|
-
const absPath = sp.resolve(
|
|
15825
|
-
const targetPath = follow ? await fsrealpath(
|
|
15766
|
+
const absPath = sp.resolve(path30);
|
|
15767
|
+
const targetPath = follow ? await fsrealpath(path30) : path30;
|
|
15826
15768
|
if (this.fsw.closed)
|
|
15827
15769
|
return;
|
|
15828
15770
|
closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
|
|
@@ -15832,29 +15774,29 @@ var NodeFsHandler = class {
|
|
|
15832
15774
|
this.fsw._symlinkPaths.set(absPath, targetPath);
|
|
15833
15775
|
}
|
|
15834
15776
|
} else if (stats.isSymbolicLink()) {
|
|
15835
|
-
const targetPath = follow ? await fsrealpath(
|
|
15777
|
+
const targetPath = follow ? await fsrealpath(path30) : path30;
|
|
15836
15778
|
if (this.fsw.closed)
|
|
15837
15779
|
return;
|
|
15838
15780
|
const parent = sp.dirname(wh.watchPath);
|
|
15839
15781
|
this.fsw._getWatchedDir(parent).add(wh.watchPath);
|
|
15840
15782
|
this.fsw._emit(EV.ADD, wh.watchPath, stats);
|
|
15841
|
-
closer = await this._handleDir(parent, stats, initialAdd, depth,
|
|
15783
|
+
closer = await this._handleDir(parent, stats, initialAdd, depth, path30, wh, targetPath);
|
|
15842
15784
|
if (this.fsw.closed)
|
|
15843
15785
|
return;
|
|
15844
15786
|
if (targetPath !== void 0) {
|
|
15845
|
-
this.fsw._symlinkPaths.set(sp.resolve(
|
|
15787
|
+
this.fsw._symlinkPaths.set(sp.resolve(path30), targetPath);
|
|
15846
15788
|
}
|
|
15847
15789
|
} else {
|
|
15848
15790
|
closer = this._handleFile(wh.watchPath, stats, initialAdd);
|
|
15849
15791
|
}
|
|
15850
15792
|
ready();
|
|
15851
15793
|
if (closer)
|
|
15852
|
-
this.fsw._addPathCloser(
|
|
15794
|
+
this.fsw._addPathCloser(path30, closer);
|
|
15853
15795
|
return false;
|
|
15854
15796
|
} catch (error) {
|
|
15855
15797
|
if (this.fsw._handleError(error)) {
|
|
15856
15798
|
ready();
|
|
15857
|
-
return
|
|
15799
|
+
return path30;
|
|
15858
15800
|
}
|
|
15859
15801
|
}
|
|
15860
15802
|
}
|
|
@@ -15886,35 +15828,35 @@ function createPattern(matcher) {
|
|
|
15886
15828
|
if (matcher.path === string)
|
|
15887
15829
|
return true;
|
|
15888
15830
|
if (matcher.recursive) {
|
|
15889
|
-
const
|
|
15890
|
-
if (!
|
|
15831
|
+
const relative14 = sp2.relative(matcher.path, string);
|
|
15832
|
+
if (!relative14) {
|
|
15891
15833
|
return false;
|
|
15892
15834
|
}
|
|
15893
|
-
return !
|
|
15835
|
+
return !relative14.startsWith("..") && !sp2.isAbsolute(relative14);
|
|
15894
15836
|
}
|
|
15895
15837
|
return false;
|
|
15896
15838
|
};
|
|
15897
15839
|
}
|
|
15898
15840
|
return () => false;
|
|
15899
15841
|
}
|
|
15900
|
-
function normalizePath2(
|
|
15901
|
-
if (typeof
|
|
15842
|
+
function normalizePath2(path30) {
|
|
15843
|
+
if (typeof path30 !== "string")
|
|
15902
15844
|
throw new Error("string expected");
|
|
15903
|
-
|
|
15904
|
-
|
|
15845
|
+
path30 = sp2.normalize(path30);
|
|
15846
|
+
path30 = path30.replace(/\\/g, "/");
|
|
15905
15847
|
let prepend = false;
|
|
15906
|
-
if (
|
|
15848
|
+
if (path30.startsWith("//"))
|
|
15907
15849
|
prepend = true;
|
|
15908
|
-
|
|
15850
|
+
path30 = path30.replace(DOUBLE_SLASH_RE, "/");
|
|
15909
15851
|
if (prepend)
|
|
15910
|
-
|
|
15911
|
-
return
|
|
15852
|
+
path30 = "/" + path30;
|
|
15853
|
+
return path30;
|
|
15912
15854
|
}
|
|
15913
15855
|
function matchPatterns(patterns, testString, stats) {
|
|
15914
|
-
const
|
|
15856
|
+
const path30 = normalizePath2(testString);
|
|
15915
15857
|
for (let index = 0; index < patterns.length; index++) {
|
|
15916
15858
|
const pattern = patterns[index];
|
|
15917
|
-
if (pattern(
|
|
15859
|
+
if (pattern(path30, stats)) {
|
|
15918
15860
|
return true;
|
|
15919
15861
|
}
|
|
15920
15862
|
}
|
|
@@ -15952,19 +15894,19 @@ var toUnix = (string) => {
|
|
|
15952
15894
|
}
|
|
15953
15895
|
return str;
|
|
15954
15896
|
};
|
|
15955
|
-
var normalizePathToUnix = (
|
|
15956
|
-
var normalizeIgnored = (cwd = "") => (
|
|
15957
|
-
if (typeof
|
|
15958
|
-
return normalizePathToUnix(sp2.isAbsolute(
|
|
15897
|
+
var normalizePathToUnix = (path30) => toUnix(sp2.normalize(toUnix(path30)));
|
|
15898
|
+
var normalizeIgnored = (cwd = "") => (path30) => {
|
|
15899
|
+
if (typeof path30 === "string") {
|
|
15900
|
+
return normalizePathToUnix(sp2.isAbsolute(path30) ? path30 : sp2.join(cwd, path30));
|
|
15959
15901
|
} else {
|
|
15960
|
-
return
|
|
15902
|
+
return path30;
|
|
15961
15903
|
}
|
|
15962
15904
|
};
|
|
15963
|
-
var getAbsolutePath = (
|
|
15964
|
-
if (sp2.isAbsolute(
|
|
15965
|
-
return
|
|
15905
|
+
var getAbsolutePath = (path30, cwd) => {
|
|
15906
|
+
if (sp2.isAbsolute(path30)) {
|
|
15907
|
+
return path30;
|
|
15966
15908
|
}
|
|
15967
|
-
return sp2.join(cwd,
|
|
15909
|
+
return sp2.join(cwd, path30);
|
|
15968
15910
|
};
|
|
15969
15911
|
var EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
|
|
15970
15912
|
var DirEntry = class {
|
|
@@ -16029,10 +15971,10 @@ var WatchHelper = class {
|
|
|
16029
15971
|
dirParts;
|
|
16030
15972
|
followSymlinks;
|
|
16031
15973
|
statMethod;
|
|
16032
|
-
constructor(
|
|
15974
|
+
constructor(path30, follow, fsw) {
|
|
16033
15975
|
this.fsw = fsw;
|
|
16034
|
-
const watchPath =
|
|
16035
|
-
this.path =
|
|
15976
|
+
const watchPath = path30;
|
|
15977
|
+
this.path = path30 = path30.replace(REPLACER_RE, "");
|
|
16036
15978
|
this.watchPath = watchPath;
|
|
16037
15979
|
this.fullWatchPath = sp2.resolve(watchPath);
|
|
16038
15980
|
this.dirParts = [];
|
|
@@ -16172,20 +16114,20 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
16172
16114
|
this._closePromise = void 0;
|
|
16173
16115
|
let paths = unifyPaths(paths_);
|
|
16174
16116
|
if (cwd) {
|
|
16175
|
-
paths = paths.map((
|
|
16176
|
-
const absPath = getAbsolutePath(
|
|
16117
|
+
paths = paths.map((path30) => {
|
|
16118
|
+
const absPath = getAbsolutePath(path30, cwd);
|
|
16177
16119
|
return absPath;
|
|
16178
16120
|
});
|
|
16179
16121
|
}
|
|
16180
|
-
paths.forEach((
|
|
16181
|
-
this._removeIgnoredPath(
|
|
16122
|
+
paths.forEach((path30) => {
|
|
16123
|
+
this._removeIgnoredPath(path30);
|
|
16182
16124
|
});
|
|
16183
16125
|
this._userIgnored = void 0;
|
|
16184
16126
|
if (!this._readyCount)
|
|
16185
16127
|
this._readyCount = 0;
|
|
16186
16128
|
this._readyCount += paths.length;
|
|
16187
|
-
Promise.all(paths.map(async (
|
|
16188
|
-
const res = await this._nodeFsHandler._addToNodeFs(
|
|
16129
|
+
Promise.all(paths.map(async (path30) => {
|
|
16130
|
+
const res = await this._nodeFsHandler._addToNodeFs(path30, !_internal, void 0, 0, _origAdd);
|
|
16189
16131
|
if (res)
|
|
16190
16132
|
this._emitReady();
|
|
16191
16133
|
return res;
|
|
@@ -16207,17 +16149,17 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
16207
16149
|
return this;
|
|
16208
16150
|
const paths = unifyPaths(paths_);
|
|
16209
16151
|
const { cwd } = this.options;
|
|
16210
|
-
paths.forEach((
|
|
16211
|
-
if (!sp2.isAbsolute(
|
|
16152
|
+
paths.forEach((path30) => {
|
|
16153
|
+
if (!sp2.isAbsolute(path30) && !this._closers.has(path30)) {
|
|
16212
16154
|
if (cwd)
|
|
16213
|
-
|
|
16214
|
-
|
|
16155
|
+
path30 = sp2.join(cwd, path30);
|
|
16156
|
+
path30 = sp2.resolve(path30);
|
|
16215
16157
|
}
|
|
16216
|
-
this._closePath(
|
|
16217
|
-
this._addIgnoredPath(
|
|
16218
|
-
if (this._watched.has(
|
|
16158
|
+
this._closePath(path30);
|
|
16159
|
+
this._addIgnoredPath(path30);
|
|
16160
|
+
if (this._watched.has(path30)) {
|
|
16219
16161
|
this._addIgnoredPath({
|
|
16220
|
-
path:
|
|
16162
|
+
path: path30,
|
|
16221
16163
|
recursive: true
|
|
16222
16164
|
});
|
|
16223
16165
|
}
|
|
@@ -16281,38 +16223,38 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
16281
16223
|
* @param stats arguments to be passed with event
|
|
16282
16224
|
* @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
|
|
16283
16225
|
*/
|
|
16284
|
-
async _emit(event,
|
|
16226
|
+
async _emit(event, path30, stats) {
|
|
16285
16227
|
if (this.closed)
|
|
16286
16228
|
return;
|
|
16287
16229
|
const opts = this.options;
|
|
16288
16230
|
if (isWindows)
|
|
16289
|
-
|
|
16231
|
+
path30 = sp2.normalize(path30);
|
|
16290
16232
|
if (opts.cwd)
|
|
16291
|
-
|
|
16292
|
-
const args = [
|
|
16233
|
+
path30 = sp2.relative(opts.cwd, path30);
|
|
16234
|
+
const args = [path30];
|
|
16293
16235
|
if (stats != null)
|
|
16294
16236
|
args.push(stats);
|
|
16295
16237
|
const awf = opts.awaitWriteFinish;
|
|
16296
16238
|
let pw;
|
|
16297
|
-
if (awf && (pw = this._pendingWrites.get(
|
|
16239
|
+
if (awf && (pw = this._pendingWrites.get(path30))) {
|
|
16298
16240
|
pw.lastChange = /* @__PURE__ */ new Date();
|
|
16299
16241
|
return this;
|
|
16300
16242
|
}
|
|
16301
16243
|
if (opts.atomic) {
|
|
16302
16244
|
if (event === EVENTS.UNLINK) {
|
|
16303
|
-
this._pendingUnlinks.set(
|
|
16245
|
+
this._pendingUnlinks.set(path30, [event, ...args]);
|
|
16304
16246
|
setTimeout(() => {
|
|
16305
|
-
this._pendingUnlinks.forEach((entry,
|
|
16247
|
+
this._pendingUnlinks.forEach((entry, path31) => {
|
|
16306
16248
|
this.emit(...entry);
|
|
16307
16249
|
this.emit(EVENTS.ALL, ...entry);
|
|
16308
|
-
this._pendingUnlinks.delete(
|
|
16250
|
+
this._pendingUnlinks.delete(path31);
|
|
16309
16251
|
});
|
|
16310
16252
|
}, typeof opts.atomic === "number" ? opts.atomic : 100);
|
|
16311
16253
|
return this;
|
|
16312
16254
|
}
|
|
16313
|
-
if (event === EVENTS.ADD && this._pendingUnlinks.has(
|
|
16255
|
+
if (event === EVENTS.ADD && this._pendingUnlinks.has(path30)) {
|
|
16314
16256
|
event = EVENTS.CHANGE;
|
|
16315
|
-
this._pendingUnlinks.delete(
|
|
16257
|
+
this._pendingUnlinks.delete(path30);
|
|
16316
16258
|
}
|
|
16317
16259
|
}
|
|
16318
16260
|
if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
|
|
@@ -16330,16 +16272,16 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
16330
16272
|
this.emitWithAll(event, args);
|
|
16331
16273
|
}
|
|
16332
16274
|
};
|
|
16333
|
-
this._awaitWriteFinish(
|
|
16275
|
+
this._awaitWriteFinish(path30, awf.stabilityThreshold, event, awfEmit);
|
|
16334
16276
|
return this;
|
|
16335
16277
|
}
|
|
16336
16278
|
if (event === EVENTS.CHANGE) {
|
|
16337
|
-
const isThrottled = !this._throttle(EVENTS.CHANGE,
|
|
16279
|
+
const isThrottled = !this._throttle(EVENTS.CHANGE, path30, 50);
|
|
16338
16280
|
if (isThrottled)
|
|
16339
16281
|
return this;
|
|
16340
16282
|
}
|
|
16341
16283
|
if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
|
|
16342
|
-
const fullPath = opts.cwd ? sp2.join(opts.cwd,
|
|
16284
|
+
const fullPath = opts.cwd ? sp2.join(opts.cwd, path30) : path30;
|
|
16343
16285
|
let stats2;
|
|
16344
16286
|
try {
|
|
16345
16287
|
stats2 = await stat3(fullPath);
|
|
@@ -16370,23 +16312,23 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
16370
16312
|
* @param timeout duration of time to suppress duplicate actions
|
|
16371
16313
|
* @returns tracking object or false if action should be suppressed
|
|
16372
16314
|
*/
|
|
16373
|
-
_throttle(actionType,
|
|
16315
|
+
_throttle(actionType, path30, timeout) {
|
|
16374
16316
|
if (!this._throttled.has(actionType)) {
|
|
16375
16317
|
this._throttled.set(actionType, /* @__PURE__ */ new Map());
|
|
16376
16318
|
}
|
|
16377
16319
|
const action = this._throttled.get(actionType);
|
|
16378
16320
|
if (!action)
|
|
16379
16321
|
throw new Error("invalid throttle");
|
|
16380
|
-
const actionPath = action.get(
|
|
16322
|
+
const actionPath = action.get(path30);
|
|
16381
16323
|
if (actionPath) {
|
|
16382
16324
|
actionPath.count++;
|
|
16383
16325
|
return false;
|
|
16384
16326
|
}
|
|
16385
16327
|
let timeoutObject;
|
|
16386
16328
|
const clear = () => {
|
|
16387
|
-
const item = action.get(
|
|
16329
|
+
const item = action.get(path30);
|
|
16388
16330
|
const count = item ? item.count : 0;
|
|
16389
|
-
action.delete(
|
|
16331
|
+
action.delete(path30);
|
|
16390
16332
|
clearTimeout(timeoutObject);
|
|
16391
16333
|
if (item)
|
|
16392
16334
|
clearTimeout(item.timeoutObject);
|
|
@@ -16394,7 +16336,7 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
16394
16336
|
};
|
|
16395
16337
|
timeoutObject = setTimeout(clear, timeout);
|
|
16396
16338
|
const thr = { timeoutObject, clear, count: 0 };
|
|
16397
|
-
action.set(
|
|
16339
|
+
action.set(path30, thr);
|
|
16398
16340
|
return thr;
|
|
16399
16341
|
}
|
|
16400
16342
|
_incrReadyCount() {
|
|
@@ -16408,44 +16350,44 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
16408
16350
|
* @param event
|
|
16409
16351
|
* @param awfEmit Callback to be called when ready for event to be emitted.
|
|
16410
16352
|
*/
|
|
16411
|
-
_awaitWriteFinish(
|
|
16353
|
+
_awaitWriteFinish(path30, threshold, event, awfEmit) {
|
|
16412
16354
|
const awf = this.options.awaitWriteFinish;
|
|
16413
16355
|
if (typeof awf !== "object")
|
|
16414
16356
|
return;
|
|
16415
16357
|
const pollInterval = awf.pollInterval;
|
|
16416
16358
|
let timeoutHandler;
|
|
16417
|
-
let fullPath =
|
|
16418
|
-
if (this.options.cwd && !sp2.isAbsolute(
|
|
16419
|
-
fullPath = sp2.join(this.options.cwd,
|
|
16359
|
+
let fullPath = path30;
|
|
16360
|
+
if (this.options.cwd && !sp2.isAbsolute(path30)) {
|
|
16361
|
+
fullPath = sp2.join(this.options.cwd, path30);
|
|
16420
16362
|
}
|
|
16421
16363
|
const now2 = /* @__PURE__ */ new Date();
|
|
16422
16364
|
const writes = this._pendingWrites;
|
|
16423
16365
|
function awaitWriteFinishFn(prevStat) {
|
|
16424
16366
|
statcb(fullPath, (err, curStat) => {
|
|
16425
|
-
if (err || !writes.has(
|
|
16367
|
+
if (err || !writes.has(path30)) {
|
|
16426
16368
|
if (err && err.code !== "ENOENT")
|
|
16427
16369
|
awfEmit(err);
|
|
16428
16370
|
return;
|
|
16429
16371
|
}
|
|
16430
16372
|
const now3 = Number(/* @__PURE__ */ new Date());
|
|
16431
16373
|
if (prevStat && curStat.size !== prevStat.size) {
|
|
16432
|
-
writes.get(
|
|
16374
|
+
writes.get(path30).lastChange = now3;
|
|
16433
16375
|
}
|
|
16434
|
-
const pw = writes.get(
|
|
16376
|
+
const pw = writes.get(path30);
|
|
16435
16377
|
const df = now3 - pw.lastChange;
|
|
16436
16378
|
if (df >= threshold) {
|
|
16437
|
-
writes.delete(
|
|
16379
|
+
writes.delete(path30);
|
|
16438
16380
|
awfEmit(void 0, curStat);
|
|
16439
16381
|
} else {
|
|
16440
16382
|
timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
|
|
16441
16383
|
}
|
|
16442
16384
|
});
|
|
16443
16385
|
}
|
|
16444
|
-
if (!writes.has(
|
|
16445
|
-
writes.set(
|
|
16386
|
+
if (!writes.has(path30)) {
|
|
16387
|
+
writes.set(path30, {
|
|
16446
16388
|
lastChange: now2,
|
|
16447
16389
|
cancelWait: () => {
|
|
16448
|
-
writes.delete(
|
|
16390
|
+
writes.delete(path30);
|
|
16449
16391
|
clearTimeout(timeoutHandler);
|
|
16450
16392
|
return event;
|
|
16451
16393
|
}
|
|
@@ -16456,8 +16398,8 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
16456
16398
|
/**
|
|
16457
16399
|
* Determines whether user has asked to ignore this path.
|
|
16458
16400
|
*/
|
|
16459
|
-
_isIgnored(
|
|
16460
|
-
if (this.options.atomic && DOT_RE.test(
|
|
16401
|
+
_isIgnored(path30, stats) {
|
|
16402
|
+
if (this.options.atomic && DOT_RE.test(path30))
|
|
16461
16403
|
return true;
|
|
16462
16404
|
if (!this._userIgnored) {
|
|
16463
16405
|
const { cwd } = this.options;
|
|
@@ -16467,17 +16409,17 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
16467
16409
|
const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
|
|
16468
16410
|
this._userIgnored = anymatch(list, void 0);
|
|
16469
16411
|
}
|
|
16470
|
-
return this._userIgnored(
|
|
16412
|
+
return this._userIgnored(path30, stats);
|
|
16471
16413
|
}
|
|
16472
|
-
_isntIgnored(
|
|
16473
|
-
return !this._isIgnored(
|
|
16414
|
+
_isntIgnored(path30, stat5) {
|
|
16415
|
+
return !this._isIgnored(path30, stat5);
|
|
16474
16416
|
}
|
|
16475
16417
|
/**
|
|
16476
16418
|
* Provides a set of common helpers and properties relating to symlink handling.
|
|
16477
16419
|
* @param path file or directory pattern being watched
|
|
16478
16420
|
*/
|
|
16479
|
-
_getWatchHelpers(
|
|
16480
|
-
return new WatchHelper(
|
|
16421
|
+
_getWatchHelpers(path30) {
|
|
16422
|
+
return new WatchHelper(path30, this.options.followSymlinks, this);
|
|
16481
16423
|
}
|
|
16482
16424
|
// Directory helpers
|
|
16483
16425
|
// -----------------
|
|
@@ -16509,63 +16451,63 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
16509
16451
|
* @param item base path of item/directory
|
|
16510
16452
|
*/
|
|
16511
16453
|
_remove(directory, item, isDirectory) {
|
|
16512
|
-
const
|
|
16513
|
-
const fullPath = sp2.resolve(
|
|
16514
|
-
isDirectory = isDirectory != null ? isDirectory : this._watched.has(
|
|
16515
|
-
if (!this._throttle("remove",
|
|
16454
|
+
const path30 = sp2.join(directory, item);
|
|
16455
|
+
const fullPath = sp2.resolve(path30);
|
|
16456
|
+
isDirectory = isDirectory != null ? isDirectory : this._watched.has(path30) || this._watched.has(fullPath);
|
|
16457
|
+
if (!this._throttle("remove", path30, 100))
|
|
16516
16458
|
return;
|
|
16517
16459
|
if (!isDirectory && this._watched.size === 1) {
|
|
16518
16460
|
this.add(directory, item, true);
|
|
16519
16461
|
}
|
|
16520
|
-
const wp = this._getWatchedDir(
|
|
16462
|
+
const wp = this._getWatchedDir(path30);
|
|
16521
16463
|
const nestedDirectoryChildren = wp.getChildren();
|
|
16522
|
-
nestedDirectoryChildren.forEach((nested) => this._remove(
|
|
16464
|
+
nestedDirectoryChildren.forEach((nested) => this._remove(path30, nested));
|
|
16523
16465
|
const parent = this._getWatchedDir(directory);
|
|
16524
16466
|
const wasTracked = parent.has(item);
|
|
16525
16467
|
parent.remove(item);
|
|
16526
16468
|
if (this._symlinkPaths.has(fullPath)) {
|
|
16527
16469
|
this._symlinkPaths.delete(fullPath);
|
|
16528
16470
|
}
|
|
16529
|
-
let relPath =
|
|
16471
|
+
let relPath = path30;
|
|
16530
16472
|
if (this.options.cwd)
|
|
16531
|
-
relPath = sp2.relative(this.options.cwd,
|
|
16473
|
+
relPath = sp2.relative(this.options.cwd, path30);
|
|
16532
16474
|
if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
|
|
16533
16475
|
const event = this._pendingWrites.get(relPath).cancelWait();
|
|
16534
16476
|
if (event === EVENTS.ADD)
|
|
16535
16477
|
return;
|
|
16536
16478
|
}
|
|
16537
|
-
this._watched.delete(
|
|
16479
|
+
this._watched.delete(path30);
|
|
16538
16480
|
this._watched.delete(fullPath);
|
|
16539
16481
|
const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
|
|
16540
|
-
if (wasTracked && !this._isIgnored(
|
|
16541
|
-
this._emit(eventName,
|
|
16542
|
-
this._closePath(
|
|
16482
|
+
if (wasTracked && !this._isIgnored(path30))
|
|
16483
|
+
this._emit(eventName, path30);
|
|
16484
|
+
this._closePath(path30);
|
|
16543
16485
|
}
|
|
16544
16486
|
/**
|
|
16545
16487
|
* Closes all watchers for a path
|
|
16546
16488
|
*/
|
|
16547
|
-
_closePath(
|
|
16548
|
-
this._closeFile(
|
|
16549
|
-
const dir = sp2.dirname(
|
|
16550
|
-
this._getWatchedDir(dir).remove(sp2.basename(
|
|
16489
|
+
_closePath(path30) {
|
|
16490
|
+
this._closeFile(path30);
|
|
16491
|
+
const dir = sp2.dirname(path30);
|
|
16492
|
+
this._getWatchedDir(dir).remove(sp2.basename(path30));
|
|
16551
16493
|
}
|
|
16552
16494
|
/**
|
|
16553
16495
|
* Closes only file-specific watchers
|
|
16554
16496
|
*/
|
|
16555
|
-
_closeFile(
|
|
16556
|
-
const closers = this._closers.get(
|
|
16497
|
+
_closeFile(path30) {
|
|
16498
|
+
const closers = this._closers.get(path30);
|
|
16557
16499
|
if (!closers)
|
|
16558
16500
|
return;
|
|
16559
16501
|
closers.forEach((closer) => closer());
|
|
16560
|
-
this._closers.delete(
|
|
16502
|
+
this._closers.delete(path30);
|
|
16561
16503
|
}
|
|
16562
|
-
_addPathCloser(
|
|
16504
|
+
_addPathCloser(path30, closer) {
|
|
16563
16505
|
if (!closer)
|
|
16564
16506
|
return;
|
|
16565
|
-
let list = this._closers.get(
|
|
16507
|
+
let list = this._closers.get(path30);
|
|
16566
16508
|
if (!list) {
|
|
16567
16509
|
list = [];
|
|
16568
|
-
this._closers.set(
|
|
16510
|
+
this._closers.set(path30, list);
|
|
16569
16511
|
}
|
|
16570
16512
|
list.push(closer);
|
|
16571
16513
|
}
|
|
@@ -16595,12 +16537,291 @@ function watch(paths, options = {}) {
|
|
|
16595
16537
|
var chokidar_default = { watch, FSWatcher };
|
|
16596
16538
|
|
|
16597
16539
|
// src/watcher/file-watcher.ts
|
|
16540
|
+
import * as path23 from "path";
|
|
16541
|
+
|
|
16542
|
+
// src/watcher/native-recursive-watcher.ts
|
|
16543
|
+
import { watch as watch2 } from "fs";
|
|
16598
16544
|
import * as path21 from "path";
|
|
16545
|
+
var NativeRecursiveWatcher = class {
|
|
16546
|
+
constructor(root, onChange, options = {}) {
|
|
16547
|
+
this.root = root;
|
|
16548
|
+
this.onChange = onChange;
|
|
16549
|
+
this.watchFactory = options.watchFactory ?? this.defaultWatchFactory;
|
|
16550
|
+
this.onError = options.onError;
|
|
16551
|
+
}
|
|
16552
|
+
root;
|
|
16553
|
+
onChange;
|
|
16554
|
+
watcher = null;
|
|
16555
|
+
listenerToken = 0;
|
|
16556
|
+
watchFactory;
|
|
16557
|
+
onError;
|
|
16558
|
+
start() {
|
|
16559
|
+
if (this.watcher) return;
|
|
16560
|
+
const token = ++this.listenerToken;
|
|
16561
|
+
const listener = (_eventType, filename) => {
|
|
16562
|
+
if (this.watcher === null || this.listenerToken !== token) return;
|
|
16563
|
+
const absolutePath = this.toAbsolutePath(filename);
|
|
16564
|
+
const nextResult = this.onChange(absolutePath);
|
|
16565
|
+
if (nextResult instanceof Promise) {
|
|
16566
|
+
void nextResult.catch((error) => {
|
|
16567
|
+
console.error("[codebase-index] Error handling native watcher event:", error);
|
|
16568
|
+
});
|
|
16569
|
+
}
|
|
16570
|
+
};
|
|
16571
|
+
const watcher = this.watchFactory(this.root, listener, {
|
|
16572
|
+
persistent: true,
|
|
16573
|
+
recursive: true
|
|
16574
|
+
});
|
|
16575
|
+
watcher.on?.("error", (error) => {
|
|
16576
|
+
if (this.watcher === watcher && this.listenerToken === token) {
|
|
16577
|
+
this.onError?.(error);
|
|
16578
|
+
}
|
|
16579
|
+
});
|
|
16580
|
+
this.watcher = watcher;
|
|
16581
|
+
}
|
|
16582
|
+
async stop() {
|
|
16583
|
+
const watcher = this.watcher;
|
|
16584
|
+
this.watcher = null;
|
|
16585
|
+
this.listenerToken += 1;
|
|
16586
|
+
if (!watcher) return;
|
|
16587
|
+
await watcher.close();
|
|
16588
|
+
}
|
|
16589
|
+
toAbsolutePath(filename) {
|
|
16590
|
+
if (filename == null) return null;
|
|
16591
|
+
const normalizedFilename = typeof filename === "string" ? filename : filename.toString();
|
|
16592
|
+
const absolutePath = path21.resolve(this.root, normalizedFilename);
|
|
16593
|
+
const relativePath = path21.relative(this.root, absolutePath);
|
|
16594
|
+
const outsideRoot = relativePath === ".." || relativePath.startsWith(`..${path21.sep}`) || path21.isAbsolute(relativePath);
|
|
16595
|
+
return outsideRoot ? null : absolutePath;
|
|
16596
|
+
}
|
|
16597
|
+
defaultWatchFactory = (root, listener, options) => watch2(root, options, listener);
|
|
16598
|
+
};
|
|
16599
|
+
|
|
16600
|
+
// src/watcher/snapshot.ts
|
|
16601
|
+
import * as fsPromises4 from "fs/promises";
|
|
16602
|
+
import * as path22 from "path";
|
|
16603
|
+
async function buildFileSnapshotScan(projectRoot, config, configPaths = []) {
|
|
16604
|
+
const normalizedProjectRoot = path22.resolve(projectRoot);
|
|
16605
|
+
const ignoreFilter = createIgnoreFilter(normalizedProjectRoot);
|
|
16606
|
+
const includePatterns = [...config.include, ...config.additionalInclude ?? []];
|
|
16607
|
+
const maxDepth = config.indexing?.maxDepth ?? -1;
|
|
16608
|
+
const snapshot = /* @__PURE__ */ new Map();
|
|
16609
|
+
const unreadablePrefixes = /* @__PURE__ */ new Set();
|
|
16610
|
+
const includeFile = async (filePath) => {
|
|
16611
|
+
const normalizedPath2 = path22.resolve(filePath);
|
|
16612
|
+
if (!shouldIncludeFile(normalizedPath2, normalizedProjectRoot, includePatterns, config.exclude, ignoreFilter)) return;
|
|
16613
|
+
const stat5 = await readStatIfFile(normalizedPath2, unreadablePrefixes);
|
|
16614
|
+
if (stat5) snapshot.set(normalizedPath2, { size: stat5.size, mtimeMs: stat5.mtimeMs });
|
|
16615
|
+
};
|
|
16616
|
+
const walk = async (directoryPath, depth) => {
|
|
16617
|
+
let entries;
|
|
16618
|
+
try {
|
|
16619
|
+
entries = await fsPromises4.readdir(directoryPath, { withFileTypes: true });
|
|
16620
|
+
} catch (error) {
|
|
16621
|
+
if (isMissingFsError(error)) return;
|
|
16622
|
+
if (isPermissionFsError(error)) {
|
|
16623
|
+
unreadablePrefixes.add(path22.resolve(directoryPath));
|
|
16624
|
+
return;
|
|
16625
|
+
}
|
|
16626
|
+
throw error;
|
|
16627
|
+
}
|
|
16628
|
+
for (const entry of entries) {
|
|
16629
|
+
const fullPath = path22.join(directoryPath, entry.name);
|
|
16630
|
+
const relativePath = path22.relative(normalizedProjectRoot, fullPath);
|
|
16631
|
+
if (entry.isDirectory()) {
|
|
16632
|
+
if (hasFilteredPathSegment(relativePath, path22.sep) || isRestrictedDirectory(relativePath, path22.sep)) continue;
|
|
16633
|
+
if (ignoreFilter.ignores(relativePath)) continue;
|
|
16634
|
+
if (maxDepth === -1 || depth < maxDepth) await walk(fullPath, depth + 1);
|
|
16635
|
+
} else if (entry.isFile()) {
|
|
16636
|
+
await includeFile(fullPath);
|
|
16637
|
+
}
|
|
16638
|
+
}
|
|
16639
|
+
};
|
|
16640
|
+
await walk(normalizedProjectRoot, 0);
|
|
16641
|
+
await includeExplicitConfigPaths(snapshot, unreadablePrefixes, configPaths);
|
|
16642
|
+
return { entries: snapshot, unreadablePrefixes };
|
|
16643
|
+
}
|
|
16644
|
+
async function buildFileSnapshotForPathScan(projectRoot, config, configPaths, targetPath) {
|
|
16645
|
+
const normalizedProjectRoot = path22.resolve(projectRoot);
|
|
16646
|
+
const normalizedTargetPath = path22.resolve(targetPath);
|
|
16647
|
+
if (!isWithinPath(normalizedProjectRoot, normalizedTargetPath)) {
|
|
16648
|
+
return { entries: /* @__PURE__ */ new Map(), unreadablePrefixes: /* @__PURE__ */ new Set() };
|
|
16649
|
+
}
|
|
16650
|
+
const ignoreFilter = createIgnoreFilter(normalizedProjectRoot);
|
|
16651
|
+
const includePatterns = [...config.include, ...config.additionalInclude ?? []];
|
|
16652
|
+
const maxDepth = config.indexing?.maxDepth ?? -1;
|
|
16653
|
+
const explicitConfigPaths = new Set(configPaths.map((configPath) => path22.resolve(configPath)));
|
|
16654
|
+
const snapshot = /* @__PURE__ */ new Map();
|
|
16655
|
+
const unreadablePrefixes = /* @__PURE__ */ new Set();
|
|
16656
|
+
const includeFile = async (filePath) => {
|
|
16657
|
+
const normalizedPath2 = path22.resolve(filePath);
|
|
16658
|
+
if (!explicitConfigPaths.has(normalizedPath2) && !shouldIncludeFile(
|
|
16659
|
+
normalizedPath2,
|
|
16660
|
+
normalizedProjectRoot,
|
|
16661
|
+
includePatterns,
|
|
16662
|
+
config.exclude,
|
|
16663
|
+
ignoreFilter
|
|
16664
|
+
)) return;
|
|
16665
|
+
const stat5 = await readStatIfFile(normalizedPath2, unreadablePrefixes);
|
|
16666
|
+
if (stat5) snapshot.set(normalizedPath2, { size: stat5.size, mtimeMs: stat5.mtimeMs });
|
|
16667
|
+
};
|
|
16668
|
+
const walk = async (directoryPath, depth) => {
|
|
16669
|
+
let entries;
|
|
16670
|
+
try {
|
|
16671
|
+
entries = await fsPromises4.readdir(directoryPath, { withFileTypes: true });
|
|
16672
|
+
} catch (error) {
|
|
16673
|
+
if (isMissingFsError(error)) return;
|
|
16674
|
+
if (isPermissionFsError(error)) {
|
|
16675
|
+
unreadablePrefixes.add(path22.resolve(directoryPath));
|
|
16676
|
+
return;
|
|
16677
|
+
}
|
|
16678
|
+
throw error;
|
|
16679
|
+
}
|
|
16680
|
+
for (const entry of entries) {
|
|
16681
|
+
const fullPath = path22.join(directoryPath, entry.name);
|
|
16682
|
+
const relativePath = path22.relative(normalizedProjectRoot, fullPath);
|
|
16683
|
+
if (entry.isDirectory()) {
|
|
16684
|
+
if (hasFilteredPathSegment(relativePath, path22.sep) || isRestrictedDirectory(relativePath, path22.sep)) continue;
|
|
16685
|
+
if (ignoreFilter.ignores(relativePath)) continue;
|
|
16686
|
+
if (maxDepth === -1 || depth < maxDepth) await walk(fullPath, depth + 1);
|
|
16687
|
+
} else if (entry.isFile()) {
|
|
16688
|
+
await includeFile(fullPath);
|
|
16689
|
+
}
|
|
16690
|
+
}
|
|
16691
|
+
};
|
|
16692
|
+
const targetStat = await readStatIfFile(normalizedTargetPath, unreadablePrefixes);
|
|
16693
|
+
if (targetStat) await includeFile(normalizedTargetPath);
|
|
16694
|
+
else await walk(normalizedTargetPath, 0);
|
|
16695
|
+
await includeExplicitConfigPathsInPath(snapshot, unreadablePrefixes, configPaths, normalizedTargetPath);
|
|
16696
|
+
return { entries: snapshot, unreadablePrefixes };
|
|
16697
|
+
}
|
|
16698
|
+
function completeFileSnapshot(previous, scan) {
|
|
16699
|
+
const completed = new Map(scan.entries);
|
|
16700
|
+
for (const unreadablePrefix of scan.unreadablePrefixes) {
|
|
16701
|
+
for (const [entryPath, entry] of previous) {
|
|
16702
|
+
if (isWithinPath(unreadablePrefix, entryPath) && !completed.has(entryPath)) completed.set(entryPath, entry);
|
|
16703
|
+
}
|
|
16704
|
+
}
|
|
16705
|
+
return completed;
|
|
16706
|
+
}
|
|
16707
|
+
async function includeExplicitConfigPaths(snapshot, unreadablePrefixes, configPaths) {
|
|
16708
|
+
for (const configPath of [...new Set(configPaths.map((value) => path22.resolve(value)))]) {
|
|
16709
|
+
if (snapshot.has(configPath)) continue;
|
|
16710
|
+
const stat5 = await readStatIfFile(configPath, unreadablePrefixes);
|
|
16711
|
+
if (stat5) snapshot.set(configPath, { size: stat5.size, mtimeMs: stat5.mtimeMs });
|
|
16712
|
+
}
|
|
16713
|
+
}
|
|
16714
|
+
async function includeExplicitConfigPathsInPath(snapshot, unreadablePrefixes, configPaths, targetPath) {
|
|
16715
|
+
await includeExplicitConfigPaths(
|
|
16716
|
+
snapshot,
|
|
16717
|
+
unreadablePrefixes,
|
|
16718
|
+
configPaths.filter((configPath) => isWithinPath(targetPath, path22.resolve(configPath)))
|
|
16719
|
+
);
|
|
16720
|
+
}
|
|
16721
|
+
function isWithinPath(parentPath, childPath) {
|
|
16722
|
+
const relativePath = path22.relative(parentPath, childPath);
|
|
16723
|
+
return relativePath === "" || !relativePath.startsWith(`..${path22.sep}`) && relativePath !== ".." && !path22.isAbsolute(relativePath);
|
|
16724
|
+
}
|
|
16725
|
+
async function readStatIfFile(filePath, unreadablePrefixes) {
|
|
16726
|
+
try {
|
|
16727
|
+
const stat5 = await fsPromises4.stat(filePath);
|
|
16728
|
+
return stat5.isFile() ? stat5 : null;
|
|
16729
|
+
} catch (error) {
|
|
16730
|
+
if (isMissingFsError(error)) return null;
|
|
16731
|
+
if (isPermissionFsError(error)) {
|
|
16732
|
+
unreadablePrefixes.add(path22.resolve(filePath));
|
|
16733
|
+
return null;
|
|
16734
|
+
}
|
|
16735
|
+
throw error;
|
|
16736
|
+
}
|
|
16737
|
+
}
|
|
16738
|
+
function isMissingFsError(error) {
|
|
16739
|
+
return error instanceof Error && ["ENOENT", "ENOTDIR"].includes(error.code ?? "");
|
|
16740
|
+
}
|
|
16741
|
+
function isPermissionFsError(error) {
|
|
16742
|
+
return error instanceof Error && ["EACCES", "EPERM"].includes(error.code ?? "");
|
|
16743
|
+
}
|
|
16744
|
+
var diffTypeOrder = { add: 0, change: 1, unlink: 2 };
|
|
16745
|
+
function diffFileSnapshots(previous, current, forcedChanges = /* @__PURE__ */ new Set()) {
|
|
16746
|
+
const changes = [];
|
|
16747
|
+
for (const [filePath, previousEntry] of previous) {
|
|
16748
|
+
const currentEntry = current.get(filePath);
|
|
16749
|
+
if (!currentEntry) changes.push({ type: "unlink", path: filePath });
|
|
16750
|
+
else if (forcedChanges.has(filePath) || currentEntry.size !== previousEntry.size || currentEntry.mtimeMs !== previousEntry.mtimeMs) {
|
|
16751
|
+
changes.push({ type: "change", path: filePath });
|
|
16752
|
+
}
|
|
16753
|
+
}
|
|
16754
|
+
for (const [filePath] of current) {
|
|
16755
|
+
if (!previous.has(filePath)) changes.push({ type: "add", path: filePath });
|
|
16756
|
+
}
|
|
16757
|
+
return changes.sort((left, right) => left.path.localeCompare(right.path) || diffTypeOrder[left.type] - diffTypeOrder[right.type]);
|
|
16758
|
+
}
|
|
16759
|
+
|
|
16760
|
+
// src/watcher/snapshot-reconciler.ts
|
|
16761
|
+
var FileSnapshotReconciler = class {
|
|
16762
|
+
constructor(projectRoot, config, configPaths) {
|
|
16763
|
+
this.projectRoot = projectRoot;
|
|
16764
|
+
this.config = config;
|
|
16765
|
+
this.configPaths = configPaths;
|
|
16766
|
+
}
|
|
16767
|
+
projectRoot;
|
|
16768
|
+
config;
|
|
16769
|
+
configPaths;
|
|
16770
|
+
snapshot = null;
|
|
16771
|
+
reconciliationTail = Promise.resolve();
|
|
16772
|
+
async initialize() {
|
|
16773
|
+
this.snapshot = (await buildFileSnapshotScan(this.projectRoot, this.config, this.configPaths)).entries;
|
|
16774
|
+
}
|
|
16775
|
+
async reconcile(invalidations = []) {
|
|
16776
|
+
if (this.snapshot === null) {
|
|
16777
|
+
throw new Error("FileSnapshotReconciler is not initialized. Call initialize() before reconcile().");
|
|
16778
|
+
}
|
|
16779
|
+
const reconciliation = this.reconciliationTail.then(async () => {
|
|
16780
|
+
const previousSnapshot = this.snapshot;
|
|
16781
|
+
if (previousSnapshot === null) {
|
|
16782
|
+
throw new Error("FileSnapshotReconciler is not initialized. Call initialize() before reconcile().");
|
|
16783
|
+
}
|
|
16784
|
+
const normalizedInvalidations = invalidations.map((invalidation) => typeof invalidation === "string" || invalidation === null ? { path: invalidation, forceChange: false } : { path: invalidation.path, forceChange: invalidation.forceChange === true });
|
|
16785
|
+
const scopedPaths = normalizedInvalidations.map((invalidation) => invalidation.path).filter((filePath) => filePath !== null);
|
|
16786
|
+
const scan = scopedPaths.length === 0 || scopedPaths.length !== normalizedInvalidations.length ? await buildFileSnapshotScan(this.projectRoot, this.config, this.configPaths) : await this.reconcilePaths(previousSnapshot, scopedPaths);
|
|
16787
|
+
const nextSnapshot = completeFileSnapshot(previousSnapshot, scan);
|
|
16788
|
+
const forcedChanges = new Set(normalizedInvalidations.filter((invalidation) => invalidation.path !== null && invalidation.forceChange).map((invalidation) => invalidation.path));
|
|
16789
|
+
const changes = diffFileSnapshots(previousSnapshot, nextSnapshot, forcedChanges);
|
|
16790
|
+
this.snapshot = nextSnapshot;
|
|
16791
|
+
return changes;
|
|
16792
|
+
});
|
|
16793
|
+
this.reconciliationTail = reconciliation.then(() => void 0, () => void 0);
|
|
16794
|
+
return reconciliation;
|
|
16795
|
+
}
|
|
16796
|
+
async reconcilePaths(previousSnapshot, invalidatedPaths) {
|
|
16797
|
+
const scopes = this.getScopes(invalidatedPaths);
|
|
16798
|
+
const entries = new Map(previousSnapshot);
|
|
16799
|
+
const unreadablePrefixes = /* @__PURE__ */ new Set();
|
|
16800
|
+
for (const scope of scopes) {
|
|
16801
|
+
for (const previousPath of entries.keys()) {
|
|
16802
|
+
if (isWithinPath(scope, previousPath)) entries.delete(previousPath);
|
|
16803
|
+
}
|
|
16804
|
+
const scopedScan = await buildFileSnapshotForPathScan(this.projectRoot, this.config, this.configPaths, scope);
|
|
16805
|
+
for (const [filePath, entry] of scopedScan.entries) entries.set(filePath, entry);
|
|
16806
|
+
for (const unreadablePrefix of scopedScan.unreadablePrefixes) unreadablePrefixes.add(unreadablePrefix);
|
|
16807
|
+
}
|
|
16808
|
+
return { entries, unreadablePrefixes };
|
|
16809
|
+
}
|
|
16810
|
+
getScopes(invalidatedPaths) {
|
|
16811
|
+
const uniquePaths = [...new Set(invalidatedPaths)].sort((left, right) => left.length - right.length);
|
|
16812
|
+
return uniquePaths.filter((candidate, index) => !uniquePaths.slice(0, index).some(
|
|
16813
|
+
(ancestor) => isWithinPath(ancestor, candidate)
|
|
16814
|
+
));
|
|
16815
|
+
}
|
|
16816
|
+
};
|
|
16817
|
+
|
|
16818
|
+
// src/watcher/file-watcher.ts
|
|
16599
16819
|
var FileWatcher = class {
|
|
16600
16820
|
watcher = null;
|
|
16601
16821
|
projectRoot;
|
|
16602
16822
|
config;
|
|
16603
16823
|
configPath;
|
|
16824
|
+
backend;
|
|
16604
16825
|
projectConfigPaths;
|
|
16605
16826
|
pendingChanges = /* @__PURE__ */ new Map();
|
|
16606
16827
|
debounceTimer = null;
|
|
@@ -16610,44 +16831,74 @@ var FileWatcher = class {
|
|
|
16610
16831
|
resolveReady = null;
|
|
16611
16832
|
pollingFallbackAttempted = false;
|
|
16612
16833
|
pendingClose = null;
|
|
16834
|
+
startupReadySignals = 1;
|
|
16835
|
+
nativeWatcher = null;
|
|
16836
|
+
nativeReconciler = null;
|
|
16837
|
+
nativeSetupGeneration = 0;
|
|
16838
|
+
nativeStarting = false;
|
|
16839
|
+
nativeInitializing = false;
|
|
16840
|
+
nativeReconcileTimer = null;
|
|
16841
|
+
nativeInvalidatedPaths = /* @__PURE__ */ new Map();
|
|
16842
|
+
configPathStates = /* @__PURE__ */ new Map();
|
|
16613
16843
|
constructor(projectRoot, config, host, options = {}) {
|
|
16614
16844
|
this.projectRoot = projectRoot;
|
|
16615
16845
|
this.config = config;
|
|
16846
|
+
this.backend = options.backend ?? "auto";
|
|
16616
16847
|
this.configPath = options.configPath;
|
|
16617
16848
|
this.projectConfigPaths = options.configPath ? [options.configPath] : getProjectConfigCandidatePaths(projectRoot, host);
|
|
16618
16849
|
}
|
|
16619
16850
|
start(handler) {
|
|
16620
|
-
if (this.watcher) {
|
|
16851
|
+
if (this.watcher || this.nativeWatcher || this.nativeStarting) {
|
|
16621
16852
|
return;
|
|
16622
16853
|
}
|
|
16623
16854
|
this.onChanges = handler;
|
|
16624
16855
|
this.pollingFallbackAttempted = false;
|
|
16625
16856
|
this.resetReady();
|
|
16857
|
+
if (this.shouldUseNativeWatcher()) {
|
|
16858
|
+
if (this.hasExternalConfigWatchTarget()) {
|
|
16859
|
+
this.setStartupReadySignals(2);
|
|
16860
|
+
this.startExternalConfigWatcher();
|
|
16861
|
+
}
|
|
16862
|
+
this.nativeStarting = true;
|
|
16863
|
+
void this.createNativeWatcher();
|
|
16864
|
+
return;
|
|
16865
|
+
}
|
|
16626
16866
|
this.createWatcher();
|
|
16627
16867
|
}
|
|
16628
16868
|
resetReady() {
|
|
16629
|
-
this.readyPromise = new Promise((
|
|
16630
|
-
this.resolveReady =
|
|
16869
|
+
this.readyPromise = new Promise((resolve17) => {
|
|
16870
|
+
this.resolveReady = resolve17;
|
|
16631
16871
|
});
|
|
16872
|
+
this.startupReadySignals = 1;
|
|
16632
16873
|
}
|
|
16633
|
-
|
|
16634
|
-
|
|
16635
|
-
|
|
16636
|
-
|
|
16637
|
-
|
|
16638
|
-
|
|
16639
|
-
|
|
16640
|
-
|
|
16641
|
-
|
|
16642
|
-
}).map((projectConfigPath) => existsSync13(projectConfigPath) ? projectConfigPath : this.getNearestExistingDirectory(path21.dirname(projectConfigPath)));
|
|
16643
|
-
const uniqueExternalConfigTargets = [...new Set(externalConfigTargets)];
|
|
16644
|
-
if (uniqueExternalConfigTargets.length > 0) {
|
|
16645
|
-
watchTargets = [this.projectRoot, ...uniqueExternalConfigTargets];
|
|
16646
|
-
}
|
|
16874
|
+
setStartupReadySignals(expectedSignals) {
|
|
16875
|
+
if (!this.readyPromise) {
|
|
16876
|
+
return;
|
|
16877
|
+
}
|
|
16878
|
+
this.startupReadySignals = Math.max(0, expectedSignals);
|
|
16879
|
+
}
|
|
16880
|
+
reportStartupReadySignal() {
|
|
16881
|
+
if (!this.readyPromise || !this.resolveReady) {
|
|
16882
|
+
return;
|
|
16647
16883
|
}
|
|
16884
|
+
if (this.startupReadySignals <= 0) {
|
|
16885
|
+
return;
|
|
16886
|
+
}
|
|
16887
|
+
this.startupReadySignals -= 1;
|
|
16888
|
+
if (this.startupReadySignals !== 0) {
|
|
16889
|
+
return;
|
|
16890
|
+
}
|
|
16891
|
+
this.resolveReady();
|
|
16892
|
+
this.resolveReady = null;
|
|
16893
|
+
}
|
|
16894
|
+
createWatcher(watchTargets, usePolling = false, reportsStartupReady = true) {
|
|
16895
|
+
let reportedStartupReady = false;
|
|
16896
|
+
this.configPathStates = this.getConfigPathStates();
|
|
16897
|
+
const ignoreFilter = createIgnoreFilter(this.projectRoot);
|
|
16898
|
+
const resolvedWatchTargets = watchTargets ?? this.getFullChokidarWatchTargets();
|
|
16648
16899
|
const watcherOptions = {
|
|
16649
16900
|
ignored: (filePath) => {
|
|
16650
|
-
const relativePath =
|
|
16901
|
+
const relativePath = path23.relative(this.projectRoot, filePath);
|
|
16651
16902
|
if (!relativePath) return false;
|
|
16652
16903
|
if (this.isProjectConfigPathOrAncestor(relativePath)) {
|
|
16653
16904
|
return false;
|
|
@@ -16655,10 +16906,10 @@ var FileWatcher = class {
|
|
|
16655
16906
|
if (this.isOutsideProjectPath(relativePath)) {
|
|
16656
16907
|
return true;
|
|
16657
16908
|
}
|
|
16658
|
-
if (hasFilteredPathSegment(relativePath,
|
|
16909
|
+
if (hasFilteredPathSegment(relativePath, path23.sep)) {
|
|
16659
16910
|
return true;
|
|
16660
16911
|
}
|
|
16661
|
-
if (isRestrictedDirectory(relativePath,
|
|
16912
|
+
if (isRestrictedDirectory(relativePath, path23.sep)) {
|
|
16662
16913
|
return true;
|
|
16663
16914
|
}
|
|
16664
16915
|
if (ignoreFilter.ignores(relativePath)) {
|
|
@@ -16691,10 +16942,13 @@ var FileWatcher = class {
|
|
|
16691
16942
|
watcher = new FSWatcher(watcherOptions);
|
|
16692
16943
|
}
|
|
16693
16944
|
this.watcher = watcher;
|
|
16694
|
-
watcher.
|
|
16945
|
+
watcher.on("ready", () => {
|
|
16695
16946
|
if (this.watcher !== watcher) return;
|
|
16696
|
-
this.
|
|
16697
|
-
|
|
16947
|
+
this.reconcileConfigPathStates();
|
|
16948
|
+
if (reportsStartupReady) {
|
|
16949
|
+
this.reportStartupReadySignal();
|
|
16950
|
+
reportedStartupReady = true;
|
|
16951
|
+
}
|
|
16698
16952
|
});
|
|
16699
16953
|
watcher.on("error", (error) => {
|
|
16700
16954
|
const err = error instanceof Error ? error : null;
|
|
@@ -16708,10 +16962,13 @@ var FileWatcher = class {
|
|
|
16708
16962
|
console.error("[codebase-index] Failed to close exhausted file watcher:", closeError);
|
|
16709
16963
|
});
|
|
16710
16964
|
if (this.onChanges) {
|
|
16965
|
+
const replacementReportsStartupReady = reportsStartupReady || reportedStartupReady;
|
|
16711
16966
|
if (!this.resolveReady) {
|
|
16712
16967
|
this.resetReady();
|
|
16968
|
+
} else if (reportedStartupReady) {
|
|
16969
|
+
this.startupReadySignals += 1;
|
|
16713
16970
|
}
|
|
16714
|
-
this.createWatcher(true);
|
|
16971
|
+
this.createWatcher(resolvedWatchTargets, true, replacementReportsStartupReady);
|
|
16715
16972
|
} else {
|
|
16716
16973
|
this.watcher = null;
|
|
16717
16974
|
}
|
|
@@ -16722,13 +16979,166 @@ var FileWatcher = class {
|
|
|
16722
16979
|
watcher.on("add", (filePath) => this.handleChange(watcher, "add", filePath));
|
|
16723
16980
|
watcher.on("change", (filePath) => this.handleChange(watcher, "change", filePath));
|
|
16724
16981
|
watcher.on("unlink", (filePath) => this.handleChange(watcher, "unlink", filePath));
|
|
16725
|
-
watcher.add(
|
|
16982
|
+
watcher.add(resolvedWatchTargets);
|
|
16983
|
+
}
|
|
16984
|
+
shouldUseNativeWatcher() {
|
|
16985
|
+
if (this.backend === "chokidar") {
|
|
16986
|
+
return false;
|
|
16987
|
+
}
|
|
16988
|
+
return true;
|
|
16989
|
+
}
|
|
16990
|
+
getFullChokidarWatchTargets() {
|
|
16991
|
+
if (this.configPath) {
|
|
16992
|
+
return [this.projectRoot, this.configPath];
|
|
16993
|
+
}
|
|
16994
|
+
const externalConfigTargets = this.getExternalConfigWatchTargets();
|
|
16995
|
+
if (externalConfigTargets.length === 0) {
|
|
16996
|
+
return this.projectRoot;
|
|
16997
|
+
}
|
|
16998
|
+
return [this.projectRoot, ...externalConfigTargets];
|
|
16999
|
+
}
|
|
17000
|
+
getExternalConfigWatchTargets() {
|
|
17001
|
+
return [...new Set(
|
|
17002
|
+
this.projectConfigPaths.filter((projectConfigPath) => {
|
|
17003
|
+
const relativeConfigPath = path23.relative(this.projectRoot, projectConfigPath);
|
|
17004
|
+
return this.isOutsideProjectPath(relativeConfigPath);
|
|
17005
|
+
}).map((projectConfigPath) => {
|
|
17006
|
+
if (existsSync13(projectConfigPath)) {
|
|
17007
|
+
return projectConfigPath;
|
|
17008
|
+
}
|
|
17009
|
+
return this.getNearestExistingDirectory(path23.dirname(projectConfigPath));
|
|
17010
|
+
})
|
|
17011
|
+
)];
|
|
17012
|
+
}
|
|
17013
|
+
hasExternalConfigWatchTarget() {
|
|
17014
|
+
return this.getExternalConfigWatchTargets().length > 0;
|
|
17015
|
+
}
|
|
17016
|
+
startExternalConfigWatcher(usePolling = false) {
|
|
17017
|
+
const externalTargets = this.getExternalConfigWatchTargets();
|
|
17018
|
+
if (externalTargets.length === 0) {
|
|
17019
|
+
return;
|
|
17020
|
+
}
|
|
17021
|
+
this.createWatcher(externalTargets, usePolling);
|
|
17022
|
+
}
|
|
17023
|
+
async createNativeWatcher() {
|
|
17024
|
+
const generation = ++this.nativeSetupGeneration;
|
|
17025
|
+
const reconciler = new FileSnapshotReconciler(this.projectRoot, this.config, this.projectConfigPaths);
|
|
17026
|
+
const watcher = new NativeRecursiveWatcher(
|
|
17027
|
+
this.projectRoot,
|
|
17028
|
+
(filePath) => this.scheduleNativeReconciliation(generation, filePath),
|
|
17029
|
+
{ onError: (error) => void this.fallbackFromNativeWatcher(generation, error) }
|
|
17030
|
+
);
|
|
17031
|
+
this.nativeReconciler = reconciler;
|
|
17032
|
+
this.nativeWatcher = watcher;
|
|
17033
|
+
this.nativeInitializing = true;
|
|
17034
|
+
try {
|
|
17035
|
+
watcher.start();
|
|
17036
|
+
if (!this.isCurrentNativeSetup(generation)) {
|
|
17037
|
+
await watcher.stop();
|
|
17038
|
+
return;
|
|
17039
|
+
}
|
|
17040
|
+
await reconciler.initialize();
|
|
17041
|
+
if (!this.isCurrentNativeSetup(generation) || this.nativeWatcher !== watcher) {
|
|
17042
|
+
await watcher.stop();
|
|
17043
|
+
return;
|
|
17044
|
+
}
|
|
17045
|
+
this.nativeStarting = false;
|
|
17046
|
+
this.nativeInitializing = false;
|
|
17047
|
+
await this.reconcileNativeWatcherWithPendingInvalidations(generation);
|
|
17048
|
+
this.reportStartupReadySignal();
|
|
17049
|
+
} catch (error) {
|
|
17050
|
+
if (!this.isCurrentNativeSetup(generation)) return;
|
|
17051
|
+
this.nativeInitializing = false;
|
|
17052
|
+
if (this.nativeWatcher) {
|
|
17053
|
+
await this.fallbackFromNativeWatcher(generation, error);
|
|
17054
|
+
return;
|
|
17055
|
+
}
|
|
17056
|
+
this.nativeStarting = false;
|
|
17057
|
+
const externalWatcher = this.watcher;
|
|
17058
|
+
this.watcher = null;
|
|
17059
|
+
this.nativeReconciler = null;
|
|
17060
|
+
await externalWatcher?.close();
|
|
17061
|
+
console.warn("[codebase-index] Native recursive watcher unavailable; using Chokidar fallback.", error);
|
|
17062
|
+
this.setStartupReadySignals(1);
|
|
17063
|
+
this.createWatcher();
|
|
17064
|
+
}
|
|
17065
|
+
}
|
|
17066
|
+
isCurrentNativeSetup(generation) {
|
|
17067
|
+
return this.nativeSetupGeneration === generation && this.onChanges !== null;
|
|
17068
|
+
}
|
|
17069
|
+
scheduleNativeReconciliation(generation, filePath) {
|
|
17070
|
+
if (!this.isCurrentNativeSetup(generation)) return;
|
|
17071
|
+
const requiresFullReconciliation = filePath === path23.join(this.projectRoot, ".gitignore");
|
|
17072
|
+
const invalidatedPath = requiresFullReconciliation ? null : filePath;
|
|
17073
|
+
this.nativeInvalidatedPaths.set(invalidatedPath, invalidatedPath !== null);
|
|
17074
|
+
if (this.nativeReconcileTimer) {
|
|
17075
|
+
clearTimeout(this.nativeReconcileTimer);
|
|
17076
|
+
}
|
|
17077
|
+
this.nativeReconcileTimer = setTimeout(() => {
|
|
17078
|
+
this.nativeReconcileTimer = null;
|
|
17079
|
+
void this.reconcileNativeWatcherFromQueue(generation);
|
|
17080
|
+
}, 100);
|
|
17081
|
+
}
|
|
17082
|
+
reconcileNativeWatcherFromQueue(generation) {
|
|
17083
|
+
if (!this.isCurrentNativeSetup(generation) || this.nativeInitializing) return;
|
|
17084
|
+
const invalidatedPaths = this.popNativeInvalidations();
|
|
17085
|
+
if (invalidatedPaths.length === 0) return;
|
|
17086
|
+
void this.reconcileNativeWatcher(generation, invalidatedPaths);
|
|
17087
|
+
}
|
|
17088
|
+
async reconcileNativeWatcher(generation, invalidatedPaths) {
|
|
17089
|
+
if (!this.isCurrentNativeSetup(generation) || !this.nativeReconciler) return;
|
|
17090
|
+
try {
|
|
17091
|
+
const reconciler = this.nativeReconciler;
|
|
17092
|
+
const changes = await reconciler.reconcile(invalidatedPaths);
|
|
17093
|
+
if (!this.isCurrentNativeSetup(generation) || this.nativeReconciler !== reconciler) return;
|
|
17094
|
+
this.recordChanges(changes);
|
|
17095
|
+
} catch (error) {
|
|
17096
|
+
await this.fallbackFromNativeWatcher(generation, error);
|
|
17097
|
+
}
|
|
17098
|
+
}
|
|
17099
|
+
async reconcileNativeWatcherWithPendingInvalidations(generation) {
|
|
17100
|
+
const invalidatedPaths = this.popNativeInvalidations();
|
|
17101
|
+
if (invalidatedPaths.length === 0) return;
|
|
17102
|
+
await this.reconcileNativeWatcher(generation, invalidatedPaths);
|
|
17103
|
+
}
|
|
17104
|
+
popNativeInvalidations() {
|
|
17105
|
+
if (this.nativeInvalidatedPaths.size === 0) return [];
|
|
17106
|
+
const invalidations = [...this.nativeInvalidatedPaths].map(([invalidatedPath, forceChange]) => ({
|
|
17107
|
+
path: invalidatedPath,
|
|
17108
|
+
forceChange
|
|
17109
|
+
}));
|
|
17110
|
+
this.nativeInvalidatedPaths.clear();
|
|
17111
|
+
return invalidations;
|
|
17112
|
+
}
|
|
17113
|
+
async fallbackFromNativeWatcher(generation, error) {
|
|
17114
|
+
if (!this.isCurrentNativeSetup(generation)) return;
|
|
17115
|
+
const watcher = this.nativeWatcher;
|
|
17116
|
+
const externalWatcher = this.watcher;
|
|
17117
|
+
this.nativeWatcher = null;
|
|
17118
|
+
this.watcher = null;
|
|
17119
|
+
this.nativeReconciler = null;
|
|
17120
|
+
this.nativeStarting = false;
|
|
17121
|
+
this.nativeInitializing = false;
|
|
17122
|
+
this.nativeSetupGeneration += 1;
|
|
17123
|
+
if (this.nativeReconcileTimer) {
|
|
17124
|
+
clearTimeout(this.nativeReconcileTimer);
|
|
17125
|
+
this.nativeReconcileTimer = null;
|
|
17126
|
+
}
|
|
17127
|
+
this.nativeInvalidatedPaths.clear();
|
|
17128
|
+
this.setStartupReadySignals(1);
|
|
17129
|
+
console.warn("[codebase-index] Native recursive watcher failed; using Chokidar fallback.", error);
|
|
17130
|
+
await watcher?.stop();
|
|
17131
|
+
await externalWatcher?.close();
|
|
17132
|
+
if (this.onChanges) {
|
|
17133
|
+
this.createWatcher();
|
|
17134
|
+
}
|
|
16726
17135
|
}
|
|
16727
17136
|
handleChange(watcher, type, filePath) {
|
|
16728
17137
|
if (this.watcher !== watcher) {
|
|
16729
17138
|
return;
|
|
16730
17139
|
}
|
|
16731
17140
|
if (this.isProjectConfigPath(filePath)) {
|
|
17141
|
+
this.updateConfigPathState(filePath);
|
|
16732
17142
|
this.pendingChanges.set(filePath, type);
|
|
16733
17143
|
this.scheduleFlush();
|
|
16734
17144
|
return;
|
|
@@ -16743,27 +17153,33 @@ var FileWatcher = class {
|
|
|
16743
17153
|
)) {
|
|
16744
17154
|
return;
|
|
16745
17155
|
}
|
|
16746
|
-
this.
|
|
17156
|
+
this.recordChanges([{ path: filePath, type }]);
|
|
17157
|
+
}
|
|
17158
|
+
recordChanges(changes) {
|
|
17159
|
+
if (changes.length === 0) return;
|
|
17160
|
+
for (const change of changes) {
|
|
17161
|
+
this.pendingChanges.set(change.path, change.type);
|
|
17162
|
+
}
|
|
16747
17163
|
this.scheduleFlush();
|
|
16748
17164
|
}
|
|
16749
17165
|
isProjectConfigPath(filePath) {
|
|
16750
|
-
const relativePath =
|
|
16751
|
-
const normalizedRelativePath =
|
|
17166
|
+
const relativePath = path23.relative(this.projectRoot, filePath);
|
|
17167
|
+
const normalizedRelativePath = path23.normalize(relativePath);
|
|
16752
17168
|
return this.getProjectConfigRelativePaths().some((configPath) => configPath === normalizedRelativePath);
|
|
16753
17169
|
}
|
|
16754
17170
|
isProjectConfigPathOrAncestor(relativePath) {
|
|
16755
|
-
const normalizedRelativePath =
|
|
17171
|
+
const normalizedRelativePath = path23.normalize(relativePath);
|
|
16756
17172
|
return this.getProjectConfigRelativePaths().some(
|
|
16757
|
-
(configPath) => configPath === normalizedRelativePath || configPath.startsWith(`${normalizedRelativePath}${
|
|
17173
|
+
(configPath) => configPath === normalizedRelativePath || configPath.startsWith(`${normalizedRelativePath}${path23.sep}`)
|
|
16758
17174
|
);
|
|
16759
17175
|
}
|
|
16760
17176
|
isOutsideProjectPath(relativePath) {
|
|
16761
|
-
return relativePath === ".." || relativePath.startsWith(`..${
|
|
17177
|
+
return relativePath === ".." || relativePath.startsWith(`..${path23.sep}`) || path23.isAbsolute(relativePath);
|
|
16762
17178
|
}
|
|
16763
17179
|
getNearestExistingDirectory(directoryPath) {
|
|
16764
17180
|
let candidate = directoryPath;
|
|
16765
17181
|
while (!existsSync13(candidate)) {
|
|
16766
|
-
const parent =
|
|
17182
|
+
const parent = path23.dirname(candidate);
|
|
16767
17183
|
if (parent === candidate) break;
|
|
16768
17184
|
candidate = parent;
|
|
16769
17185
|
}
|
|
@@ -16771,9 +17187,51 @@ var FileWatcher = class {
|
|
|
16771
17187
|
}
|
|
16772
17188
|
getProjectConfigRelativePaths() {
|
|
16773
17189
|
return this.projectConfigPaths.map(
|
|
16774
|
-
(configPath) =>
|
|
17190
|
+
(configPath) => path23.normalize(path23.relative(this.projectRoot, configPath))
|
|
16775
17191
|
);
|
|
16776
17192
|
}
|
|
17193
|
+
getConfigPathStates() {
|
|
17194
|
+
const states = /* @__PURE__ */ new Map();
|
|
17195
|
+
for (const configPath of this.projectConfigPaths) {
|
|
17196
|
+
const state = this.getConfigPathState(configPath);
|
|
17197
|
+
if (state) states.set(configPath, state);
|
|
17198
|
+
}
|
|
17199
|
+
return states;
|
|
17200
|
+
}
|
|
17201
|
+
getConfigPathState(configPath) {
|
|
17202
|
+
try {
|
|
17203
|
+
const stats = statSync6(configPath);
|
|
17204
|
+
return stats.isFile() ? { mtimeMs: stats.mtimeMs, size: stats.size } : void 0;
|
|
17205
|
+
} catch (error) {
|
|
17206
|
+
void error;
|
|
17207
|
+
return void 0;
|
|
17208
|
+
}
|
|
17209
|
+
}
|
|
17210
|
+
updateConfigPathState(configPath) {
|
|
17211
|
+
const state = this.getConfigPathState(configPath);
|
|
17212
|
+
if (state) {
|
|
17213
|
+
this.configPathStates.set(configPath, state);
|
|
17214
|
+
} else {
|
|
17215
|
+
this.configPathStates.delete(configPath);
|
|
17216
|
+
}
|
|
17217
|
+
}
|
|
17218
|
+
reconcileConfigPathStates() {
|
|
17219
|
+
const nextStates = this.getConfigPathStates();
|
|
17220
|
+
const changes = [];
|
|
17221
|
+
for (const configPath of this.projectConfigPaths) {
|
|
17222
|
+
const previous = this.configPathStates.get(configPath);
|
|
17223
|
+
const next = nextStates.get(configPath);
|
|
17224
|
+
if (!previous && next) {
|
|
17225
|
+
changes.push({ path: configPath, type: "add" });
|
|
17226
|
+
} else if (previous && !next) {
|
|
17227
|
+
changes.push({ path: configPath, type: "unlink" });
|
|
17228
|
+
} else if (previous && next && (previous.size !== next.size || previous.mtimeMs !== next.mtimeMs)) {
|
|
17229
|
+
changes.push({ path: configPath, type: "change" });
|
|
17230
|
+
}
|
|
17231
|
+
}
|
|
17232
|
+
this.configPathStates = nextStates;
|
|
17233
|
+
this.recordChanges(changes);
|
|
17234
|
+
}
|
|
16777
17235
|
scheduleFlush() {
|
|
16778
17236
|
if (this.debounceTimer) {
|
|
16779
17237
|
clearTimeout(this.debounceTimer);
|
|
@@ -16787,7 +17245,7 @@ var FileWatcher = class {
|
|
|
16787
17245
|
return;
|
|
16788
17246
|
}
|
|
16789
17247
|
const changes = Array.from(this.pendingChanges.entries()).map(
|
|
16790
|
-
([
|
|
17248
|
+
([path30, type]) => ({ path: path30, type })
|
|
16791
17249
|
);
|
|
16792
17250
|
this.pendingChanges.clear();
|
|
16793
17251
|
try {
|
|
@@ -16801,20 +17259,31 @@ var FileWatcher = class {
|
|
|
16801
17259
|
clearTimeout(this.debounceTimer);
|
|
16802
17260
|
this.debounceTimer = null;
|
|
16803
17261
|
}
|
|
17262
|
+
if (this.nativeReconcileTimer) {
|
|
17263
|
+
clearTimeout(this.nativeReconcileTimer);
|
|
17264
|
+
this.nativeReconcileTimer = null;
|
|
17265
|
+
}
|
|
17266
|
+
this.nativeInvalidatedPaths.clear();
|
|
16804
17267
|
const watcher = this.watcher;
|
|
17268
|
+
const nativeWatcher = this.nativeWatcher;
|
|
16805
17269
|
const pendingClose = this.pendingClose;
|
|
16806
17270
|
const resolveReady = this.resolveReady;
|
|
16807
17271
|
this.watcher = null;
|
|
17272
|
+
this.nativeWatcher = null;
|
|
17273
|
+
this.nativeReconciler = null;
|
|
17274
|
+
this.nativeStarting = false;
|
|
17275
|
+
this.nativeInitializing = false;
|
|
17276
|
+
this.nativeSetupGeneration += 1;
|
|
16808
17277
|
this.pendingClose = null;
|
|
16809
17278
|
this.resolveReady = null;
|
|
16810
17279
|
this.readyPromise = null;
|
|
16811
17280
|
this.pendingChanges.clear();
|
|
16812
17281
|
this.onChanges = null;
|
|
16813
|
-
await Promise.all([watcher?.close(), pendingClose]);
|
|
17282
|
+
await Promise.all([watcher?.close(), nativeWatcher?.stop(), pendingClose]);
|
|
16814
17283
|
resolveReady?.();
|
|
16815
17284
|
}
|
|
16816
17285
|
isRunning() {
|
|
16817
|
-
return this.watcher !== null;
|
|
17286
|
+
return this.watcher !== null || this.nativeWatcher !== null || this.nativeStarting;
|
|
16818
17287
|
}
|
|
16819
17288
|
async waitUntilReady() {
|
|
16820
17289
|
await (this.readyPromise ?? Promise.resolve());
|
|
@@ -16822,7 +17291,7 @@ var FileWatcher = class {
|
|
|
16822
17291
|
};
|
|
16823
17292
|
|
|
16824
17293
|
// src/watcher/git-head-watcher.ts
|
|
16825
|
-
import * as
|
|
17294
|
+
import * as path24 from "path";
|
|
16826
17295
|
var GitHeadWatcher = class {
|
|
16827
17296
|
watcher = null;
|
|
16828
17297
|
projectRoot;
|
|
@@ -16844,13 +17313,13 @@ var GitHeadWatcher = class {
|
|
|
16844
17313
|
this.readyPromise = Promise.resolve();
|
|
16845
17314
|
return;
|
|
16846
17315
|
}
|
|
16847
|
-
this.readyPromise = new Promise((
|
|
16848
|
-
this.resolveReady =
|
|
17316
|
+
this.readyPromise = new Promise((resolve17) => {
|
|
17317
|
+
this.resolveReady = resolve17;
|
|
16849
17318
|
});
|
|
16850
17319
|
this.onBranchChange = handler;
|
|
16851
17320
|
this.currentBranch = getCurrentBranch(this.projectRoot);
|
|
16852
17321
|
const headPath = getHeadPath(this.projectRoot);
|
|
16853
|
-
const refsPath =
|
|
17322
|
+
const refsPath = path24.join(this.projectRoot, ".git", "refs", "heads");
|
|
16854
17323
|
this.watcher = chokidar_default.watch([headPath, refsPath], {
|
|
16855
17324
|
persistent: true,
|
|
16856
17325
|
ignoreInitial: true,
|
|
@@ -17706,7 +18175,7 @@ async function resolveCodebaseContextUnmeasured(projectRoot, host, input) {
|
|
|
17706
18175
|
const directory = input.directory ?? void 0;
|
|
17707
18176
|
const tokenBudget = input.tokenBudget ?? void 0;
|
|
17708
18177
|
if (from && to) {
|
|
17709
|
-
const
|
|
18178
|
+
const path30 = await getCallGraphPath(
|
|
17710
18179
|
projectRoot,
|
|
17711
18180
|
host,
|
|
17712
18181
|
from,
|
|
@@ -17715,25 +18184,25 @@ async function resolveCodebaseContextUnmeasured(projectRoot, host, input) {
|
|
|
17715
18184
|
fromFilePath,
|
|
17716
18185
|
toFilePath
|
|
17717
18186
|
);
|
|
17718
|
-
const pathText = formatCallGraphPathResult(
|
|
17719
|
-
if (
|
|
18187
|
+
const pathText = formatCallGraphPathResult(path30);
|
|
18188
|
+
if (path30.path.length > 0) {
|
|
17720
18189
|
const fitted2 = fitTextToContextBudget(
|
|
17721
18190
|
pathText,
|
|
17722
18191
|
tokenBudget
|
|
17723
18192
|
);
|
|
17724
18193
|
return {
|
|
17725
18194
|
text: fitted2.text,
|
|
17726
|
-
details: fittedDetails("path", fitted2,
|
|
18195
|
+
details: fittedDetails("path", fitted2, path30.path.length)
|
|
17727
18196
|
};
|
|
17728
18197
|
}
|
|
17729
|
-
if (
|
|
18198
|
+
if (path30.from.status !== "resolved" || path30.to.status !== "resolved") {
|
|
17730
18199
|
const fitted2 = fitTextToContextBudget(pathText, tokenBudget);
|
|
17731
18200
|
return {
|
|
17732
18201
|
text: fitted2.text,
|
|
17733
18202
|
details: fittedDetails("path", fitted2, 0)
|
|
17734
18203
|
};
|
|
17735
18204
|
}
|
|
17736
|
-
const resolvedFrom =
|
|
18205
|
+
const resolvedFrom = path30.from;
|
|
17737
18206
|
const { callers } = await getCallGraphData(projectRoot, host, {
|
|
17738
18207
|
name: to,
|
|
17739
18208
|
direction: "callers",
|
|
@@ -17892,7 +18361,7 @@ async function executeCallGraph(projectRoot, host, args) {
|
|
|
17892
18361
|
return { text: formatCallGraphResult(await getCallGraphData(projectRoot, host, args)) };
|
|
17893
18362
|
}
|
|
17894
18363
|
async function executeCallGraphPath(projectRoot, host, args) {
|
|
17895
|
-
const
|
|
18364
|
+
const path30 = await getCallGraphPath(
|
|
17896
18365
|
projectRoot,
|
|
17897
18366
|
host,
|
|
17898
18367
|
args.from,
|
|
@@ -17901,7 +18370,7 @@ async function executeCallGraphPath(projectRoot, host, args) {
|
|
|
17901
18370
|
args.fromFilePath,
|
|
17902
18371
|
args.toFilePath
|
|
17903
18372
|
);
|
|
17904
|
-
return { text: formatCallGraphPathResult(
|
|
18373
|
+
return { text: formatCallGraphPathResult(path30) };
|
|
17905
18374
|
}
|
|
17906
18375
|
async function executeCodeCommunities(projectRoot, host, args) {
|
|
17907
18376
|
const result = await getCodeCommunities(projectRoot, host, args);
|
|
@@ -17911,11 +18380,11 @@ async function executeCodeCommunities(projectRoot, host, args) {
|
|
|
17911
18380
|
// src/adapters/opencode/tools.ts
|
|
17912
18381
|
import { writeFileSync as writeFileSync4 } from "fs";
|
|
17913
18382
|
import * as os7 from "os";
|
|
17914
|
-
import * as
|
|
18383
|
+
import * as path27 from "path";
|
|
17915
18384
|
|
|
17916
18385
|
// src/tools/visualize/activity.ts
|
|
17917
18386
|
import { execFileSync } from "child_process";
|
|
17918
|
-
import * as
|
|
18387
|
+
import * as path25 from "path";
|
|
17919
18388
|
function attachRecentActivity(data, projectRoot) {
|
|
17920
18389
|
const activity = readGitActivity(projectRoot);
|
|
17921
18390
|
const changes = activity.size > 0 ? buildGitChanges(data, activity, projectRoot) : buildGraphChanges(data);
|
|
@@ -18077,7 +18546,7 @@ function normalizePath3(filePath) {
|
|
|
18077
18546
|
return filePath.replace(/\\/g, "/");
|
|
18078
18547
|
}
|
|
18079
18548
|
function toGitRelativePath(projectRoot, filePath) {
|
|
18080
|
-
const relativePath =
|
|
18549
|
+
const relativePath = path25.isAbsolute(filePath) ? path25.relative(projectRoot, filePath) : filePath;
|
|
18081
18550
|
return normalizePath3(relativePath);
|
|
18082
18551
|
}
|
|
18083
18552
|
|
|
@@ -18335,7 +18804,7 @@ render();
|
|
|
18335
18804
|
}
|
|
18336
18805
|
|
|
18337
18806
|
// src/tools/visualize/transform.ts
|
|
18338
|
-
import * as
|
|
18807
|
+
import * as path26 from "path";
|
|
18339
18808
|
|
|
18340
18809
|
// src/tools/visualize/modules.ts
|
|
18341
18810
|
var MAX_MODULES = 18;
|
|
@@ -18468,8 +18937,8 @@ function compactModules(prefixToNodes) {
|
|
|
18468
18937
|
function deriveModules(nodes) {
|
|
18469
18938
|
const initial = /* @__PURE__ */ new Map();
|
|
18470
18939
|
for (const node of nodes) {
|
|
18471
|
-
const
|
|
18472
|
-
const prefix = modulePrefixFromRelativePath(
|
|
18940
|
+
const relative14 = stripToProjectRelative(node.filePath);
|
|
18941
|
+
const prefix = modulePrefixFromRelativePath(relative14);
|
|
18473
18942
|
if (!initial.has(prefix)) initial.set(prefix, []);
|
|
18474
18943
|
initial.get(prefix)?.push(node);
|
|
18475
18944
|
}
|
|
@@ -18595,7 +19064,7 @@ function transformForVisualization(symbols, edges, options = {}) {
|
|
|
18595
19064
|
filePath: s.filePath,
|
|
18596
19065
|
kind: s.kind,
|
|
18597
19066
|
line: s.startLine,
|
|
18598
|
-
directory:
|
|
19067
|
+
directory: path26.dirname(s.filePath),
|
|
18599
19068
|
moduleId: "",
|
|
18600
19069
|
moduleLabel: ""
|
|
18601
19070
|
}));
|
|
@@ -18915,7 +19384,7 @@ var index_visualize = tool({
|
|
|
18915
19384
|
return "No connected symbols found for visualization. Try including orphans with includeOrphans=true, or check that the call graph has resolved edges.";
|
|
18916
19385
|
}
|
|
18917
19386
|
const html = generateVisualizationHtml(vizData);
|
|
18918
|
-
const outputPath =
|
|
19387
|
+
const outputPath = path27.join(os7.tmpdir(), `call-graph-${Date.now()}.html`);
|
|
18919
19388
|
writeFileSync4(outputPath, html, "utf-8");
|
|
18920
19389
|
let result = `Temporal call graph visualization generated: ${outputPath}
|
|
18921
19390
|
|
|
@@ -19022,7 +19491,7 @@ var PI_TOOL_NAMES = [
|
|
|
19022
19491
|
|
|
19023
19492
|
// src/commands/loader.ts
|
|
19024
19493
|
import { existsSync as existsSync14, readdirSync as readdirSync3, readFileSync as readFileSync9 } from "fs";
|
|
19025
|
-
import * as
|
|
19494
|
+
import * as path28 from "path";
|
|
19026
19495
|
function parseFrontmatter(content) {
|
|
19027
19496
|
const frontmatterRegex = /^---\s*\n([\s\S]*?)\n---\s*\n([\s\S]*)$/;
|
|
19028
19497
|
const match = content.match(frontmatterRegex);
|
|
@@ -19048,7 +19517,7 @@ function loadCommandsFromDirectory(commandsDir) {
|
|
|
19048
19517
|
}
|
|
19049
19518
|
const files = readdirSync3(commandsDir).filter((f) => f.endsWith(".md"));
|
|
19050
19519
|
for (const file of files) {
|
|
19051
|
-
const filePath =
|
|
19520
|
+
const filePath = path28.join(commandsDir, file);
|
|
19052
19521
|
let content;
|
|
19053
19522
|
try {
|
|
19054
19523
|
content = readFileSync9(filePath, "utf-8");
|
|
@@ -19057,7 +19526,7 @@ function loadCommandsFromDirectory(commandsDir) {
|
|
|
19057
19526
|
throw new Error(`Failed to load command file ${filePath}: ${message}`);
|
|
19058
19527
|
}
|
|
19059
19528
|
const { frontmatter, body } = parseFrontmatter(content);
|
|
19060
|
-
const name =
|
|
19529
|
+
const name = path28.basename(file, ".md");
|
|
19061
19530
|
const description = frontmatter.description || `Run the ${name} command`;
|
|
19062
19531
|
commands.set(name, {
|
|
19063
19532
|
description,
|
|
@@ -19391,23 +19860,41 @@ var RoutingHintController = class {
|
|
|
19391
19860
|
|
|
19392
19861
|
// src/adapters/opencode.ts
|
|
19393
19862
|
var activeWatchers = /* @__PURE__ */ new Map();
|
|
19394
|
-
|
|
19395
|
-
|
|
19396
|
-
|
|
19397
|
-
existing.
|
|
19398
|
-
|
|
19399
|
-
|
|
19400
|
-
|
|
19401
|
-
|
|
19863
|
+
var watcherReplacementChains = /* @__PURE__ */ new Map();
|
|
19864
|
+
async function replaceActiveWatcher(projectRoot, createNextWatcher) {
|
|
19865
|
+
const chain = (watcherReplacementChains.get(projectRoot) ?? Promise.resolve()).catch(() => void 0).then(async () => {
|
|
19866
|
+
const existing = activeWatchers.get(projectRoot);
|
|
19867
|
+
if (existing) {
|
|
19868
|
+
try {
|
|
19869
|
+
await existing.stop();
|
|
19870
|
+
} catch (error) {
|
|
19871
|
+
console.error("[codebase-index] Failed to stop replaced watcher:", error);
|
|
19872
|
+
throw error;
|
|
19873
|
+
}
|
|
19874
|
+
if (activeWatchers.get(projectRoot) === existing) {
|
|
19875
|
+
activeWatchers.delete(projectRoot);
|
|
19876
|
+
}
|
|
19877
|
+
}
|
|
19878
|
+
if (createNextWatcher) {
|
|
19879
|
+
activeWatchers.set(projectRoot, createNextWatcher());
|
|
19880
|
+
}
|
|
19881
|
+
});
|
|
19882
|
+
watcherReplacementChains.set(projectRoot, chain);
|
|
19883
|
+
try {
|
|
19884
|
+
await chain;
|
|
19885
|
+
} finally {
|
|
19886
|
+
if (watcherReplacementChains.get(projectRoot) === chain) {
|
|
19887
|
+
watcherReplacementChains.delete(projectRoot);
|
|
19888
|
+
}
|
|
19402
19889
|
}
|
|
19403
19890
|
}
|
|
19404
19891
|
function getCommandsDir() {
|
|
19405
19892
|
let currentDir = process.cwd();
|
|
19406
19893
|
if (typeof import.meta !== "undefined" && import.meta.url) {
|
|
19407
|
-
currentDir =
|
|
19894
|
+
currentDir = path29.dirname(fileURLToPath2(import.meta.url));
|
|
19408
19895
|
}
|
|
19409
|
-
const packageRoot =
|
|
19410
|
-
return
|
|
19896
|
+
const packageRoot = path29.basename(currentDir) === "adapters" ? path29.join(currentDir, "..", "..") : path29.join(currentDir, "..");
|
|
19897
|
+
return path29.join(packageRoot, "commands");
|
|
19411
19898
|
}
|
|
19412
19899
|
function appendRoutingHints(output, hints, preferredRole) {
|
|
19413
19900
|
const preferredBucket = preferredRole === "developer" ? output.developer : output.system;
|
|
@@ -19448,9 +19935,12 @@ var plugin = async ({ directory, worktree }) => {
|
|
|
19448
19935
|
startAutoIndex(projectRoot, "opencode", "startup");
|
|
19449
19936
|
}
|
|
19450
19937
|
if (config.indexing.watchFiles && isValidProject) {
|
|
19451
|
-
replaceActiveWatcher(
|
|
19938
|
+
await replaceActiveWatcher(
|
|
19939
|
+
projectRoot,
|
|
19940
|
+
() => createWatcherWithIndexer(getProjectIndexer, projectRoot, config, "opencode")
|
|
19941
|
+
);
|
|
19452
19942
|
} else {
|
|
19453
|
-
replaceActiveWatcher(projectRoot, null);
|
|
19943
|
+
await replaceActiveWatcher(projectRoot, null);
|
|
19454
19944
|
}
|
|
19455
19945
|
return {
|
|
19456
19946
|
tool: {
|