opencode-codebase-index 0.24.0 → 0.25.1
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/README.md +10 -0
- package/dist/cbi.cjs +15788 -0
- package/dist/cbi.cjs.map +1 -0
- package/dist/cbi.js +15791 -0
- package/dist/cbi.js.map +1 -0
- package/dist/cli.cjs +1847 -660
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +1881 -685
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +1673 -590
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1680 -588
- package/dist/index.js.map +1 -1
- package/dist/pi-extension.cjs +1585 -485
- package/dist/pi-extension.cjs.map +1 -1
- package/dist/pi-extension.js +1641 -532
- 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 -2
package/dist/cli.cjs
CHANGED
|
@@ -496,7 +496,7 @@ var require_ignore = __commonJS({
|
|
|
496
496
|
// path matching.
|
|
497
497
|
// - check `string` either `MODE_IGNORE` or `MODE_CHECK_IGNORE`
|
|
498
498
|
// @returns {TestResult} true if a file is ignored
|
|
499
|
-
test(
|
|
499
|
+
test(path34, checkUnignored, mode) {
|
|
500
500
|
let ignored = false;
|
|
501
501
|
let unignored = false;
|
|
502
502
|
let matchedRule;
|
|
@@ -505,7 +505,7 @@ var require_ignore = __commonJS({
|
|
|
505
505
|
if (unignored === negative && ignored !== unignored || negative && !ignored && !unignored && !checkUnignored) {
|
|
506
506
|
return;
|
|
507
507
|
}
|
|
508
|
-
const matched = rule[mode].test(
|
|
508
|
+
const matched = rule[mode].test(path34);
|
|
509
509
|
if (!matched) {
|
|
510
510
|
return;
|
|
511
511
|
}
|
|
@@ -526,17 +526,17 @@ var require_ignore = __commonJS({
|
|
|
526
526
|
var throwError = (message, Ctor) => {
|
|
527
527
|
throw new Ctor(message);
|
|
528
528
|
};
|
|
529
|
-
var checkPath = (
|
|
530
|
-
if (!isString(
|
|
529
|
+
var checkPath = (path34, originalPath, doThrow) => {
|
|
530
|
+
if (!isString(path34)) {
|
|
531
531
|
return doThrow(
|
|
532
532
|
`path must be a string, but got \`${originalPath}\``,
|
|
533
533
|
TypeError
|
|
534
534
|
);
|
|
535
535
|
}
|
|
536
|
-
if (!
|
|
536
|
+
if (!path34) {
|
|
537
537
|
return doThrow(`path must not be empty`, TypeError);
|
|
538
538
|
}
|
|
539
|
-
if (checkPath.isNotRelative(
|
|
539
|
+
if (checkPath.isNotRelative(path34)) {
|
|
540
540
|
const r = "`path.relative()`d";
|
|
541
541
|
return doThrow(
|
|
542
542
|
`path should be a ${r} string, but got "${originalPath}"`,
|
|
@@ -545,7 +545,7 @@ var require_ignore = __commonJS({
|
|
|
545
545
|
}
|
|
546
546
|
return true;
|
|
547
547
|
};
|
|
548
|
-
var isNotRelative = (
|
|
548
|
+
var isNotRelative = (path34) => REGEX_TEST_INVALID_PATH.test(path34);
|
|
549
549
|
checkPath.isNotRelative = isNotRelative;
|
|
550
550
|
checkPath.convert = (p) => p;
|
|
551
551
|
var Ignore2 = class {
|
|
@@ -575,19 +575,19 @@ var require_ignore = __commonJS({
|
|
|
575
575
|
}
|
|
576
576
|
// @returns {TestResult}
|
|
577
577
|
_test(originalPath, cache, checkUnignored, slices) {
|
|
578
|
-
const
|
|
578
|
+
const path34 = originalPath && checkPath.convert(originalPath);
|
|
579
579
|
checkPath(
|
|
580
|
-
|
|
580
|
+
path34,
|
|
581
581
|
originalPath,
|
|
582
582
|
this._strictPathCheck ? throwError : RETURN_FALSE
|
|
583
583
|
);
|
|
584
|
-
return this._t(
|
|
584
|
+
return this._t(path34, cache, checkUnignored, slices);
|
|
585
585
|
}
|
|
586
|
-
checkIgnore(
|
|
587
|
-
if (!REGEX_TEST_TRAILING_SLASH.test(
|
|
588
|
-
return this.test(
|
|
586
|
+
checkIgnore(path34) {
|
|
587
|
+
if (!REGEX_TEST_TRAILING_SLASH.test(path34)) {
|
|
588
|
+
return this.test(path34);
|
|
589
589
|
}
|
|
590
|
-
const slices =
|
|
590
|
+
const slices = path34.split(SLASH2).filter(Boolean);
|
|
591
591
|
slices.pop();
|
|
592
592
|
if (slices.length) {
|
|
593
593
|
const parent = this._t(
|
|
@@ -600,18 +600,18 @@ var require_ignore = __commonJS({
|
|
|
600
600
|
return parent;
|
|
601
601
|
}
|
|
602
602
|
}
|
|
603
|
-
return this._rules.test(
|
|
603
|
+
return this._rules.test(path34, false, MODE_CHECK_IGNORE);
|
|
604
604
|
}
|
|
605
|
-
_t(
|
|
606
|
-
if (
|
|
607
|
-
return cache[
|
|
605
|
+
_t(path34, cache, checkUnignored, slices) {
|
|
606
|
+
if (path34 in cache) {
|
|
607
|
+
return cache[path34];
|
|
608
608
|
}
|
|
609
609
|
if (!slices) {
|
|
610
|
-
slices =
|
|
610
|
+
slices = path34.split(SLASH2).filter(Boolean);
|
|
611
611
|
}
|
|
612
612
|
slices.pop();
|
|
613
613
|
if (!slices.length) {
|
|
614
|
-
return cache[
|
|
614
|
+
return cache[path34] = this._rules.test(path34, checkUnignored, MODE_IGNORE);
|
|
615
615
|
}
|
|
616
616
|
const parent = this._t(
|
|
617
617
|
slices.join(SLASH2) + SLASH2,
|
|
@@ -619,29 +619,29 @@ var require_ignore = __commonJS({
|
|
|
619
619
|
checkUnignored,
|
|
620
620
|
slices
|
|
621
621
|
);
|
|
622
|
-
return cache[
|
|
622
|
+
return cache[path34] = parent.ignored ? parent : this._rules.test(path34, checkUnignored, MODE_IGNORE);
|
|
623
623
|
}
|
|
624
|
-
ignores(
|
|
625
|
-
return this._test(
|
|
624
|
+
ignores(path34) {
|
|
625
|
+
return this._test(path34, this._ignoreCache, false).ignored;
|
|
626
626
|
}
|
|
627
627
|
createFilter() {
|
|
628
|
-
return (
|
|
628
|
+
return (path34) => !this.ignores(path34);
|
|
629
629
|
}
|
|
630
630
|
filter(paths) {
|
|
631
631
|
return makeArray(paths).filter(this.createFilter());
|
|
632
632
|
}
|
|
633
633
|
// @returns {TestResult}
|
|
634
|
-
test(
|
|
635
|
-
return this._test(
|
|
634
|
+
test(path34) {
|
|
635
|
+
return this._test(path34, this._testCache, true);
|
|
636
636
|
}
|
|
637
637
|
};
|
|
638
638
|
var factory = (options) => new Ignore2(options);
|
|
639
|
-
var isPathValid = (
|
|
639
|
+
var isPathValid = (path34) => checkPath(path34 && checkPath.convert(path34), path34, RETURN_FALSE);
|
|
640
640
|
var setupWindows = () => {
|
|
641
641
|
const makePosix = (str) => /^\\\\\?\\/.test(str) || /["<>|\u0000-\u001F]+/u.test(str) ? str : str.replace(/\\/g, "/");
|
|
642
642
|
checkPath.convert = makePosix;
|
|
643
643
|
const REGEX_TEST_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i;
|
|
644
|
-
checkPath.isNotRelative = (
|
|
644
|
+
checkPath.isNotRelative = (path34) => REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path34) || isNotRelative(path34);
|
|
645
645
|
};
|
|
646
646
|
if (
|
|
647
647
|
// Detect `process` so that it can run in browsers.
|
|
@@ -668,8 +668,8 @@ module.exports = __toCommonJS(cli_exports);
|
|
|
668
668
|
// src/adapters/mcp/cli.ts
|
|
669
669
|
var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
670
670
|
var import_fs20 = require("fs");
|
|
671
|
-
var
|
|
672
|
-
var
|
|
671
|
+
var os9 = __toESM(require("os"), 1);
|
|
672
|
+
var path33 = __toESM(require("path"), 1);
|
|
673
673
|
var import_url = require("url");
|
|
674
674
|
|
|
675
675
|
// src/config/constants.ts
|
|
@@ -1197,9 +1197,9 @@ var import_fs = require("fs");
|
|
|
1197
1197
|
var path = __toESM(require("path"), 1);
|
|
1198
1198
|
|
|
1199
1199
|
// src/eval/report-formatters.ts
|
|
1200
|
-
function assertFiniteNumber(value,
|
|
1200
|
+
function assertFiniteNumber(value, path34) {
|
|
1201
1201
|
if (typeof value !== "number" || Number.isNaN(value) || !Number.isFinite(value)) {
|
|
1202
|
-
throw new Error(`${
|
|
1202
|
+
throw new Error(`${path34} must be a finite number`);
|
|
1203
1203
|
}
|
|
1204
1204
|
return value;
|
|
1205
1205
|
}
|
|
@@ -1439,7 +1439,7 @@ function buildPerQueryArtifact(perQuery) {
|
|
|
1439
1439
|
// src/eval/runner.ts
|
|
1440
1440
|
var crypto2 = __toESM(require("crypto"), 1);
|
|
1441
1441
|
var import_fs17 = require("fs");
|
|
1442
|
-
var
|
|
1442
|
+
var path24 = __toESM(require("path"), 1);
|
|
1443
1443
|
var import_perf_hooks2 = require("perf_hooks");
|
|
1444
1444
|
|
|
1445
1445
|
// src/indexer/index.ts
|
|
@@ -1471,7 +1471,7 @@ function pTimeout(promise, options) {
|
|
|
1471
1471
|
} = options;
|
|
1472
1472
|
let timer;
|
|
1473
1473
|
let abortHandler;
|
|
1474
|
-
const wrappedPromise = new Promise((
|
|
1474
|
+
const wrappedPromise = new Promise((resolve21, reject) => {
|
|
1475
1475
|
if (typeof milliseconds !== "number" || Math.sign(milliseconds) !== 1) {
|
|
1476
1476
|
throw new TypeError(`Expected \`milliseconds\` to be a positive number, got \`${milliseconds}\``);
|
|
1477
1477
|
}
|
|
@@ -1485,7 +1485,7 @@ function pTimeout(promise, options) {
|
|
|
1485
1485
|
};
|
|
1486
1486
|
signal.addEventListener("abort", abortHandler, { once: true });
|
|
1487
1487
|
}
|
|
1488
|
-
promise.then(
|
|
1488
|
+
promise.then(resolve21, reject);
|
|
1489
1489
|
if (milliseconds === Number.POSITIVE_INFINITY) {
|
|
1490
1490
|
return;
|
|
1491
1491
|
}
|
|
@@ -1493,7 +1493,7 @@ function pTimeout(promise, options) {
|
|
|
1493
1493
|
timer = customTimers.setTimeout.call(void 0, () => {
|
|
1494
1494
|
if (fallback) {
|
|
1495
1495
|
try {
|
|
1496
|
-
|
|
1496
|
+
resolve21(fallback());
|
|
1497
1497
|
} catch (error) {
|
|
1498
1498
|
reject(error);
|
|
1499
1499
|
}
|
|
@@ -1503,7 +1503,7 @@ function pTimeout(promise, options) {
|
|
|
1503
1503
|
promise.cancel();
|
|
1504
1504
|
}
|
|
1505
1505
|
if (message === false) {
|
|
1506
|
-
|
|
1506
|
+
resolve21();
|
|
1507
1507
|
} else if (message instanceof Error) {
|
|
1508
1508
|
reject(message);
|
|
1509
1509
|
} else {
|
|
@@ -1905,7 +1905,7 @@ var PQueue = class extends import_index.default {
|
|
|
1905
1905
|
// Assign unique ID if not provided
|
|
1906
1906
|
id: options.id ?? (this.#idAssigner++).toString()
|
|
1907
1907
|
};
|
|
1908
|
-
return new Promise((
|
|
1908
|
+
return new Promise((resolve21, reject) => {
|
|
1909
1909
|
const taskSymbol = /* @__PURE__ */ Symbol(`task-${options.id}`);
|
|
1910
1910
|
let cleanupQueueAbortHandler = () => void 0;
|
|
1911
1911
|
const run = async () => {
|
|
@@ -1945,7 +1945,7 @@ var PQueue = class extends import_index.default {
|
|
|
1945
1945
|
})]);
|
|
1946
1946
|
}
|
|
1947
1947
|
const result = await operation;
|
|
1948
|
-
|
|
1948
|
+
resolve21(result);
|
|
1949
1949
|
this.emit("completed", result);
|
|
1950
1950
|
} catch (error) {
|
|
1951
1951
|
reject(error);
|
|
@@ -2133,13 +2133,13 @@ var PQueue = class extends import_index.default {
|
|
|
2133
2133
|
});
|
|
2134
2134
|
}
|
|
2135
2135
|
async #onEvent(event, filter) {
|
|
2136
|
-
return new Promise((
|
|
2136
|
+
return new Promise((resolve21) => {
|
|
2137
2137
|
const listener = () => {
|
|
2138
2138
|
if (filter && !filter()) {
|
|
2139
2139
|
return;
|
|
2140
2140
|
}
|
|
2141
2141
|
this.off(event, listener);
|
|
2142
|
-
|
|
2142
|
+
resolve21();
|
|
2143
2143
|
};
|
|
2144
2144
|
this.on(event, listener);
|
|
2145
2145
|
});
|
|
@@ -2425,7 +2425,7 @@ async function onAttemptFailure({ error, attemptNumber, retriesConsumed, startTi
|
|
|
2425
2425
|
const finalDelay = Math.min(delayTime, remainingTime);
|
|
2426
2426
|
options.signal?.throwIfAborted();
|
|
2427
2427
|
if (finalDelay > 0) {
|
|
2428
|
-
await new Promise((
|
|
2428
|
+
await new Promise((resolve21, reject) => {
|
|
2429
2429
|
const onAbort = () => {
|
|
2430
2430
|
clearTimeout(timeoutToken);
|
|
2431
2431
|
options.signal?.removeEventListener("abort", onAbort);
|
|
@@ -2433,7 +2433,7 @@ async function onAttemptFailure({ error, attemptNumber, retriesConsumed, startTi
|
|
|
2433
2433
|
};
|
|
2434
2434
|
const timeoutToken = setTimeout(() => {
|
|
2435
2435
|
options.signal?.removeEventListener("abort", onAbort);
|
|
2436
|
-
|
|
2436
|
+
resolve21();
|
|
2437
2437
|
}, finalDelay);
|
|
2438
2438
|
if (options.unref) {
|
|
2439
2439
|
timeoutToken.unref?.();
|
|
@@ -2795,17 +2795,17 @@ function validateExternalUrl(urlString) {
|
|
|
2795
2795
|
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
2796
2796
|
return { valid: false, reason: `Blocked protocol: ${parsed.protocol}` };
|
|
2797
2797
|
}
|
|
2798
|
-
const
|
|
2799
|
-
if (BLOCKED_HOSTNAMES.has(
|
|
2800
|
-
return { valid: false, reason: `Blocked: cloud metadata service (${
|
|
2798
|
+
const hostname3 = parsed.hostname.toLowerCase();
|
|
2799
|
+
if (BLOCKED_HOSTNAMES.has(hostname3)) {
|
|
2800
|
+
return { valid: false, reason: `Blocked: cloud metadata service (${hostname3})` };
|
|
2801
2801
|
}
|
|
2802
2802
|
for (const pattern of BLOCKED_METADATA_IPS) {
|
|
2803
|
-
if (pattern.test(
|
|
2804
|
-
return { valid: false, reason: `Blocked: cloud metadata IP (${
|
|
2803
|
+
if (pattern.test(hostname3)) {
|
|
2804
|
+
return { valid: false, reason: `Blocked: cloud metadata IP (${hostname3})` };
|
|
2805
2805
|
}
|
|
2806
2806
|
}
|
|
2807
|
-
if (/^169\.254\./.test(
|
|
2808
|
-
return { valid: false, reason: `Blocked: link-local address (${
|
|
2807
|
+
if (/^169\.254\./.test(hostname3)) {
|
|
2808
|
+
return { valid: false, reason: `Blocked: link-local address (${hostname3})` };
|
|
2809
2809
|
}
|
|
2810
2810
|
return { valid: true };
|
|
2811
2811
|
}
|
|
@@ -3391,26 +3391,46 @@ function createIgnoreFilter(projectRoot) {
|
|
|
3391
3391
|
}
|
|
3392
3392
|
return ig;
|
|
3393
3393
|
}
|
|
3394
|
-
function
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3394
|
+
function toPosixRelativePath(relativePath) {
|
|
3395
|
+
return relativePath.split(path4.sep).join("/");
|
|
3396
|
+
}
|
|
3397
|
+
function matchesAnyGlob(filePath, patterns) {
|
|
3398
|
+
const normalized = toPosixRelativePath(filePath);
|
|
3399
|
+
return patterns.some((pattern) => matchGlob(normalized, pattern));
|
|
3400
|
+
}
|
|
3401
|
+
function isExcludedByPatterns(relativePath, excludePatterns) {
|
|
3402
|
+
return matchesAnyGlob(relativePath, excludePatterns);
|
|
3403
|
+
}
|
|
3404
|
+
function isExcludedDirectory(relativePath, excludePatterns) {
|
|
3405
|
+
const normalized = toPosixRelativePath(relativePath);
|
|
3406
|
+
if (matchesAnyGlob(normalized, excludePatterns)) {
|
|
3407
|
+
return true;
|
|
3401
3408
|
}
|
|
3402
3409
|
for (const pattern of excludePatterns) {
|
|
3403
|
-
|
|
3404
|
-
|
|
3410
|
+
const posixPattern = toPosixRelativePath(pattern).replace(/\/+$/, "");
|
|
3411
|
+
if (!posixPattern.endsWith("/**")) {
|
|
3412
|
+
continue;
|
|
3405
3413
|
}
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
if (matchGlob(relativePath, pattern)) {
|
|
3414
|
+
const directoryPattern = posixPattern.slice(0, -3);
|
|
3415
|
+
if (directoryPattern && matchesAnyGlob(normalized, [directoryPattern])) {
|
|
3409
3416
|
return true;
|
|
3410
3417
|
}
|
|
3411
3418
|
}
|
|
3412
3419
|
return false;
|
|
3413
3420
|
}
|
|
3421
|
+
function shouldIncludeFile(filePath, projectRoot, includePatterns, excludePatterns, ignoreFilter) {
|
|
3422
|
+
const relativePath = toPosixRelativePath(path4.relative(projectRoot, filePath));
|
|
3423
|
+
if (hasFilteredPathSegment(relativePath, "/")) {
|
|
3424
|
+
return false;
|
|
3425
|
+
}
|
|
3426
|
+
if (ignoreFilter.ignores(relativePath)) {
|
|
3427
|
+
return false;
|
|
3428
|
+
}
|
|
3429
|
+
if (isExcludedByPatterns(relativePath, excludePatterns)) {
|
|
3430
|
+
return false;
|
|
3431
|
+
}
|
|
3432
|
+
return matchesAnyGlob(relativePath, includePatterns);
|
|
3433
|
+
}
|
|
3414
3434
|
function matchGlob(filePath, pattern) {
|
|
3415
3435
|
if (pattern.startsWith("**/")) {
|
|
3416
3436
|
const withoutPrefix = pattern.slice(3);
|
|
@@ -3432,7 +3452,7 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
|
|
|
3432
3452
|
const subdirs = [];
|
|
3433
3453
|
for (const entry of entries) {
|
|
3434
3454
|
const fullPath = path4.join(dir, entry.name);
|
|
3435
|
-
const relativePath = path4.relative(projectRoot, fullPath);
|
|
3455
|
+
const relativePath = toPosixRelativePath(path4.relative(projectRoot, fullPath));
|
|
3436
3456
|
if (isHiddenPathSegment(entry.name)) {
|
|
3437
3457
|
if (entry.isDirectory()) {
|
|
3438
3458
|
skipped.push({ path: relativePath, reason: "excluded" });
|
|
@@ -3450,6 +3470,10 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
|
|
|
3450
3470
|
continue;
|
|
3451
3471
|
}
|
|
3452
3472
|
if (entry.isDirectory()) {
|
|
3473
|
+
if (isExcludedDirectory(relativePath, excludePatterns)) {
|
|
3474
|
+
skipped.push({ path: relativePath, reason: "excluded" });
|
|
3475
|
+
continue;
|
|
3476
|
+
}
|
|
3453
3477
|
subdirs.push({ fullPath, relativePath });
|
|
3454
3478
|
} else if (entry.isFile()) {
|
|
3455
3479
|
const stat5 = await import_fs3.promises.stat(fullPath);
|
|
@@ -3457,20 +3481,11 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
|
|
|
3457
3481
|
skipped.push({ path: relativePath, reason: "too_large" });
|
|
3458
3482
|
continue;
|
|
3459
3483
|
}
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
continue;
|
|
3464
|
-
}
|
|
3465
|
-
}
|
|
3466
|
-
let matched = false;
|
|
3467
|
-
for (const pattern of includePatterns) {
|
|
3468
|
-
if (matchGlob(relativePath, pattern)) {
|
|
3469
|
-
matched = true;
|
|
3470
|
-
break;
|
|
3471
|
-
}
|
|
3484
|
+
if (isExcludedByPatterns(relativePath, excludePatterns)) {
|
|
3485
|
+
skipped.push({ path: relativePath, reason: "excluded" });
|
|
3486
|
+
continue;
|
|
3472
3487
|
}
|
|
3473
|
-
if (
|
|
3488
|
+
if (matchesAnyGlob(relativePath, includePatterns)) {
|
|
3474
3489
|
filesInDir.push({ path: fullPath, size: stat5.size });
|
|
3475
3490
|
}
|
|
3476
3491
|
}
|
|
@@ -3481,7 +3496,7 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
|
|
|
3481
3496
|
yield f;
|
|
3482
3497
|
}
|
|
3483
3498
|
for (let i = options.maxFilesPerDirectory; i < filesInDir.length; i++) {
|
|
3484
|
-
skipped.push({ path: path4.relative(projectRoot, filesInDir[i].path), reason: "excluded" });
|
|
3499
|
+
skipped.push({ path: toPosixRelativePath(path4.relative(projectRoot, filesInDir[i].path)), reason: "excluded" });
|
|
3485
3500
|
}
|
|
3486
3501
|
const canRecurse = options.maxDepth === -1 || currentDepth < options.maxDepth;
|
|
3487
3502
|
if (canRecurse) {
|
|
@@ -3610,6 +3625,26 @@ function formatCostEstimate(estimate) {
|
|
|
3610
3625
|
\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518
|
|
3611
3626
|
`;
|
|
3612
3627
|
}
|
|
3628
|
+
function formatDryRunEstimate(estimate) {
|
|
3629
|
+
return `Dry run: parsed the file set to measure the embedding workload. No embedding requests were made and the index was not changed.
|
|
3630
|
+
|
|
3631
|
+
Files to embed: ${estimate.filesCount.toLocaleString()}
|
|
3632
|
+
Chunks to embed: ${estimate.chunksCount.toLocaleString()}
|
|
3633
|
+
Tokens to embed: ${estimate.tokensToEmbed.toLocaleString()}
|
|
3634
|
+
|
|
3635
|
+
The "Tokens to embed" value uses the local estimateTokens(text) = ceil(len/4). It
|
|
3636
|
+
matches the live "Tokens used" counter only for providers that report usage on the
|
|
3637
|
+
same basis (ollama); for providers that report a server tokenizer count (OpenAI,
|
|
3638
|
+
Gemini, custom) it is only an estimate.
|
|
3639
|
+
|
|
3640
|
+
For a matching provider and a project-scoped force index, the force pass clears its
|
|
3641
|
+
own cached embeddings, so the live counter climbs to this number. A force index on a
|
|
3642
|
+
shared global index can reuse cached embeddings from other projects, and an
|
|
3643
|
+
incremental index counts cached chunks that are not re-embedded; in both cases this
|
|
3644
|
+
number is an upper bound on the live counter, so a progress percent against this
|
|
3645
|
+
total tops out below 100%.
|
|
3646
|
+
`;
|
|
3647
|
+
}
|
|
3613
3648
|
function formatBytes(bytes) {
|
|
3614
3649
|
if (bytes === 0) return "0 B";
|
|
3615
3650
|
const k = 1024;
|
|
@@ -6835,6 +6870,9 @@ var CALL_GRAPH_SYMBOL_CHUNK_TYPES = /* @__PURE__ */ new Set([
|
|
|
6835
6870
|
"enum_declaration",
|
|
6836
6871
|
"function_definition",
|
|
6837
6872
|
"class_definition",
|
|
6873
|
+
// Ruby module/class symbols that are declaration-bearing and navigable.
|
|
6874
|
+
"class",
|
|
6875
|
+
"module",
|
|
6838
6876
|
"class_specifier",
|
|
6839
6877
|
"struct_specifier",
|
|
6840
6878
|
"namespace_definition",
|
|
@@ -7079,8 +7117,8 @@ function pathSegmentsForAffinityMatch(filePath) {
|
|
|
7079
7117
|
if (segments.length === 0) {
|
|
7080
7118
|
return [];
|
|
7081
7119
|
}
|
|
7082
|
-
const
|
|
7083
|
-
const basenameWithoutExt =
|
|
7120
|
+
const basename9 = segments[segments.length - 1] ?? "";
|
|
7121
|
+
const basenameWithoutExt = basename9.replace(/\.[^/.]+$/u, "");
|
|
7084
7122
|
const normalizedSegments = segments.map((segment) => segment.toLowerCase());
|
|
7085
7123
|
return Array.from(/* @__PURE__ */ new Set([
|
|
7086
7124
|
...normalizedSegments,
|
|
@@ -7493,7 +7531,7 @@ function removeDeadReclaimMarker(lockPath, expectedOwner) {
|
|
|
7493
7531
|
return true;
|
|
7494
7532
|
}
|
|
7495
7533
|
function reclaimDeadOwner(indexPath, lockPath, expectedOwner) {
|
|
7496
|
-
const
|
|
7534
|
+
const reclaimPath2 = path13.join(lockPath, RECLAIM_DIRECTORY_NAME);
|
|
7497
7535
|
const reclaimOwner = {
|
|
7498
7536
|
pid: process.pid,
|
|
7499
7537
|
hostname: os5.hostname(),
|
|
@@ -7502,19 +7540,19 @@ function reclaimDeadOwner(indexPath, lockPath, expectedOwner) {
|
|
|
7502
7540
|
expectedOwnerToken: expectedOwner.token
|
|
7503
7541
|
};
|
|
7504
7542
|
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
7505
|
-
if (publishJsonDirectory(
|
|
7543
|
+
if (publishJsonDirectory(reclaimPath2, reclaimOwner)) break;
|
|
7506
7544
|
if (attempt === 0 && removeDeadReclaimMarker(lockPath, expectedOwner)) continue;
|
|
7507
7545
|
return false;
|
|
7508
7546
|
}
|
|
7509
7547
|
try {
|
|
7510
|
-
const currentReclaimer = readReclaimOwner(
|
|
7548
|
+
const currentReclaimer = readReclaimOwner(reclaimPath2);
|
|
7511
7549
|
const currentOwner = readDirectoryOwner(lockPath);
|
|
7512
7550
|
if (!currentReclaimer || !sameReclaimOwner(currentReclaimer, reclaimOwner) || !currentOwner || !sameOwner(currentOwner, expectedOwner) || getOwnerLiveness(currentOwner) !== "dead") {
|
|
7513
7551
|
return false;
|
|
7514
7552
|
}
|
|
7515
7553
|
publishRecoveryMarker(indexPath, expectedOwner);
|
|
7516
7554
|
const ownerBeforeQuarantine = readDirectoryOwner(lockPath);
|
|
7517
|
-
const reclaimerBeforeQuarantine = readReclaimOwner(
|
|
7555
|
+
const reclaimerBeforeQuarantine = readReclaimOwner(reclaimPath2);
|
|
7518
7556
|
if (!ownerBeforeQuarantine || !sameOwner(ownerBeforeQuarantine, expectedOwner) || getOwnerLiveness(ownerBeforeQuarantine) !== "dead" || !reclaimerBeforeQuarantine || !sameReclaimOwner(reclaimerBeforeQuarantine, reclaimOwner)) {
|
|
7519
7557
|
return false;
|
|
7520
7558
|
}
|
|
@@ -8730,6 +8768,17 @@ var Indexer = class _Indexer {
|
|
|
8730
8768
|
}
|
|
8731
8769
|
return path15.relative(this.projectRoot, canonicalFilePath).split(path15.sep).join("/");
|
|
8732
8770
|
}
|
|
8771
|
+
isStoredPathExcluded(storedPath) {
|
|
8772
|
+
let matchPath = storedPath.split(path15.sep).join("/");
|
|
8773
|
+
if (path15.isAbsolute(storedPath)) {
|
|
8774
|
+
const relativePath = path15.relative(this.projectRoot, storedPath).split(path15.sep).join("/");
|
|
8775
|
+
if (relativePath.startsWith("..") || path15.isAbsolute(relativePath)) {
|
|
8776
|
+
return false;
|
|
8777
|
+
}
|
|
8778
|
+
matchPath = relativePath;
|
|
8779
|
+
}
|
|
8780
|
+
return isExcludedByPatterns(matchPath, this.config.exclude);
|
|
8781
|
+
}
|
|
8733
8782
|
resolveStoredFilePath(filePath, rootPath = this.projectRoot) {
|
|
8734
8783
|
if (path15.isAbsolute(filePath)) {
|
|
8735
8784
|
return filePath;
|
|
@@ -9754,7 +9803,7 @@ var Indexer = class _Indexer {
|
|
|
9754
9803
|
await options.queue.onSizeLessThan(Math.max(1, options.providerRateLimits.concurrency));
|
|
9755
9804
|
const task = options.queue.add(async () => {
|
|
9756
9805
|
if (options.rateLimitState.backoffMs > 0) {
|
|
9757
|
-
await new Promise((
|
|
9806
|
+
await new Promise((resolve21) => setTimeout(resolve21, options.rateLimitState.backoffMs));
|
|
9758
9807
|
}
|
|
9759
9808
|
try {
|
|
9760
9809
|
const embeddingResult = await pRetry(
|
|
@@ -10871,6 +10920,70 @@ var Indexer = class _Indexer {
|
|
|
10871
10920
|
);
|
|
10872
10921
|
return createCostEstimate(files, configuredProviderInfo);
|
|
10873
10922
|
}
|
|
10923
|
+
// Dry-run counterpart to index()/forceIndex(): parse the real file set and sum
|
|
10924
|
+
// estimateTokens over the embedding text of every indexable chunk, without
|
|
10925
|
+
// calling the embedding provider or writing to the index. Read-only and
|
|
10926
|
+
// lock-free (mirrors estimateCost). The token sum is the exact value "Tokens
|
|
10927
|
+
// used" climbs to for a force index (cache bypassed); for an incremental it is
|
|
10928
|
+
// an upper bound because cached chunks are counted here but not re-embedded.
|
|
10929
|
+
// Used by index_codebase(dryRun:true) to give a stable, monotonic progress
|
|
10930
|
+
// denominator that matches the live "Tokens used" basis.
|
|
10931
|
+
async dryRunCost() {
|
|
10932
|
+
const { configuredProviderInfo } = await this.ensureInitialized();
|
|
10933
|
+
const maxChunkTokens = getSafeEmbeddingChunkTokenLimit(configuredProviderInfo);
|
|
10934
|
+
const includePatterns = [...this.config.include, ...this.config.additionalInclude];
|
|
10935
|
+
const { files } = await collectFiles(
|
|
10936
|
+
this.materializedProjectRoot,
|
|
10937
|
+
includePatterns,
|
|
10938
|
+
this.config.exclude,
|
|
10939
|
+
this.config.indexing.maxFileSize,
|
|
10940
|
+
this.getMaterializedKnowledgeBases(),
|
|
10941
|
+
{ maxDepth: this.config.indexing.maxDepth, maxFilesPerDirectory: this.config.indexing.maxFilesPerDirectory }
|
|
10942
|
+
);
|
|
10943
|
+
let filesCount = 0;
|
|
10944
|
+
let chunksCount = 0;
|
|
10945
|
+
let tokensToEmbed = 0;
|
|
10946
|
+
for (const batch of iterateOrderedFileBatches(files, (f) => f.size, this.fileBatchLimits)) {
|
|
10947
|
+
const loadedFiles = await Promise.all(batch.map(async (f) => {
|
|
10948
|
+
try {
|
|
10949
|
+
return {
|
|
10950
|
+
path: this.toStoredFilePath(f.path),
|
|
10951
|
+
content: await import_fs10.promises.readFile(f.path, "utf-8")
|
|
10952
|
+
};
|
|
10953
|
+
} catch {
|
|
10954
|
+
return null;
|
|
10955
|
+
}
|
|
10956
|
+
}));
|
|
10957
|
+
const readable = loadedFiles.filter(
|
|
10958
|
+
(f) => f !== null
|
|
10959
|
+
);
|
|
10960
|
+
filesCount += readable.length;
|
|
10961
|
+
const contentByPath = new Map(readable.map((f) => [f.path, f.content]));
|
|
10962
|
+
const parsedFiles = parseFiles(readable, this.config.indexing.linesPerChunk);
|
|
10963
|
+
for (const parsed of parsedFiles) {
|
|
10964
|
+
let chunksToProcess = parsed.chunks;
|
|
10965
|
+
if (this.config.indexing.fallbackToTextOnMaxChunks && chunksToProcess.length > this.config.indexing.maxChunksPerFile) {
|
|
10966
|
+
const content = contentByPath.get(parsed.path);
|
|
10967
|
+
if (content !== void 0) {
|
|
10968
|
+
chunksToProcess = parseFileAsText(parsed.path, content, this.config.indexing.linesPerChunk);
|
|
10969
|
+
}
|
|
10970
|
+
}
|
|
10971
|
+
chunksToProcess = selectIndexableChunks(
|
|
10972
|
+
chunksToProcess,
|
|
10973
|
+
this.config.indexing.maxChunksPerFile,
|
|
10974
|
+
this.config.indexing.semanticOnly
|
|
10975
|
+
);
|
|
10976
|
+
for (const chunk of chunksToProcess) {
|
|
10977
|
+
const texts = createEmbeddingTexts(chunk, parsed.path, maxChunkTokens);
|
|
10978
|
+
chunksCount += 1;
|
|
10979
|
+
for (const text of texts) {
|
|
10980
|
+
tokensToEmbed += estimateTokens2(text);
|
|
10981
|
+
}
|
|
10982
|
+
}
|
|
10983
|
+
}
|
|
10984
|
+
}
|
|
10985
|
+
return { filesCount, chunksCount, tokensToEmbed };
|
|
10986
|
+
}
|
|
10874
10987
|
async index(onProgress) {
|
|
10875
10988
|
return this.withIndexMutationLease("index", async (recoveredOwners) => {
|
|
10876
10989
|
return this.indexUnlocked(onProgress, recoveredOwners);
|
|
@@ -11067,7 +11180,7 @@ var Indexer = class _Indexer {
|
|
|
11067
11180
|
}
|
|
11068
11181
|
}
|
|
11069
11182
|
}
|
|
11070
|
-
const shouldRetryFailedPath = (filePath) => filePath !== null && currentFileHashes.has(filePath) && unchangedFilePaths.has(filePath);
|
|
11183
|
+
const shouldRetryFailedPath = (filePath) => filePath !== null && !this.isStoredPathExcluded(filePath) && currentFileHashes.has(filePath) && unchangedFilePaths.has(filePath);
|
|
11071
11184
|
const failedProcessing = this.prepareFailedBatchProcessing(scopedRoots, shouldRetryFailedPath);
|
|
11072
11185
|
const maxChunkTokens = getSafeEmbeddingChunkTokenLimit(configuredProviderInfo);
|
|
11073
11186
|
const providerRateLimits = this.getProviderRateLimits(configuredProviderInfo.provider);
|
|
@@ -12395,7 +12508,8 @@ var Indexer = class _Indexer {
|
|
|
12395
12508
|
const maxChunkTokens = getSafeEmbeddingChunkTokenLimit(configuredProviderInfo);
|
|
12396
12509
|
const providerRateLimits = this.getProviderRateLimits(configuredProviderInfo.provider);
|
|
12397
12510
|
const roots = this.config.scope === "global" ? this.getScopedRoots() : null;
|
|
12398
|
-
const
|
|
12511
|
+
const shouldProcessFailedPath = (filePath) => filePath === null || !this.isStoredPathExcluded(filePath);
|
|
12512
|
+
const failedProcessing = this.prepareFailedBatchProcessing(roots, shouldProcessFailedPath);
|
|
12399
12513
|
if (failedProcessing.latestById.size === 0) {
|
|
12400
12514
|
this.finalizeFailedBatchWriteState(failedProcessing.state);
|
|
12401
12515
|
return { succeeded: 0, failed: 0, remaining: 0 };
|
|
@@ -12408,7 +12522,7 @@ var Indexer = class _Indexer {
|
|
|
12408
12522
|
const retryableChunks = this.iterateLatestFailedChunks(
|
|
12409
12523
|
failedProcessing.latestById,
|
|
12410
12524
|
roots,
|
|
12411
|
-
|
|
12525
|
+
shouldProcessFailedPath,
|
|
12412
12526
|
maxChunkTokens
|
|
12413
12527
|
);
|
|
12414
12528
|
for (const retryBatch of iterateOrderedFileBatches(
|
|
@@ -12678,9 +12792,9 @@ var Indexer = class _Indexer {
|
|
|
12678
12792
|
this.requireReadableComponents(readIssues, "database");
|
|
12679
12793
|
let shortest = [];
|
|
12680
12794
|
for (const branchKey of this.getBranchCatalogKeys()) {
|
|
12681
|
-
const
|
|
12682
|
-
if (
|
|
12683
|
-
shortest =
|
|
12795
|
+
const path34 = database.findShortestPath(fromName, toName, branchKey, maxDepth);
|
|
12796
|
+
if (path34.length > 0 && (shortest.length === 0 || path34.length < shortest.length)) {
|
|
12797
|
+
shortest = path34;
|
|
12684
12798
|
}
|
|
12685
12799
|
}
|
|
12686
12800
|
return shortest.map((hop) => this.resolveFilePathRecord(hop));
|
|
@@ -12728,13 +12842,13 @@ var Indexer = class _Indexer {
|
|
|
12728
12842
|
}
|
|
12729
12843
|
}
|
|
12730
12844
|
if (!found) continue;
|
|
12731
|
-
const
|
|
12845
|
+
const path34 = [];
|
|
12732
12846
|
let currentSymbolId = toSymbolId;
|
|
12733
12847
|
while (true) {
|
|
12734
12848
|
const symbol = symbolsById.get(currentSymbolId);
|
|
12735
12849
|
if (!symbol) break;
|
|
12736
12850
|
const parent = parentBySymbolId.get(currentSymbolId);
|
|
12737
|
-
|
|
12851
|
+
path34.push({
|
|
12738
12852
|
symbolId: symbol.id,
|
|
12739
12853
|
symbolName: symbol.name,
|
|
12740
12854
|
filePath: symbol.filePath,
|
|
@@ -12744,9 +12858,9 @@ var Indexer = class _Indexer {
|
|
|
12744
12858
|
if (!parent) break;
|
|
12745
12859
|
currentSymbolId = parent.parentId;
|
|
12746
12860
|
}
|
|
12747
|
-
|
|
12748
|
-
if (
|
|
12749
|
-
shortest =
|
|
12861
|
+
path34.reverse();
|
|
12862
|
+
if (path34.length > 0 && (shortest.length === 0 || path34.length < shortest.length)) {
|
|
12863
|
+
shortest = path34;
|
|
12750
12864
|
}
|
|
12751
12865
|
}
|
|
12752
12866
|
return shortest.map((hop) => this.resolveFilePathRecord(hop));
|
|
@@ -13130,7 +13244,7 @@ var CODE_COMMUNITIES_MAX_COUPLING_LIMIT = 100;
|
|
|
13130
13244
|
|
|
13131
13245
|
// src/tools/operations.ts
|
|
13132
13246
|
var import_fs14 = require("fs");
|
|
13133
|
-
var
|
|
13247
|
+
var path22 = __toESM(require("path"), 1);
|
|
13134
13248
|
|
|
13135
13249
|
// src/tools/knowledge-base-paths.ts
|
|
13136
13250
|
var path16 = __toESM(require("path"), 1);
|
|
@@ -13425,8 +13539,8 @@ function formatExactSearchHandoff(results) {
|
|
|
13425
13539
|
}
|
|
13426
13540
|
function formatContextEvidence(result, index) {
|
|
13427
13541
|
const symbol = result.name ? ` ${JSON.stringify(compactEvidenceValue(result.name, 80))}` : "";
|
|
13428
|
-
const
|
|
13429
|
-
return `[${index}] ${result.chunkType}${symbol} in ${
|
|
13542
|
+
const path34 = compactEvidenceValue(result.filePath, 120);
|
|
13543
|
+
return `[${index}] ${result.chunkType}${symbol} in ${path34}:${result.startLine}-${result.endLine} (score ${result.score.toFixed(2)})`;
|
|
13430
13544
|
}
|
|
13431
13545
|
function formatContextPack(heading, selected, candidateCount, duplicateCount, limitOmittedCount, budgetOmittedCount, includeExactSearchHandoff) {
|
|
13432
13546
|
const lines = selected.map((result, index) => formatContextEvidence(result, index + 1));
|
|
@@ -14069,124 +14183,43 @@ function formatEffectivenessMetrics(snapshot) {
|
|
|
14069
14183
|
|
|
14070
14184
|
// src/utils/auto-index.ts
|
|
14071
14185
|
var import_fs11 = require("fs");
|
|
14186
|
+
var os7 = __toESM(require("os"), 1);
|
|
14187
|
+
var path18 = __toESM(require("path"), 1);
|
|
14188
|
+
|
|
14189
|
+
// src/utils/background-worker.ts
|
|
14190
|
+
var import_node_crypto2 = require("crypto");
|
|
14191
|
+
var import_node_fs = require("fs");
|
|
14072
14192
|
var os6 = __toESM(require("os"), 1);
|
|
14073
14193
|
var path17 = __toESM(require("path"), 1);
|
|
14074
|
-
|
|
14075
|
-
|
|
14076
|
-
var
|
|
14077
|
-
var
|
|
14078
|
-
var
|
|
14079
|
-
|
|
14080
|
-
|
|
14081
|
-
}
|
|
14082
|
-
|
|
14083
|
-
|
|
14084
|
-
|
|
14085
|
-
|
|
14086
|
-
|
|
14087
|
-
|
|
14088
|
-
|
|
14089
|
-
|
|
14090
|
-
|
|
14091
|
-
return;
|
|
14092
|
-
}
|
|
14093
|
-
resolve20(stdout);
|
|
14094
|
-
}
|
|
14095
|
-
);
|
|
14096
|
-
});
|
|
14097
|
-
}
|
|
14098
|
-
function parseMacOsPowerSource(output) {
|
|
14099
|
-
const match = output.match(/Now drawing from '([^']+)'/i);
|
|
14100
|
-
if (!match) {
|
|
14101
|
-
return "unknown";
|
|
14102
|
-
}
|
|
14103
|
-
const source = match[1].toLowerCase();
|
|
14104
|
-
if (source === "battery power") {
|
|
14105
|
-
return "battery";
|
|
14106
|
-
}
|
|
14107
|
-
if (source === "ac power") {
|
|
14108
|
-
return "ac";
|
|
14109
|
-
}
|
|
14110
|
-
return "unknown";
|
|
14111
|
-
}
|
|
14112
|
-
async function readMacOsPowerSource(commandRunner = runCommand) {
|
|
14113
|
-
const output = await commandRunner(
|
|
14114
|
-
"/usr/bin/pmset",
|
|
14115
|
-
["-g", "batt"],
|
|
14116
|
-
{ timeoutMs: PMSET_TIMEOUT_MS }
|
|
14117
|
-
);
|
|
14118
|
-
return parseMacOsPowerSource(output);
|
|
14119
|
-
}
|
|
14120
|
-
var MacOsBackgroundIndexingPolicy = class {
|
|
14121
|
-
constructor(readPowerSource, recheckDelayMs) {
|
|
14122
|
-
this.readPowerSource = readPowerSource;
|
|
14123
|
-
this.recheckDelayMs = recheckDelayMs;
|
|
14124
|
-
}
|
|
14125
|
-
readPowerSource;
|
|
14126
|
-
recheckDelayMs;
|
|
14127
|
-
lastPaused = null;
|
|
14128
|
-
reportedFailure = false;
|
|
14129
|
-
isPaused() {
|
|
14130
|
-
return this.checkPowerSource();
|
|
14131
|
-
}
|
|
14132
|
-
async checkPowerSource() {
|
|
14133
|
-
try {
|
|
14134
|
-
const source = await this.readPowerSource();
|
|
14135
|
-
if (source === "unknown") {
|
|
14136
|
-
throw new Error("pmset returned an unrecognized power source");
|
|
14137
|
-
}
|
|
14138
|
-
this.reportedFailure = false;
|
|
14139
|
-
const paused = source === "battery";
|
|
14140
|
-
if (paused && this.lastPaused !== true) {
|
|
14141
|
-
console.warn("[codebase-index] Background indexing paused while macOS is using battery power.");
|
|
14142
|
-
} else if (!paused && this.lastPaused === true) {
|
|
14143
|
-
console.warn("[codebase-index] AC power detected; resuming pending background indexing.");
|
|
14144
|
-
}
|
|
14145
|
-
this.lastPaused = paused;
|
|
14146
|
-
return paused;
|
|
14147
|
-
} catch (error) {
|
|
14148
|
-
if (!this.reportedFailure) {
|
|
14149
|
-
console.error(
|
|
14150
|
-
`[codebase-index] Failed to determine the macOS power source; background indexing will continue: ${getErrorMessage4(error)}`
|
|
14151
|
-
);
|
|
14152
|
-
this.reportedFailure = true;
|
|
14153
|
-
}
|
|
14154
|
-
this.lastPaused = false;
|
|
14155
|
-
return false;
|
|
14156
|
-
}
|
|
14157
|
-
}
|
|
14158
|
-
};
|
|
14159
|
-
function createBackgroundIndexingPolicy(pauseOnBattery, options = {}) {
|
|
14160
|
-
const platform2 = options.platform ?? process.platform;
|
|
14161
|
-
if (!pauseOnBattery || platform2 !== "darwin") {
|
|
14162
|
-
return null;
|
|
14163
|
-
}
|
|
14164
|
-
return new MacOsBackgroundIndexingPolicy(
|
|
14165
|
-
options.readPowerSource ?? readMacOsPowerSource,
|
|
14166
|
-
options.recheckDelayMs ?? POWER_SOURCE_RECHECK_DELAY_MS
|
|
14167
|
-
);
|
|
14168
|
-
}
|
|
14169
|
-
|
|
14170
|
-
// src/utils/auto-index.ts
|
|
14171
|
-
var MAX_RETRY_DELAY_MS = 1e4;
|
|
14172
|
-
var SHUTDOWN_WAIT_MS = 2e3;
|
|
14173
|
-
var coordinators = /* @__PURE__ */ new Map();
|
|
14174
|
-
var coordinatorKeysByProject = /* @__PURE__ */ new Map();
|
|
14175
|
-
var coordinatorReplacementBarriers = /* @__PURE__ */ new Map();
|
|
14176
|
-
var AutoIndexCancelledError = class extends Error {
|
|
14177
|
-
constructor() {
|
|
14178
|
-
super("Auto-index coordination was cancelled");
|
|
14179
|
-
this.name = "AutoIndexCancelledError";
|
|
14180
|
-
}
|
|
14194
|
+
var OWNER_FILE_NAME2 = "owner.json";
|
|
14195
|
+
var HEARTBEAT_FILE_PREFIX = "heartbeat.";
|
|
14196
|
+
var RECLAIM_DIRECTORY_NAME2 = "reclaim";
|
|
14197
|
+
var REFRESH_REQUEST_FILE_NAME = "refresh-request.json";
|
|
14198
|
+
var HEARTBEAT_INTERVAL_MS = 5e3;
|
|
14199
|
+
var STALE_LEASE_MS = 3e4;
|
|
14200
|
+
var RETRY_DELAY_MS = 5e3;
|
|
14201
|
+
var UUID_PATTERN2 = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
14202
|
+
var BackgroundWorkerStopError = class extends Error {
|
|
14203
|
+
constructor(watcherError, autoIndexError) {
|
|
14204
|
+
super("Failed to stop background worker");
|
|
14205
|
+
this.watcherError = watcherError;
|
|
14206
|
+
this.autoIndexError = autoIndexError;
|
|
14207
|
+
this.name = "BackgroundWorkerStopError";
|
|
14208
|
+
}
|
|
14209
|
+
watcherError;
|
|
14210
|
+
autoIndexError;
|
|
14181
14211
|
};
|
|
14182
|
-
|
|
14183
|
-
|
|
14212
|
+
var workers = /* @__PURE__ */ new Map();
|
|
14213
|
+
var workerKeysByProject = /* @__PURE__ */ new Map();
|
|
14214
|
+
var workerReplacementBarriers = /* @__PURE__ */ new Map();
|
|
14215
|
+
function getErrorCode2(error) {
|
|
14216
|
+
return typeof error === "object" && error !== null && "code" in error ? String(error.code) : void 0;
|
|
14184
14217
|
}
|
|
14185
14218
|
function canonicalizePath(targetPath) {
|
|
14186
14219
|
const resolved = path17.resolve(targetPath);
|
|
14187
|
-
if ((0,
|
|
14220
|
+
if ((0, import_node_fs.existsSync)(resolved)) {
|
|
14188
14221
|
try {
|
|
14189
|
-
return
|
|
14222
|
+
return import_node_fs.realpathSync.native(resolved);
|
|
14190
14223
|
} catch {
|
|
14191
14224
|
return resolved;
|
|
14192
14225
|
}
|
|
@@ -14195,50 +14228,1020 @@ function canonicalizePath(targetPath) {
|
|
|
14195
14228
|
if (parent === resolved) return resolved;
|
|
14196
14229
|
return path17.join(canonicalizePath(parent), path17.basename(resolved));
|
|
14197
14230
|
}
|
|
14198
|
-
function isHomeDirectory(projectRoot) {
|
|
14199
|
-
return canonicalizePath(projectRoot) === canonicalizePath(os6.homedir());
|
|
14200
|
-
}
|
|
14201
14231
|
function projectLookupKey(projectRoot, host) {
|
|
14202
14232
|
return `${host}::${canonicalizePath(projectRoot)}`;
|
|
14203
14233
|
}
|
|
14204
|
-
function
|
|
14234
|
+
function getBackgroundWorkerProjectKey(projectRoot, host) {
|
|
14235
|
+
return projectLookupKey(projectRoot, host);
|
|
14236
|
+
}
|
|
14237
|
+
function resolveIdentity(projectRoot, config, host) {
|
|
14205
14238
|
const canonicalProjectRoot = canonicalizePath(projectRoot);
|
|
14206
|
-
const
|
|
14207
|
-
return
|
|
14239
|
+
const canonicalIndexPath = canonicalizePath(resolveProjectIndexPath(projectRoot, config.scope, host));
|
|
14240
|
+
return {
|
|
14241
|
+
canonicalIndexPath,
|
|
14242
|
+
canonicalProjectRoot,
|
|
14243
|
+
key: `${canonicalIndexPath}::${canonicalProjectRoot}`
|
|
14244
|
+
};
|
|
14208
14245
|
}
|
|
14209
|
-
function
|
|
14210
|
-
|
|
14211
|
-
|
|
14212
|
-
|
|
14213
|
-
|
|
14214
|
-
|
|
14246
|
+
function controllerKey(identity, host) {
|
|
14247
|
+
return `${identity.key}::${host}`;
|
|
14248
|
+
}
|
|
14249
|
+
function leaseDirectoryName(identity) {
|
|
14250
|
+
const hash = (0, import_node_crypto2.createHash)("sha256").update(identity.key).digest("hex").slice(0, 32);
|
|
14251
|
+
return `background-worker.${hash}.lease`;
|
|
14252
|
+
}
|
|
14253
|
+
function leasePathFor(identity) {
|
|
14254
|
+
return path17.join(identity.canonicalIndexPath, leaseDirectoryName(identity));
|
|
14255
|
+
}
|
|
14256
|
+
function parseOwner2(value) {
|
|
14257
|
+
if (typeof value !== "object" || value === null) return null;
|
|
14258
|
+
const candidate = value;
|
|
14259
|
+
if (candidate.version !== 1) return null;
|
|
14260
|
+
if (!Number.isInteger(candidate.pid) || (candidate.pid ?? 0) <= 0) return null;
|
|
14261
|
+
if (typeof candidate.hostname !== "string" || candidate.hostname.length === 0) return null;
|
|
14262
|
+
if (typeof candidate.startedAt !== "string" || Number.isNaN(Date.parse(candidate.startedAt))) return null;
|
|
14263
|
+
if (typeof candidate.heartbeatAt !== "string" || Number.isNaN(Date.parse(candidate.heartbeatAt))) return null;
|
|
14264
|
+
if (typeof candidate.projectRoot !== "string" || candidate.projectRoot.length === 0) return null;
|
|
14265
|
+
if (typeof candidate.indexPath !== "string" || candidate.indexPath.length === 0) return null;
|
|
14266
|
+
if (typeof candidate.token !== "string" || !UUID_PATTERN2.test(candidate.token)) return null;
|
|
14267
|
+
return candidate;
|
|
14268
|
+
}
|
|
14269
|
+
function parseHeartbeat(value, expectedToken) {
|
|
14270
|
+
if (typeof value !== "object" || value === null) return null;
|
|
14271
|
+
const candidate = value;
|
|
14272
|
+
if (candidate.version !== 1 || candidate.token !== expectedToken) return null;
|
|
14273
|
+
if (typeof candidate.heartbeatAt !== "string" || Number.isNaN(Date.parse(candidate.heartbeatAt))) return null;
|
|
14274
|
+
return candidate;
|
|
14275
|
+
}
|
|
14276
|
+
function parseReclaimOwner2(value) {
|
|
14277
|
+
if (typeof value !== "object" || value === null) return null;
|
|
14278
|
+
const candidate = value;
|
|
14279
|
+
if (candidate.version !== 1) return null;
|
|
14280
|
+
if (!Number.isInteger(candidate.pid) || (candidate.pid ?? 0) <= 0) return null;
|
|
14281
|
+
if (typeof candidate.hostname !== "string" || candidate.hostname.length === 0) return null;
|
|
14282
|
+
if (typeof candidate.startedAt !== "string" || Number.isNaN(Date.parse(candidate.startedAt))) return null;
|
|
14283
|
+
if (typeof candidate.token !== "string" || !UUID_PATTERN2.test(candidate.token)) return null;
|
|
14284
|
+
if (candidate.expectedOwnerToken !== null && (typeof candidate.expectedOwnerToken !== "string" || !UUID_PATTERN2.test(candidate.expectedOwnerToken))) return null;
|
|
14285
|
+
return candidate;
|
|
14286
|
+
}
|
|
14287
|
+
function heartbeatPath(leasePath, token) {
|
|
14288
|
+
return path17.join(leasePath, `${HEARTBEAT_FILE_PREFIX}${token}.json`);
|
|
14289
|
+
}
|
|
14290
|
+
function reclaimPath(leasePath) {
|
|
14291
|
+
return path17.join(leasePath, RECLAIM_DIRECTORY_NAME2);
|
|
14292
|
+
}
|
|
14293
|
+
function refreshRequestPath(leasePath) {
|
|
14294
|
+
return path17.join(leasePath, REFRESH_REQUEST_FILE_NAME);
|
|
14295
|
+
}
|
|
14296
|
+
function readLeaseOwner(leasePath) {
|
|
14297
|
+
try {
|
|
14298
|
+
return parseOwner2(JSON.parse((0, import_node_fs.readFileSync)(path17.join(leasePath, OWNER_FILE_NAME2), "utf-8")));
|
|
14299
|
+
} catch {
|
|
14300
|
+
return null;
|
|
14215
14301
|
}
|
|
14216
|
-
return { safeToRun: true };
|
|
14217
14302
|
}
|
|
14218
|
-
function
|
|
14219
|
-
|
|
14220
|
-
if (
|
|
14221
|
-
|
|
14222
|
-
|
|
14303
|
+
function readOwner(leasePath) {
|
|
14304
|
+
const owner = readLeaseOwner(leasePath);
|
|
14305
|
+
if (!owner) return null;
|
|
14306
|
+
try {
|
|
14307
|
+
const heartbeat = parseHeartbeat(
|
|
14308
|
+
JSON.parse((0, import_node_fs.readFileSync)(heartbeatPath(leasePath, owner.token), "utf-8")),
|
|
14309
|
+
owner.token
|
|
14310
|
+
);
|
|
14311
|
+
return heartbeat ? { ...owner, heartbeatAt: heartbeat.heartbeatAt } : owner;
|
|
14312
|
+
} catch {
|
|
14313
|
+
return owner;
|
|
14223
14314
|
}
|
|
14224
|
-
|
|
14225
|
-
|
|
14315
|
+
}
|
|
14316
|
+
function readReclaimOwner2(leasePath) {
|
|
14317
|
+
try {
|
|
14318
|
+
return parseReclaimOwner2(JSON.parse((0, import_node_fs.readFileSync)(path17.join(reclaimPath(leasePath), OWNER_FILE_NAME2), "utf-8")));
|
|
14319
|
+
} catch {
|
|
14320
|
+
return null;
|
|
14226
14321
|
}
|
|
14227
|
-
if (progress.phase === "storing") return 95;
|
|
14228
|
-
return 0;
|
|
14229
14322
|
}
|
|
14230
|
-
function
|
|
14231
|
-
if (
|
|
14232
|
-
|
|
14323
|
+
function ownerLiveness(owner) {
|
|
14324
|
+
if (owner.hostname !== os6.hostname()) return "unknown";
|
|
14325
|
+
try {
|
|
14326
|
+
process.kill(owner.pid, 0);
|
|
14327
|
+
return "alive";
|
|
14328
|
+
} catch (error) {
|
|
14329
|
+
const code = getErrorCode2(error);
|
|
14330
|
+
if (code === "ESRCH") return "dead";
|
|
14331
|
+
if (code === "EPERM") return "alive";
|
|
14332
|
+
return "unknown";
|
|
14233
14333
|
}
|
|
14234
|
-
return "Automatic indexing failed. Check the embedding provider configuration, then run index_codebase.";
|
|
14235
14334
|
}
|
|
14236
|
-
function
|
|
14237
|
-
|
|
14238
|
-
|
|
14239
|
-
|
|
14335
|
+
function isHeartbeatExpired(owner) {
|
|
14336
|
+
return Date.now() - Date.parse(owner.heartbeatAt) >= STALE_LEASE_MS;
|
|
14337
|
+
}
|
|
14338
|
+
function sameOwner2(left, right) {
|
|
14339
|
+
return left.pid === right.pid && left.hostname === right.hostname && left.token === right.token;
|
|
14340
|
+
}
|
|
14341
|
+
function writeHeartbeat(leasePath, owner) {
|
|
14342
|
+
const targetPath = heartbeatPath(leasePath, owner.token);
|
|
14343
|
+
const temporaryPath = `${targetPath}.tmp.${process.pid}.${owner.token}.${(0, import_node_crypto2.randomUUID)()}`;
|
|
14344
|
+
const heartbeat = {
|
|
14345
|
+
version: 1,
|
|
14346
|
+
token: owner.token,
|
|
14347
|
+
heartbeatAt: owner.heartbeatAt
|
|
14348
|
+
};
|
|
14349
|
+
try {
|
|
14350
|
+
(0, import_node_fs.writeFileSync)(temporaryPath, JSON.stringify(heartbeat), {
|
|
14351
|
+
encoding: "utf-8",
|
|
14352
|
+
flag: "wx",
|
|
14353
|
+
mode: 384
|
|
14354
|
+
});
|
|
14355
|
+
(0, import_node_fs.renameSync)(temporaryPath, targetPath);
|
|
14356
|
+
const currentOwner = readLeaseOwner(leasePath);
|
|
14357
|
+
return currentOwner !== null && sameOwner2(currentOwner, owner);
|
|
14358
|
+
} finally {
|
|
14359
|
+
if ((0, import_node_fs.existsSync)(temporaryPath)) (0, import_node_fs.rmSync)(temporaryPath, { force: true });
|
|
14360
|
+
}
|
|
14361
|
+
}
|
|
14362
|
+
function requestRefreshFromLeader(leasePath, allowDisabledAutoIndex) {
|
|
14363
|
+
const requestPath = refreshRequestPath(leasePath);
|
|
14364
|
+
const temporaryPath = `${requestPath}.tmp.${process.pid}.${(0, import_node_crypto2.randomUUID)()}`;
|
|
14365
|
+
try {
|
|
14366
|
+
const request = {
|
|
14367
|
+
allowDisabledAutoIndex,
|
|
14368
|
+
requestedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
14369
|
+
version: 1
|
|
14370
|
+
};
|
|
14371
|
+
(0, import_node_fs.writeFileSync)(temporaryPath, JSON.stringify(request), {
|
|
14372
|
+
encoding: "utf-8",
|
|
14373
|
+
flag: "wx",
|
|
14374
|
+
mode: 384
|
|
14375
|
+
});
|
|
14376
|
+
(0, import_node_fs.renameSync)(temporaryPath, requestPath);
|
|
14377
|
+
} catch (error) {
|
|
14378
|
+
if (getErrorCode2(error) !== "ENOENT") {
|
|
14379
|
+
console.error("[codebase-index] Failed to request background index refresh from the project worker:", error);
|
|
14380
|
+
}
|
|
14381
|
+
} finally {
|
|
14382
|
+
if ((0, import_node_fs.existsSync)(temporaryPath)) (0, import_node_fs.rmSync)(temporaryPath, { force: true });
|
|
14383
|
+
}
|
|
14384
|
+
}
|
|
14385
|
+
function consumeRefreshRequest(leasePath) {
|
|
14386
|
+
const requestPath = refreshRequestPath(leasePath);
|
|
14387
|
+
const claimedPath = `${requestPath}.handling.${process.pid}.${(0, import_node_crypto2.randomUUID)()}`;
|
|
14388
|
+
try {
|
|
14389
|
+
(0, import_node_fs.renameSync)(requestPath, claimedPath);
|
|
14390
|
+
} catch (error) {
|
|
14391
|
+
if (getErrorCode2(error) === "ENOENT") return null;
|
|
14392
|
+
throw error;
|
|
14393
|
+
}
|
|
14394
|
+
try {
|
|
14395
|
+
const value = JSON.parse((0, import_node_fs.readFileSync)(claimedPath, "utf-8"));
|
|
14396
|
+
return {
|
|
14397
|
+
allowDisabledAutoIndex: value.version === 1 && value.allowDisabledAutoIndex === true,
|
|
14398
|
+
requestedAt: typeof value.requestedAt === "string" ? value.requestedAt : (/* @__PURE__ */ new Date()).toISOString(),
|
|
14399
|
+
version: 1
|
|
14400
|
+
};
|
|
14401
|
+
} catch {
|
|
14402
|
+
return { allowDisabledAutoIndex: false, requestedAt: (/* @__PURE__ */ new Date()).toISOString(), version: 1 };
|
|
14403
|
+
} finally {
|
|
14404
|
+
(0, import_node_fs.rmSync)(claimedPath, { force: true });
|
|
14405
|
+
}
|
|
14406
|
+
}
|
|
14407
|
+
function publishLease(leasePath, owner) {
|
|
14408
|
+
const candidatePath = `${leasePath}.candidate.${process.pid}.${owner.token}`;
|
|
14409
|
+
try {
|
|
14410
|
+
(0, import_node_fs.mkdirSync)(candidatePath, { mode: 448 });
|
|
14411
|
+
} catch (error) {
|
|
14412
|
+
if (getErrorCode2(error) === "ENOENT") return false;
|
|
14413
|
+
throw error;
|
|
14414
|
+
}
|
|
14415
|
+
try {
|
|
14416
|
+
(0, import_node_fs.writeFileSync)(path17.join(candidatePath, OWNER_FILE_NAME2), JSON.stringify(owner), {
|
|
14417
|
+
encoding: "utf-8",
|
|
14418
|
+
flag: "wx",
|
|
14419
|
+
mode: 384
|
|
14420
|
+
});
|
|
14421
|
+
if ((0, import_node_fs.existsSync)(leasePath)) return false;
|
|
14422
|
+
try {
|
|
14423
|
+
(0, import_node_fs.renameSync)(candidatePath, leasePath);
|
|
14424
|
+
return true;
|
|
14425
|
+
} catch (error) {
|
|
14426
|
+
if ((0, import_node_fs.existsSync)(leasePath) || getErrorCode2(error) === "ENOENT") return false;
|
|
14427
|
+
throw error;
|
|
14428
|
+
}
|
|
14429
|
+
} finally {
|
|
14430
|
+
if ((0, import_node_fs.existsSync)(candidatePath)) (0, import_node_fs.rmSync)(candidatePath, { recursive: true, force: true });
|
|
14431
|
+
}
|
|
14432
|
+
}
|
|
14433
|
+
function sameReclaimOwner2(left, right) {
|
|
14434
|
+
return left.pid === right.pid && left.hostname === right.hostname && left.token === right.token && left.expectedOwnerToken === right.expectedOwnerToken;
|
|
14435
|
+
}
|
|
14436
|
+
function reclaimerLiveness(owner) {
|
|
14437
|
+
return ownerLiveness(owner);
|
|
14438
|
+
}
|
|
14439
|
+
function isReclaimMarkerExpired(leasePath, owner) {
|
|
14440
|
+
const startedAt = owner ? Date.parse(owner.startedAt) : (() => {
|
|
14441
|
+
try {
|
|
14442
|
+
return (0, import_node_fs.lstatSync)(reclaimPath(leasePath)).mtimeMs;
|
|
14443
|
+
} catch {
|
|
14444
|
+
return Date.now();
|
|
14445
|
+
}
|
|
14446
|
+
})();
|
|
14447
|
+
return Date.now() - startedAt >= STALE_LEASE_MS;
|
|
14448
|
+
}
|
|
14449
|
+
function hasActiveReclaimMarker(leasePath, owner) {
|
|
14450
|
+
const marker = readReclaimOwner2(leasePath);
|
|
14451
|
+
return marker !== null && marker.expectedOwnerToken === owner.token && (marker.hostname !== os6.hostname() || ownerLiveness(owner) !== "alive");
|
|
14452
|
+
}
|
|
14453
|
+
function publishReclaimMarker(leasePath, expectedOwner) {
|
|
14454
|
+
const markerPath = reclaimPath(leasePath);
|
|
14455
|
+
const owner = {
|
|
14456
|
+
version: 1,
|
|
14457
|
+
pid: process.pid,
|
|
14458
|
+
hostname: os6.hostname(),
|
|
14459
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
14460
|
+
token: (0, import_node_crypto2.randomUUID)(),
|
|
14461
|
+
expectedOwnerToken: expectedOwner?.token ?? null
|
|
14462
|
+
};
|
|
14463
|
+
try {
|
|
14464
|
+
(0, import_node_fs.mkdirSync)(markerPath, { mode: 448 });
|
|
14465
|
+
} catch (error) {
|
|
14466
|
+
if (getErrorCode2(error) === "EEXIST" || getErrorCode2(error) === "ENOENT") return null;
|
|
14467
|
+
throw error;
|
|
14468
|
+
}
|
|
14469
|
+
try {
|
|
14470
|
+
(0, import_node_fs.writeFileSync)(path17.join(markerPath, OWNER_FILE_NAME2), JSON.stringify(owner), {
|
|
14471
|
+
encoding: "utf-8",
|
|
14472
|
+
flag: "wx",
|
|
14473
|
+
mode: 384
|
|
14474
|
+
});
|
|
14475
|
+
return owner;
|
|
14476
|
+
} catch (error) {
|
|
14477
|
+
(0, import_node_fs.rmSync)(markerPath, { recursive: true, force: true });
|
|
14478
|
+
throw error;
|
|
14479
|
+
}
|
|
14480
|
+
}
|
|
14481
|
+
function removeExpiredReclaimMarker(leasePath, expectedOwner) {
|
|
14482
|
+
const marker = readReclaimOwner2(leasePath);
|
|
14483
|
+
const markerPath = reclaimPath(leasePath);
|
|
14484
|
+
if (!(0, import_node_fs.existsSync)(markerPath)) return false;
|
|
14485
|
+
if (marker && marker.expectedOwnerToken !== (expectedOwner?.token ?? null)) return false;
|
|
14486
|
+
if (marker && (reclaimerLiveness(marker) === "alive" || !isReclaimMarkerExpired(leasePath, marker))) return false;
|
|
14487
|
+
if (!marker && !isReclaimMarkerExpired(leasePath, null)) return false;
|
|
14488
|
+
const staleMarkerPath = `${markerPath}.stale.${marker?.pid ?? process.pid}.${marker?.token ?? (0, import_node_crypto2.randomUUID)()}.${(0, import_node_crypto2.randomUUID)()}`;
|
|
14489
|
+
try {
|
|
14490
|
+
(0, import_node_fs.renameSync)(markerPath, staleMarkerPath);
|
|
14491
|
+
} catch (error) {
|
|
14492
|
+
if (getErrorCode2(error) === "ENOENT") return false;
|
|
14493
|
+
throw error;
|
|
14494
|
+
}
|
|
14495
|
+
try {
|
|
14496
|
+
let claimedMarker = null;
|
|
14497
|
+
try {
|
|
14498
|
+
claimedMarker = parseReclaimOwner2(
|
|
14499
|
+
JSON.parse((0, import_node_fs.readFileSync)(path17.join(staleMarkerPath, OWNER_FILE_NAME2), "utf-8"))
|
|
14500
|
+
);
|
|
14501
|
+
} catch {
|
|
14502
|
+
claimedMarker = null;
|
|
14503
|
+
}
|
|
14504
|
+
const markerMatches = marker ? claimedMarker !== null && sameReclaimOwner2(claimedMarker, marker) : claimedMarker === null;
|
|
14505
|
+
if (!markerMatches || !canReclaimLease(leasePath, expectedOwner)) {
|
|
14506
|
+
if (!(0, import_node_fs.existsSync)(markerPath) && (0, import_node_fs.existsSync)(staleMarkerPath)) (0, import_node_fs.renameSync)(staleMarkerPath, markerPath);
|
|
14507
|
+
return false;
|
|
14508
|
+
}
|
|
14509
|
+
(0, import_node_fs.rmSync)(staleMarkerPath, { recursive: true, force: true });
|
|
14510
|
+
return true;
|
|
14511
|
+
} catch (error) {
|
|
14512
|
+
if (getErrorCode2(error) === "ENOENT") return false;
|
|
14513
|
+
throw error;
|
|
14514
|
+
}
|
|
14515
|
+
}
|
|
14516
|
+
function canReclaimLease(leasePath, expectedOwner) {
|
|
14517
|
+
if (!(0, import_node_fs.existsSync)(leasePath)) return false;
|
|
14518
|
+
if (!expectedOwner) return false;
|
|
14519
|
+
const currentOwner = readOwner(leasePath);
|
|
14520
|
+
if (!currentOwner || !sameOwner2(currentOwner, expectedOwner)) return false;
|
|
14521
|
+
if (currentOwner.hostname === os6.hostname()) {
|
|
14522
|
+
return ownerLiveness(currentOwner) === "dead";
|
|
14523
|
+
}
|
|
14524
|
+
return isHeartbeatExpired(currentOwner);
|
|
14525
|
+
}
|
|
14526
|
+
function reclaimLease(leasePath, expectedOwner) {
|
|
14527
|
+
let marker = null;
|
|
14528
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
14529
|
+
marker = publishReclaimMarker(leasePath, expectedOwner);
|
|
14530
|
+
if (marker) break;
|
|
14531
|
+
if (attempt === 0 && removeExpiredReclaimMarker(leasePath, expectedOwner)) continue;
|
|
14532
|
+
return false;
|
|
14533
|
+
}
|
|
14534
|
+
if (!marker) return false;
|
|
14535
|
+
const markerPath = reclaimPath(leasePath);
|
|
14536
|
+
try {
|
|
14537
|
+
const currentMarker = readReclaimOwner2(leasePath);
|
|
14538
|
+
if (!currentMarker || !sameReclaimOwner2(currentMarker, marker) || !canReclaimLease(leasePath, expectedOwner)) {
|
|
14539
|
+
return false;
|
|
14540
|
+
}
|
|
14541
|
+
const stalePath = `${leasePath}.stale.${process.pid}.${marker.token}`;
|
|
14542
|
+
(0, import_node_fs.renameSync)(leasePath, stalePath);
|
|
14543
|
+
const quarantinedOwner = readOwner(stalePath);
|
|
14544
|
+
const quarantinedMarker = readReclaimOwner2(stalePath);
|
|
14545
|
+
if (!quarantinedMarker || !sameReclaimOwner2(quarantinedMarker, marker) || expectedOwner !== null && (!quarantinedOwner || !sameOwner2(quarantinedOwner, expectedOwner))) {
|
|
14546
|
+
if (!(0, import_node_fs.existsSync)(leasePath) && (0, import_node_fs.existsSync)(stalePath)) (0, import_node_fs.renameSync)(stalePath, leasePath);
|
|
14547
|
+
return false;
|
|
14548
|
+
}
|
|
14549
|
+
(0, import_node_fs.rmSync)(stalePath, { recursive: true, force: true });
|
|
14550
|
+
return true;
|
|
14551
|
+
} catch (error) {
|
|
14552
|
+
if (getErrorCode2(error) === "ENOENT") return false;
|
|
14553
|
+
throw error;
|
|
14554
|
+
} finally {
|
|
14555
|
+
const currentMarker = readReclaimOwner2(leasePath);
|
|
14556
|
+
if (currentMarker && sameReclaimOwner2(currentMarker, marker)) {
|
|
14557
|
+
(0, import_node_fs.rmSync)(markerPath, { recursive: true, force: true });
|
|
14558
|
+
}
|
|
14559
|
+
}
|
|
14560
|
+
}
|
|
14561
|
+
function acquireLease(identity) {
|
|
14562
|
+
(0, import_node_fs.mkdirSync)(identity.canonicalIndexPath, { recursive: true, mode: 448 });
|
|
14563
|
+
const canonicalIndexPath = import_node_fs.realpathSync.native(identity.canonicalIndexPath);
|
|
14564
|
+
const leasePath = path17.join(canonicalIndexPath, leaseDirectoryName({ ...identity, canonicalIndexPath }));
|
|
14565
|
+
for (let attempt = 0; attempt < 4; attempt += 1) {
|
|
14566
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
14567
|
+
const owner = {
|
|
14568
|
+
version: 1,
|
|
14569
|
+
pid: process.pid,
|
|
14570
|
+
hostname: os6.hostname(),
|
|
14571
|
+
startedAt: timestamp,
|
|
14572
|
+
heartbeatAt: timestamp,
|
|
14573
|
+
projectRoot: identity.canonicalProjectRoot,
|
|
14574
|
+
indexPath: canonicalIndexPath,
|
|
14575
|
+
token: (0, import_node_crypto2.randomUUID)()
|
|
14576
|
+
};
|
|
14577
|
+
if (publishLease(leasePath, owner)) {
|
|
14578
|
+
return { leasePath, owner };
|
|
14579
|
+
}
|
|
14580
|
+
const existingOwner = readOwner(leasePath);
|
|
14581
|
+
if (existingOwner) {
|
|
14582
|
+
if (canReclaimLease(leasePath, existingOwner) && reclaimLease(leasePath, existingOwner)) continue;
|
|
14583
|
+
return null;
|
|
14584
|
+
}
|
|
14585
|
+
return null;
|
|
14586
|
+
}
|
|
14587
|
+
return null;
|
|
14588
|
+
}
|
|
14589
|
+
function releaseLease(lease) {
|
|
14590
|
+
const currentOwner = readOwner(lease.leasePath);
|
|
14591
|
+
if (!currentOwner || !sameOwner2(currentOwner, lease.owner)) return false;
|
|
14592
|
+
const releasePath = `${lease.leasePath}.release.${lease.owner.pid}.${lease.owner.token}`;
|
|
14593
|
+
try {
|
|
14594
|
+
(0, import_node_fs.renameSync)(lease.leasePath, releasePath);
|
|
14595
|
+
} catch (error) {
|
|
14596
|
+
if (getErrorCode2(error) === "ENOENT") return false;
|
|
14597
|
+
throw error;
|
|
14598
|
+
}
|
|
14599
|
+
const claimedOwner = readOwner(releasePath);
|
|
14600
|
+
if (!claimedOwner || !sameOwner2(claimedOwner, lease.owner)) {
|
|
14601
|
+
if (!(0, import_node_fs.existsSync)(lease.leasePath) && (0, import_node_fs.existsSync)(releasePath)) {
|
|
14602
|
+
(0, import_node_fs.renameSync)(releasePath, lease.leasePath);
|
|
14603
|
+
}
|
|
14604
|
+
return false;
|
|
14605
|
+
}
|
|
14606
|
+
(0, import_node_fs.rmSync)(releasePath, { recursive: true, force: true });
|
|
14607
|
+
return true;
|
|
14608
|
+
}
|
|
14609
|
+
var BackgroundWorkerController = class {
|
|
14610
|
+
constructor(projectRoot, host, config, hooks, identity) {
|
|
14611
|
+
this.projectRoot = projectRoot;
|
|
14612
|
+
this.host = host;
|
|
14613
|
+
this.config = config;
|
|
14614
|
+
this.hooks = hooks;
|
|
14615
|
+
this.identity = identity;
|
|
14616
|
+
}
|
|
14617
|
+
projectRoot;
|
|
14618
|
+
host;
|
|
14619
|
+
config;
|
|
14620
|
+
hooks;
|
|
14621
|
+
identity;
|
|
14622
|
+
lease = null;
|
|
14623
|
+
watcher = null;
|
|
14624
|
+
leaderReady = Promise.resolve();
|
|
14625
|
+
heartbeatTimer = null;
|
|
14626
|
+
retryTimer = null;
|
|
14627
|
+
teardownRetryTimer = null;
|
|
14628
|
+
transition = Promise.resolve();
|
|
14629
|
+
stopPromise = null;
|
|
14630
|
+
stopped = false;
|
|
14631
|
+
stopping = false;
|
|
14632
|
+
losingLeadership = false;
|
|
14633
|
+
restartAfterStop = false;
|
|
14634
|
+
leaderWorkStopped = false;
|
|
14635
|
+
startingLeaderWork = false;
|
|
14636
|
+
stopAutoIndexOnTeardown = true;
|
|
14637
|
+
autoIndexStarted = false;
|
|
14638
|
+
reportedError = null;
|
|
14639
|
+
update(config, hooks, options) {
|
|
14640
|
+
const autoIndexWasEnabled = this.config.indexing.autoIndex;
|
|
14641
|
+
const shouldReplaceWatcher = this.watcher !== null && hooks.watcherFactory !== void 0 && (hooks.watcherFactory === null || hooks.replaceWatcher === true);
|
|
14642
|
+
this.config = config;
|
|
14643
|
+
this.hooks = {
|
|
14644
|
+
...this.hooks,
|
|
14645
|
+
...hooks,
|
|
14646
|
+
watcherFactory: hooks.watcherFactory === void 0 ? this.hooks.watcherFactory : hooks.watcherFactory,
|
|
14647
|
+
watcherFactoryForConfig: hooks.watcherFactoryForConfig === void 0 ? this.hooks.watcherFactoryForConfig : hooks.watcherFactoryForConfig
|
|
14648
|
+
};
|
|
14649
|
+
if (autoIndexWasEnabled && !config.indexing.autoIndex || options.restartAutoIndex === true && config.indexing.autoIndex && !this.startingLeaderWork) {
|
|
14650
|
+
this.autoIndexStarted = false;
|
|
14651
|
+
}
|
|
14652
|
+
if (!this.canRun()) {
|
|
14653
|
+
void this.stop().catch((error) => {
|
|
14654
|
+
console.error("[codebase-index] Failed to stop background worker after disabling automatic work:", error);
|
|
14655
|
+
});
|
|
14656
|
+
return;
|
|
14657
|
+
}
|
|
14658
|
+
if (shouldReplaceWatcher) {
|
|
14659
|
+
void this.enqueue(async () => {
|
|
14660
|
+
const watcher = this.watcher;
|
|
14661
|
+
if (watcher) {
|
|
14662
|
+
await watcher.stop();
|
|
14663
|
+
if (this.watcher === watcher) this.watcher = null;
|
|
14664
|
+
}
|
|
14665
|
+
if (this.lease && !this.stopped) this.startLeaderWork();
|
|
14666
|
+
}).catch((error) => {
|
|
14667
|
+
console.error("[codebase-index] Failed to replace background file watcher:", error);
|
|
14668
|
+
});
|
|
14669
|
+
}
|
|
14670
|
+
this.start();
|
|
14671
|
+
}
|
|
14672
|
+
startAfter(activation) {
|
|
14673
|
+
this.transition = activation.catch(() => void 0);
|
|
14674
|
+
this.start();
|
|
14675
|
+
}
|
|
14676
|
+
start() {
|
|
14677
|
+
if (!this.canRun() || this.losingLeadership) return;
|
|
14678
|
+
if (this.stopping) {
|
|
14679
|
+
this.restartAfterStop = true;
|
|
14680
|
+
return;
|
|
14681
|
+
}
|
|
14682
|
+
this.stopped = false;
|
|
14683
|
+
void this.enqueue(async () => {
|
|
14684
|
+
if (this.stopped || this.stopping || this.losingLeadership || !this.canRun()) return;
|
|
14685
|
+
if (!this.lease) {
|
|
14686
|
+
try {
|
|
14687
|
+
this.lease = acquireLease(this.identity);
|
|
14688
|
+
this.reportedError = null;
|
|
14689
|
+
} catch (error) {
|
|
14690
|
+
this.reportAcquireError(error);
|
|
14691
|
+
this.scheduleRetry();
|
|
14692
|
+
return;
|
|
14693
|
+
}
|
|
14694
|
+
}
|
|
14695
|
+
if (!this.lease) {
|
|
14696
|
+
this.scheduleRetry();
|
|
14697
|
+
return;
|
|
14698
|
+
}
|
|
14699
|
+
this.startHeartbeat();
|
|
14700
|
+
this.startLeaderWork();
|
|
14701
|
+
});
|
|
14702
|
+
}
|
|
14703
|
+
waitForStart() {
|
|
14704
|
+
return this.transition.catch(() => void 0).then(() => this.leaderReady);
|
|
14705
|
+
}
|
|
14706
|
+
requestRefresh(allowDisabledAutoIndex = false) {
|
|
14707
|
+
this.start();
|
|
14708
|
+
if (!this.isLeader()) {
|
|
14709
|
+
requestRefreshFromLeader(leasePathFor(this.identity), allowDisabledAutoIndex);
|
|
14710
|
+
return;
|
|
14711
|
+
}
|
|
14712
|
+
void this.enqueue(async () => {
|
|
14713
|
+
if (this.stopped || !this.lease) return;
|
|
14714
|
+
this.hooks.startAutoIndex("retrieval", allowDisabledAutoIndex);
|
|
14715
|
+
});
|
|
14716
|
+
}
|
|
14717
|
+
isLeader() {
|
|
14718
|
+
return this.lease !== null && !this.stopping && !this.losingLeadership;
|
|
14719
|
+
}
|
|
14720
|
+
isStopping() {
|
|
14721
|
+
return this.stopping;
|
|
14722
|
+
}
|
|
14723
|
+
getHooksForConfig(config) {
|
|
14724
|
+
const watcherFactoryForConfig = this.hooks.watcherFactoryForConfig;
|
|
14725
|
+
if (!watcherFactoryForConfig) return this.hooks;
|
|
14726
|
+
return {
|
|
14727
|
+
...this.hooks,
|
|
14728
|
+
watcherFactory: watcherFactoryForConfig(config),
|
|
14729
|
+
replaceWatcher: true
|
|
14730
|
+
};
|
|
14731
|
+
}
|
|
14732
|
+
attachWatcher(watcherFactory, watcherFactoryForConfig) {
|
|
14733
|
+
if (this.hooks.watcherFactory !== void 0) return;
|
|
14734
|
+
this.hooks = {
|
|
14735
|
+
...this.hooks,
|
|
14736
|
+
watcherFactory,
|
|
14737
|
+
watcherFactoryForConfig: watcherFactoryForConfig ?? this.hooks.watcherFactoryForConfig
|
|
14738
|
+
};
|
|
14739
|
+
this.start();
|
|
14740
|
+
}
|
|
14741
|
+
async stop(stopAutoIndex = true) {
|
|
14742
|
+
if (this.stopPromise) return this.stopPromise;
|
|
14743
|
+
this.stopped = true;
|
|
14744
|
+
this.stopping = true;
|
|
14745
|
+
this.stopAutoIndexOnTeardown &&= stopAutoIndex;
|
|
14746
|
+
this.clearRetryTimer();
|
|
14747
|
+
const attempt = this.enqueue(async () => {
|
|
14748
|
+
try {
|
|
14749
|
+
const lease = this.lease;
|
|
14750
|
+
if (this.leaderWorkStopped) {
|
|
14751
|
+
if (lease) {
|
|
14752
|
+
this.releaseStoppedLease(lease);
|
|
14753
|
+
} else {
|
|
14754
|
+
this.finishStoppedLease();
|
|
14755
|
+
}
|
|
14756
|
+
return;
|
|
14757
|
+
}
|
|
14758
|
+
const hadLeaderWork = lease !== null || this.watcher !== null || this.autoIndexStarted;
|
|
14759
|
+
const stopped = await this.stopLeaderWork(hadLeaderWork && this.stopAutoIndexOnTeardown);
|
|
14760
|
+
if (!lease) {
|
|
14761
|
+
this.finishStoppedLease();
|
|
14762
|
+
return;
|
|
14763
|
+
}
|
|
14764
|
+
if (!stopped.completed) {
|
|
14765
|
+
this.releaseLeaseWhenAutoIndexStops(lease, stopped.completion);
|
|
14766
|
+
return;
|
|
14767
|
+
}
|
|
14768
|
+
this.leaderWorkStopped = true;
|
|
14769
|
+
this.releaseStoppedLease(lease);
|
|
14770
|
+
} catch (error) {
|
|
14771
|
+
this.scheduleTeardownRetry();
|
|
14772
|
+
throw error;
|
|
14773
|
+
}
|
|
14774
|
+
});
|
|
14775
|
+
const completion = attempt.finally(() => {
|
|
14776
|
+
if (this.stopPromise === completion) this.stopPromise = null;
|
|
14777
|
+
});
|
|
14778
|
+
this.stopPromise = completion;
|
|
14779
|
+
return completion;
|
|
14780
|
+
}
|
|
14781
|
+
canRun() {
|
|
14782
|
+
return this.config.indexing.autoIndex || this.hooks.watcherFactory != null;
|
|
14783
|
+
}
|
|
14784
|
+
enqueue(operation) {
|
|
14785
|
+
const next = this.transition.catch(() => void 0).then(operation);
|
|
14786
|
+
this.transition = next;
|
|
14787
|
+
return next;
|
|
14788
|
+
}
|
|
14789
|
+
startLeaderWork() {
|
|
14790
|
+
if (this.stopped || this.stopping || this.losingLeadership) return;
|
|
14791
|
+
this.startingLeaderWork = true;
|
|
14792
|
+
try {
|
|
14793
|
+
if (this.config.indexing.autoIndex && !this.autoIndexStarted) {
|
|
14794
|
+
this.autoIndexStarted = true;
|
|
14795
|
+
this.hooks.startAutoIndex("startup");
|
|
14796
|
+
}
|
|
14797
|
+
if (!this.watcher && this.hooks.watcherFactory) {
|
|
14798
|
+
try {
|
|
14799
|
+
const watcher = this.hooks.watcherFactory();
|
|
14800
|
+
this.watcher = watcher;
|
|
14801
|
+
this.leaderReady = watcher.whenReady?.().catch((error) => {
|
|
14802
|
+
console.error("[codebase-index] Failed while waiting for background file watcher startup:", error);
|
|
14803
|
+
}) ?? Promise.resolve();
|
|
14804
|
+
} catch (error) {
|
|
14805
|
+
console.error("[codebase-index] Failed to start background file watcher:", error);
|
|
14806
|
+
this.leaderReady = Promise.resolve();
|
|
14807
|
+
}
|
|
14808
|
+
}
|
|
14809
|
+
} finally {
|
|
14810
|
+
this.startingLeaderWork = false;
|
|
14811
|
+
}
|
|
14812
|
+
}
|
|
14813
|
+
async stopLeaderWork(stopAutoIndex) {
|
|
14814
|
+
const watcher = this.watcher;
|
|
14815
|
+
let watcherError;
|
|
14816
|
+
if (watcher) {
|
|
14817
|
+
try {
|
|
14818
|
+
await watcher.stop();
|
|
14819
|
+
if (this.watcher === watcher) this.watcher = null;
|
|
14820
|
+
} catch (error) {
|
|
14821
|
+
watcherError = error;
|
|
14822
|
+
}
|
|
14823
|
+
}
|
|
14824
|
+
let autoIndexError;
|
|
14825
|
+
let autoIndexStop = {
|
|
14826
|
+
completed: true,
|
|
14827
|
+
completion: Promise.resolve()
|
|
14828
|
+
};
|
|
14829
|
+
if (stopAutoIndex) {
|
|
14830
|
+
try {
|
|
14831
|
+
autoIndexStop = await this.hooks.stopAutoIndex();
|
|
14832
|
+
this.autoIndexStarted = false;
|
|
14833
|
+
} catch (error) {
|
|
14834
|
+
autoIndexError = error;
|
|
14835
|
+
}
|
|
14836
|
+
}
|
|
14837
|
+
if (watcherError !== void 0 || autoIndexError !== void 0) {
|
|
14838
|
+
throw new BackgroundWorkerStopError(watcherError, autoIndexError);
|
|
14839
|
+
}
|
|
14840
|
+
return autoIndexStop;
|
|
14841
|
+
}
|
|
14842
|
+
releaseLeaseWhenAutoIndexStops(lease, completion) {
|
|
14843
|
+
void completion.then(
|
|
14844
|
+
() => {
|
|
14845
|
+
void this.enqueue(async () => {
|
|
14846
|
+
if (this.lease !== lease || !this.stopping) return;
|
|
14847
|
+
this.leaderWorkStopped = true;
|
|
14848
|
+
this.releaseStoppedLease(lease);
|
|
14849
|
+
}).catch((error) => {
|
|
14850
|
+
console.error("[codebase-index] Failed to release background worker lease after automatic indexing stopped:", error);
|
|
14851
|
+
this.scheduleTeardownRetry();
|
|
14852
|
+
});
|
|
14853
|
+
},
|
|
14854
|
+
(error) => {
|
|
14855
|
+
console.error("[codebase-index] Failed while waiting for automatic indexing to stop:", error);
|
|
14856
|
+
this.scheduleTeardownRetry();
|
|
14857
|
+
}
|
|
14858
|
+
);
|
|
14859
|
+
}
|
|
14860
|
+
releaseStoppedLease(lease) {
|
|
14861
|
+
if (this.lease !== lease) {
|
|
14862
|
+
this.finishStoppedLease();
|
|
14863
|
+
return;
|
|
14864
|
+
}
|
|
14865
|
+
releaseLease(lease);
|
|
14866
|
+
this.lease = null;
|
|
14867
|
+
this.finishStoppedLease();
|
|
14868
|
+
}
|
|
14869
|
+
finishStoppedLease() {
|
|
14870
|
+
this.leaderWorkStopped = false;
|
|
14871
|
+
this.stopAutoIndexOnTeardown = true;
|
|
14872
|
+
this.stopping = false;
|
|
14873
|
+
this.clearTimers();
|
|
14874
|
+
this.restartAfterTeardown();
|
|
14875
|
+
if (!this.stopped || this.stopping) return;
|
|
14876
|
+
const projectKey = projectLookupKey(this.projectRoot, this.host);
|
|
14877
|
+
const key = controllerKey(this.identity, this.host);
|
|
14878
|
+
if (workers.get(key) === this) workers.delete(key);
|
|
14879
|
+
if (workerKeysByProject.get(projectKey) === key) workerKeysByProject.delete(projectKey);
|
|
14880
|
+
}
|
|
14881
|
+
startHeartbeat() {
|
|
14882
|
+
if (this.heartbeatTimer) return;
|
|
14883
|
+
const heartbeat = () => {
|
|
14884
|
+
void this.heartbeat();
|
|
14885
|
+
};
|
|
14886
|
+
this.heartbeatTimer = setInterval(heartbeat, HEARTBEAT_INTERVAL_MS);
|
|
14887
|
+
this.heartbeatTimer.unref?.();
|
|
14888
|
+
}
|
|
14889
|
+
async heartbeat() {
|
|
14890
|
+
const lease = this.lease;
|
|
14891
|
+
if (!lease || this.losingLeadership || this.stopped && !this.stopping) return;
|
|
14892
|
+
if (hasActiveReclaimMarker(lease.leasePath, lease.owner)) {
|
|
14893
|
+
await this.loseLeadership();
|
|
14894
|
+
return;
|
|
14895
|
+
}
|
|
14896
|
+
const currentOwner = readOwner(lease.leasePath);
|
|
14897
|
+
if (!currentOwner || !sameOwner2(currentOwner, lease.owner)) {
|
|
14898
|
+
await this.loseLeadership();
|
|
14899
|
+
return;
|
|
14900
|
+
}
|
|
14901
|
+
try {
|
|
14902
|
+
const nextOwner = { ...lease.owner, heartbeatAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
14903
|
+
if (!writeHeartbeat(lease.leasePath, nextOwner)) {
|
|
14904
|
+
await this.loseLeadership();
|
|
14905
|
+
return;
|
|
14906
|
+
}
|
|
14907
|
+
lease.owner = nextOwner;
|
|
14908
|
+
const refreshRequest = !this.stopping ? consumeRefreshRequest(lease.leasePath) : null;
|
|
14909
|
+
if (refreshRequest) {
|
|
14910
|
+
this.hooks.startAutoIndex("retrieval", refreshRequest.allowDisabledAutoIndex);
|
|
14911
|
+
}
|
|
14912
|
+
} catch (error) {
|
|
14913
|
+
const ownerAfterError = readOwner(lease.leasePath);
|
|
14914
|
+
if (hasActiveReclaimMarker(lease.leasePath, lease.owner) || !ownerAfterError || !sameOwner2(ownerAfterError, lease.owner)) {
|
|
14915
|
+
await this.loseLeadership();
|
|
14916
|
+
return;
|
|
14917
|
+
}
|
|
14918
|
+
console.error("[codebase-index] Failed to renew background worker lease:", error);
|
|
14919
|
+
}
|
|
14920
|
+
}
|
|
14921
|
+
async loseLeadership() {
|
|
14922
|
+
if (this.losingLeadership) return;
|
|
14923
|
+
this.losingLeadership = true;
|
|
14924
|
+
this.clearHeartbeat();
|
|
14925
|
+
await this.enqueue(async () => this.stopAfterLeadershipLoss());
|
|
14926
|
+
}
|
|
14927
|
+
async stopAfterLeadershipLoss() {
|
|
14928
|
+
const lease = this.lease;
|
|
14929
|
+
if (!lease) {
|
|
14930
|
+
this.losingLeadership = false;
|
|
14931
|
+
return;
|
|
14932
|
+
}
|
|
14933
|
+
try {
|
|
14934
|
+
const stopped = await this.stopLeaderWork(true);
|
|
14935
|
+
this.lease = null;
|
|
14936
|
+
this.losingLeadership = false;
|
|
14937
|
+
if (stopped.completed) {
|
|
14938
|
+
this.scheduleRetry();
|
|
14939
|
+
} else {
|
|
14940
|
+
void stopped.completion.then(() => this.scheduleRetry());
|
|
14941
|
+
}
|
|
14942
|
+
} catch (error) {
|
|
14943
|
+
console.error("[codebase-index] Failed to stop background work after losing its lease:", error);
|
|
14944
|
+
this.scheduleLostLeadershipTeardownRetry();
|
|
14945
|
+
}
|
|
14946
|
+
}
|
|
14947
|
+
scheduleRetry() {
|
|
14948
|
+
if (this.stopped || !this.canRun() || this.retryTimer) return;
|
|
14949
|
+
this.retryTimer = setTimeout(() => {
|
|
14950
|
+
this.retryTimer = null;
|
|
14951
|
+
this.start();
|
|
14952
|
+
}, RETRY_DELAY_MS);
|
|
14953
|
+
this.retryTimer.unref?.();
|
|
14954
|
+
}
|
|
14955
|
+
scheduleTeardownRetry() {
|
|
14956
|
+
if (!this.stopping || this.teardownRetryTimer) return;
|
|
14957
|
+
this.teardownRetryTimer = setTimeout(() => {
|
|
14958
|
+
this.teardownRetryTimer = null;
|
|
14959
|
+
void this.stop(this.stopAutoIndexOnTeardown).catch((error) => {
|
|
14960
|
+
console.error("[codebase-index] Failed to retry background worker teardown:", error);
|
|
14961
|
+
});
|
|
14962
|
+
}, RETRY_DELAY_MS);
|
|
14963
|
+
this.teardownRetryTimer.unref?.();
|
|
14964
|
+
}
|
|
14965
|
+
restartAfterTeardown() {
|
|
14966
|
+
if (!this.restartAfterStop || !this.canRun() || this.losingLeadership) return;
|
|
14967
|
+
this.restartAfterStop = false;
|
|
14968
|
+
this.stopped = false;
|
|
14969
|
+
this.start();
|
|
14970
|
+
}
|
|
14971
|
+
scheduleLostLeadershipTeardownRetry() {
|
|
14972
|
+
if (this.stopped || !this.losingLeadership || this.retryTimer) return;
|
|
14973
|
+
this.retryTimer = setTimeout(() => {
|
|
14974
|
+
this.retryTimer = null;
|
|
14975
|
+
void this.enqueue(async () => this.stopAfterLeadershipLoss());
|
|
14976
|
+
}, RETRY_DELAY_MS);
|
|
14977
|
+
this.retryTimer.unref?.();
|
|
14978
|
+
}
|
|
14979
|
+
clearHeartbeat() {
|
|
14980
|
+
if (!this.heartbeatTimer) return;
|
|
14981
|
+
clearInterval(this.heartbeatTimer);
|
|
14982
|
+
this.heartbeatTimer = null;
|
|
14983
|
+
}
|
|
14984
|
+
clearTimers() {
|
|
14985
|
+
this.clearHeartbeat();
|
|
14986
|
+
this.clearRetryTimer();
|
|
14987
|
+
if (this.teardownRetryTimer) {
|
|
14988
|
+
clearTimeout(this.teardownRetryTimer);
|
|
14989
|
+
this.teardownRetryTimer = null;
|
|
14990
|
+
}
|
|
14991
|
+
}
|
|
14992
|
+
clearRetryTimer() {
|
|
14993
|
+
if (!this.retryTimer) return;
|
|
14994
|
+
clearTimeout(this.retryTimer);
|
|
14995
|
+
this.retryTimer = null;
|
|
14996
|
+
}
|
|
14997
|
+
reportAcquireError(error) {
|
|
14998
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
14999
|
+
if (this.reportedError === message) return;
|
|
15000
|
+
this.reportedError = message;
|
|
15001
|
+
console.error("[codebase-index] Failed to acquire background worker lease:", error);
|
|
15002
|
+
}
|
|
15003
|
+
};
|
|
15004
|
+
function configureBackgroundWorker(projectRoot, host, config, hooks, options = {}) {
|
|
15005
|
+
const projectKey = projectLookupKey(projectRoot, host);
|
|
15006
|
+
const identity = resolveIdentity(projectRoot, config, host);
|
|
15007
|
+
const key = controllerKey(identity, host);
|
|
15008
|
+
const previousKey = workerKeysByProject.get(projectKey);
|
|
15009
|
+
if (previousKey && previousKey !== key) {
|
|
15010
|
+
const previous = workers.get(previousKey);
|
|
15011
|
+
const previousBarrier = workerReplacementBarriers.get(projectKey) ?? Promise.resolve();
|
|
15012
|
+
const stopPrevious = previous?.stop(options.stopPreviousAutoIndex ?? true) ?? Promise.resolve();
|
|
15013
|
+
const activation = Promise.all([previousBarrier, stopPrevious]).then(() => void 0);
|
|
15014
|
+
workerReplacementBarriers.set(projectKey, activation);
|
|
15015
|
+
workers.delete(previousKey);
|
|
15016
|
+
const worker2 = new BackgroundWorkerController(projectRoot, host, config, hooks, identity);
|
|
15017
|
+
worker2.startAfter(activation);
|
|
15018
|
+
workers.set(key, worker2);
|
|
15019
|
+
workerKeysByProject.set(projectKey, key);
|
|
15020
|
+
return;
|
|
15021
|
+
}
|
|
15022
|
+
let worker = workers.get(key);
|
|
15023
|
+
if (!worker) {
|
|
15024
|
+
worker = new BackgroundWorkerController(projectRoot, host, config, hooks, identity);
|
|
15025
|
+
workers.set(key, worker);
|
|
15026
|
+
} else {
|
|
15027
|
+
worker.update(config, hooks, options);
|
|
15028
|
+
}
|
|
15029
|
+
workerKeysByProject.set(projectKey, key);
|
|
15030
|
+
worker.start();
|
|
15031
|
+
}
|
|
15032
|
+
function attachBackgroundWorkerWatcher(projectRoot, host, watcherFactory, watcherFactoryForConfig) {
|
|
15033
|
+
const key = workerKeysByProject.get(projectLookupKey(projectRoot, host));
|
|
15034
|
+
workers.get(key ?? "")?.attachWatcher(watcherFactory, watcherFactoryForConfig);
|
|
15035
|
+
}
|
|
15036
|
+
function updateBackgroundWorkerConfig(projectRoot, host, config) {
|
|
15037
|
+
const projectKey = projectLookupKey(projectRoot, host);
|
|
15038
|
+
const key = workerKeysByProject.get(projectKey);
|
|
15039
|
+
const worker = key ? workers.get(key) : void 0;
|
|
15040
|
+
if (!worker) return;
|
|
15041
|
+
configureBackgroundWorker(projectRoot, host, config, worker.getHooksForConfig(config), {
|
|
15042
|
+
stopPreviousAutoIndex: false,
|
|
15043
|
+
restartAutoIndex: true
|
|
15044
|
+
});
|
|
15045
|
+
}
|
|
15046
|
+
function requestBackgroundWorker(projectRoot, host) {
|
|
15047
|
+
const key = workerKeysByProject.get(projectLookupKey(projectRoot, host));
|
|
15048
|
+
workers.get(key ?? "")?.start();
|
|
15049
|
+
}
|
|
15050
|
+
function waitForBackgroundWorkerStart(projectRoot, host) {
|
|
15051
|
+
const key = workerKeysByProject.get(projectLookupKey(projectRoot, host));
|
|
15052
|
+
return workers.get(key ?? "")?.waitForStart() ?? Promise.resolve();
|
|
15053
|
+
}
|
|
15054
|
+
function requestBackgroundWorkerRefresh(projectRoot, host, allowDisabledAutoIndex = false) {
|
|
15055
|
+
const key = workerKeysByProject.get(projectLookupKey(projectRoot, host));
|
|
15056
|
+
workers.get(key ?? "")?.requestRefresh(allowDisabledAutoIndex);
|
|
15057
|
+
}
|
|
15058
|
+
function isBackgroundWorkerManaged(projectRoot, host) {
|
|
15059
|
+
const key = workerKeysByProject.get(projectLookupKey(projectRoot, host));
|
|
15060
|
+
return key !== void 0 && workers.has(key);
|
|
15061
|
+
}
|
|
15062
|
+
function isBackgroundWorkerLeader(projectRoot, host) {
|
|
15063
|
+
const key = workerKeysByProject.get(projectLookupKey(projectRoot, host));
|
|
15064
|
+
return key !== void 0 && workers.get(key)?.isLeader() === true;
|
|
15065
|
+
}
|
|
15066
|
+
function isBackgroundWorkerStopping(projectRoot, host) {
|
|
15067
|
+
const key = workerKeysByProject.get(projectLookupKey(projectRoot, host));
|
|
15068
|
+
return key !== void 0 && workers.get(key)?.isStopping() === true;
|
|
15069
|
+
}
|
|
15070
|
+
async function stopBackgroundWorker(projectRoot, host) {
|
|
15071
|
+
const projectKey = projectLookupKey(projectRoot, host);
|
|
15072
|
+
const key = workerKeysByProject.get(projectKey);
|
|
15073
|
+
const worker = key ? workers.get(key) : void 0;
|
|
15074
|
+
if (!worker) return;
|
|
15075
|
+
await worker.stop();
|
|
15076
|
+
}
|
|
15077
|
+
|
|
15078
|
+
// src/utils/power-source.ts
|
|
15079
|
+
var childProcess = __toESM(require("child_process"), 1);
|
|
15080
|
+
var POWER_SOURCE_RECHECK_DELAY_MS = 6e4;
|
|
15081
|
+
var PMSET_TIMEOUT_MS = 5e3;
|
|
15082
|
+
function getErrorMessage4(error) {
|
|
15083
|
+
return error instanceof Error ? error.message : String(error);
|
|
15084
|
+
}
|
|
15085
|
+
function runCommand(file, args, options) {
|
|
15086
|
+
return new Promise((resolve21, reject) => {
|
|
15087
|
+
childProcess.execFile(
|
|
15088
|
+
file,
|
|
15089
|
+
args,
|
|
15090
|
+
{ encoding: "utf8", timeout: options.timeoutMs },
|
|
15091
|
+
(error, stdout) => {
|
|
15092
|
+
if (error) {
|
|
15093
|
+
reject(error);
|
|
15094
|
+
return;
|
|
15095
|
+
}
|
|
15096
|
+
resolve21(stdout);
|
|
15097
|
+
}
|
|
15098
|
+
);
|
|
15099
|
+
});
|
|
15100
|
+
}
|
|
15101
|
+
function parseMacOsPowerSource(output) {
|
|
15102
|
+
const match = output.match(/Now drawing from '([^']+)'/i);
|
|
15103
|
+
if (!match) {
|
|
15104
|
+
return "unknown";
|
|
15105
|
+
}
|
|
15106
|
+
const source = match[1].toLowerCase();
|
|
15107
|
+
if (source === "battery power") {
|
|
15108
|
+
return "battery";
|
|
15109
|
+
}
|
|
15110
|
+
if (source === "ac power") {
|
|
15111
|
+
return "ac";
|
|
15112
|
+
}
|
|
15113
|
+
return "unknown";
|
|
15114
|
+
}
|
|
15115
|
+
async function readMacOsPowerSource(commandRunner = runCommand) {
|
|
15116
|
+
const output = await commandRunner(
|
|
15117
|
+
"/usr/bin/pmset",
|
|
15118
|
+
["-g", "batt"],
|
|
15119
|
+
{ timeoutMs: PMSET_TIMEOUT_MS }
|
|
15120
|
+
);
|
|
15121
|
+
return parseMacOsPowerSource(output);
|
|
15122
|
+
}
|
|
15123
|
+
var MacOsBackgroundIndexingPolicy = class {
|
|
15124
|
+
constructor(readPowerSource, recheckDelayMs) {
|
|
15125
|
+
this.readPowerSource = readPowerSource;
|
|
15126
|
+
this.recheckDelayMs = recheckDelayMs;
|
|
15127
|
+
}
|
|
15128
|
+
readPowerSource;
|
|
15129
|
+
recheckDelayMs;
|
|
15130
|
+
lastPaused = null;
|
|
15131
|
+
reportedFailure = false;
|
|
15132
|
+
isPaused() {
|
|
15133
|
+
return this.checkPowerSource();
|
|
15134
|
+
}
|
|
15135
|
+
async checkPowerSource() {
|
|
15136
|
+
try {
|
|
15137
|
+
const source = await this.readPowerSource();
|
|
15138
|
+
if (source === "unknown") {
|
|
15139
|
+
throw new Error("pmset returned an unrecognized power source");
|
|
15140
|
+
}
|
|
15141
|
+
this.reportedFailure = false;
|
|
15142
|
+
const paused = source === "battery";
|
|
15143
|
+
if (paused && this.lastPaused !== true) {
|
|
15144
|
+
console.warn("[codebase-index] Background indexing paused while macOS is using battery power.");
|
|
15145
|
+
} else if (!paused && this.lastPaused === true) {
|
|
15146
|
+
console.warn("[codebase-index] AC power detected; resuming pending background indexing.");
|
|
15147
|
+
}
|
|
15148
|
+
this.lastPaused = paused;
|
|
15149
|
+
return paused;
|
|
15150
|
+
} catch (error) {
|
|
15151
|
+
if (!this.reportedFailure) {
|
|
15152
|
+
console.error(
|
|
15153
|
+
`[codebase-index] Failed to determine the macOS power source; background indexing will continue: ${getErrorMessage4(error)}`
|
|
15154
|
+
);
|
|
15155
|
+
this.reportedFailure = true;
|
|
15156
|
+
}
|
|
15157
|
+
this.lastPaused = false;
|
|
15158
|
+
return false;
|
|
15159
|
+
}
|
|
15160
|
+
}
|
|
15161
|
+
};
|
|
15162
|
+
function createBackgroundIndexingPolicy(pauseOnBattery, options = {}) {
|
|
15163
|
+
const platform2 = options.platform ?? process.platform;
|
|
15164
|
+
if (!pauseOnBattery || platform2 !== "darwin") {
|
|
15165
|
+
return null;
|
|
15166
|
+
}
|
|
15167
|
+
return new MacOsBackgroundIndexingPolicy(
|
|
15168
|
+
options.readPowerSource ?? readMacOsPowerSource,
|
|
15169
|
+
options.recheckDelayMs ?? POWER_SOURCE_RECHECK_DELAY_MS
|
|
15170
|
+
);
|
|
15171
|
+
}
|
|
15172
|
+
|
|
15173
|
+
// src/utils/auto-index.ts
|
|
15174
|
+
var MAX_RETRY_DELAY_MS = 1e4;
|
|
15175
|
+
var SHUTDOWN_WAIT_MS = 2e3;
|
|
15176
|
+
var coordinators = /* @__PURE__ */ new Map();
|
|
15177
|
+
var coordinatorKeysByProject = /* @__PURE__ */ new Map();
|
|
15178
|
+
var coordinatorReplacementBarriers = /* @__PURE__ */ new Map();
|
|
15179
|
+
var AutoIndexCancelledError = class extends Error {
|
|
15180
|
+
constructor() {
|
|
15181
|
+
super("Auto-index coordination was cancelled");
|
|
15182
|
+
this.name = "AutoIndexCancelledError";
|
|
15183
|
+
}
|
|
15184
|
+
};
|
|
15185
|
+
function now() {
|
|
15186
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
15187
|
+
}
|
|
15188
|
+
function canonicalizePath2(targetPath) {
|
|
15189
|
+
const resolved = path18.resolve(targetPath);
|
|
15190
|
+
if ((0, import_fs11.existsSync)(resolved)) {
|
|
15191
|
+
try {
|
|
15192
|
+
return import_fs11.realpathSync.native(resolved);
|
|
15193
|
+
} catch {
|
|
15194
|
+
return resolved;
|
|
15195
|
+
}
|
|
15196
|
+
}
|
|
15197
|
+
const parent = path18.dirname(resolved);
|
|
15198
|
+
if (parent === resolved) return resolved;
|
|
15199
|
+
return path18.join(canonicalizePath2(parent), path18.basename(resolved));
|
|
15200
|
+
}
|
|
15201
|
+
function isHomeDirectory(projectRoot) {
|
|
15202
|
+
return canonicalizePath2(projectRoot) === canonicalizePath2(os7.homedir());
|
|
15203
|
+
}
|
|
15204
|
+
function projectLookupKey2(projectRoot, host) {
|
|
15205
|
+
return `${host}::${canonicalizePath2(projectRoot)}`;
|
|
15206
|
+
}
|
|
15207
|
+
function coordinatorKey(projectRoot, config, host) {
|
|
15208
|
+
const canonicalProjectRoot = canonicalizePath2(projectRoot);
|
|
15209
|
+
const indexPath = resolveProjectIndexPath(projectRoot, config.scope, host);
|
|
15210
|
+
return `${canonicalizePath2(indexPath)}::${canonicalProjectRoot}`;
|
|
15211
|
+
}
|
|
15212
|
+
function getProjectSafety(projectRoot, config) {
|
|
15213
|
+
if (isHomeDirectory(projectRoot)) {
|
|
15214
|
+
return { safeToRun: false, blockedReason: "home-directory" };
|
|
15215
|
+
}
|
|
15216
|
+
if (config.indexing.requireProjectMarker && !hasProjectMarker(projectRoot)) {
|
|
15217
|
+
return { safeToRun: false, blockedReason: "project-marker-missing" };
|
|
15218
|
+
}
|
|
15219
|
+
return { safeToRun: true };
|
|
15220
|
+
}
|
|
15221
|
+
function calculatePercentage2(progress) {
|
|
15222
|
+
if (progress.phase === "scanning") return 0;
|
|
15223
|
+
if (progress.phase === "complete") return 100;
|
|
15224
|
+
if (progress.phase === "parsing") {
|
|
15225
|
+
return progress.totalFiles === 0 ? 5 : Math.round(5 + progress.filesProcessed / progress.totalFiles * 15);
|
|
15226
|
+
}
|
|
15227
|
+
if (progress.phase === "embedding") {
|
|
15228
|
+
return progress.totalChunks === 0 ? 20 : Math.round(20 + progress.chunksProcessed / progress.totalChunks * 70);
|
|
15229
|
+
}
|
|
15230
|
+
if (progress.phase === "storing") return 95;
|
|
15231
|
+
return 0;
|
|
15232
|
+
}
|
|
15233
|
+
function safeFailureMessage(error) {
|
|
15234
|
+
if (isTransientIndexLockContention(error)) {
|
|
15235
|
+
return "Another index process remained busy after the configured retries.";
|
|
15236
|
+
}
|
|
15237
|
+
return "Automatic indexing failed. Check the embedding provider configuration, then run index_codebase.";
|
|
15238
|
+
}
|
|
15239
|
+
function cancellableDelay(delayMs, signal) {
|
|
15240
|
+
if (signal.aborted) return Promise.reject(new AutoIndexCancelledError());
|
|
15241
|
+
return new Promise((resolve21, reject) => {
|
|
15242
|
+
const timer = setTimeout(() => {
|
|
14240
15243
|
signal.removeEventListener("abort", onAbort);
|
|
14241
|
-
|
|
15244
|
+
resolve21();
|
|
14242
15245
|
}, delayMs);
|
|
14243
15246
|
timer.unref?.();
|
|
14244
15247
|
const onAbort = () => {
|
|
@@ -14250,18 +15253,44 @@ function cancellableDelay(delayMs, signal) {
|
|
|
14250
15253
|
}
|
|
14251
15254
|
function withTimeout(promise, timeoutMs) {
|
|
14252
15255
|
if (timeoutMs <= 0) return Promise.resolve(void 0);
|
|
14253
|
-
return new Promise((
|
|
14254
|
-
const timer = setTimeout(() =>
|
|
15256
|
+
return new Promise((resolve21) => {
|
|
15257
|
+
const timer = setTimeout(() => resolve21(void 0), timeoutMs);
|
|
14255
15258
|
timer.unref?.();
|
|
14256
15259
|
void promise.then((value) => {
|
|
14257
15260
|
clearTimeout(timer);
|
|
14258
|
-
|
|
15261
|
+
resolve21(value);
|
|
14259
15262
|
}, () => {
|
|
14260
15263
|
clearTimeout(timer);
|
|
14261
|
-
|
|
15264
|
+
resolve21(void 0);
|
|
14262
15265
|
});
|
|
14263
15266
|
});
|
|
14264
15267
|
}
|
|
15268
|
+
function settlesWithin(promise, timeoutMs) {
|
|
15269
|
+
if (timeoutMs <= 0) return Promise.resolve(false);
|
|
15270
|
+
return new Promise((resolve21) => {
|
|
15271
|
+
let settled = false;
|
|
15272
|
+
const timer = setTimeout(() => {
|
|
15273
|
+
if (settled) return;
|
|
15274
|
+
settled = true;
|
|
15275
|
+
resolve21(false);
|
|
15276
|
+
}, timeoutMs);
|
|
15277
|
+
timer.unref?.();
|
|
15278
|
+
void promise.then(
|
|
15279
|
+
() => {
|
|
15280
|
+
if (settled) return;
|
|
15281
|
+
settled = true;
|
|
15282
|
+
clearTimeout(timer);
|
|
15283
|
+
resolve21(true);
|
|
15284
|
+
},
|
|
15285
|
+
() => {
|
|
15286
|
+
if (settled) return;
|
|
15287
|
+
settled = true;
|
|
15288
|
+
clearTimeout(timer);
|
|
15289
|
+
resolve21(true);
|
|
15290
|
+
}
|
|
15291
|
+
);
|
|
15292
|
+
});
|
|
15293
|
+
}
|
|
14265
15294
|
function requestPriority(request) {
|
|
14266
15295
|
if (request.force) return 4;
|
|
14267
15296
|
if (request.source === "manual") return 3;
|
|
@@ -14272,6 +15301,7 @@ function mergeRequests(current, next) {
|
|
|
14272
15301
|
if (!current) return next;
|
|
14273
15302
|
const preferred = requestPriority(next) > requestPriority(current) ? next : current;
|
|
14274
15303
|
return {
|
|
15304
|
+
allowDisabledAutoIndex: current.allowDisabledAutoIndex || next.allowDisabledAutoIndex,
|
|
14275
15305
|
checkFreshness: current.checkFreshness && next.checkFreshness,
|
|
14276
15306
|
force: current.force || next.force,
|
|
14277
15307
|
onProgress: next.onProgress ?? current.onProgress,
|
|
@@ -14333,11 +15363,11 @@ var AutoIndexCoordinator = class {
|
|
|
14333
15363
|
progress: this.status.progress ? { ...this.status.progress } : void 0
|
|
14334
15364
|
};
|
|
14335
15365
|
}
|
|
14336
|
-
start(source) {
|
|
15366
|
+
start(source, allowDisabledAutoIndex = false) {
|
|
14337
15367
|
this.refreshSafety();
|
|
14338
|
-
if (!this.registration.config.indexing.autoIndex || !this.registration.safeToRun) return null;
|
|
15368
|
+
if (!this.registration.config.indexing.autoIndex && !allowDisabledAutoIndex || !this.registration.safeToRun) return null;
|
|
14339
15369
|
if (this.status.state === "failed") return this.inFlight;
|
|
14340
|
-
return this.request({ checkFreshness: true, force: false, source });
|
|
15370
|
+
return this.request({ allowDisabledAutoIndex, checkFreshness: true, force: false, source });
|
|
14341
15371
|
}
|
|
14342
15372
|
request(request) {
|
|
14343
15373
|
if (this.stopped) {
|
|
@@ -14412,13 +15442,15 @@ var AutoIndexCoordinator = class {
|
|
|
14412
15442
|
retryAttempt: void 0
|
|
14413
15443
|
});
|
|
14414
15444
|
const inFlight = this.inFlight;
|
|
14415
|
-
|
|
14416
|
-
|
|
14417
|
-
|
|
14418
|
-
|
|
14419
|
-
|
|
14420
|
-
|
|
15445
|
+
const completion = inFlight ? inFlight.then(() => void 0, () => void 0) : Promise.resolve();
|
|
15446
|
+
if (!inFlight) {
|
|
15447
|
+
return { completed: true, completion };
|
|
15448
|
+
}
|
|
15449
|
+
if (waitForCompletion) {
|
|
15450
|
+
await completion;
|
|
15451
|
+
return { completed: true, completion };
|
|
14421
15452
|
}
|
|
15453
|
+
return { completed: await settlesWithin(completion, SHUTDOWN_WAIT_MS), completion };
|
|
14422
15454
|
}
|
|
14423
15455
|
startRequest(request) {
|
|
14424
15456
|
if (this.stopped || !this.canRun(request)) {
|
|
@@ -14607,7 +15639,7 @@ var AutoIndexCoordinator = class {
|
|
|
14607
15639
|
if (request.source === "manual" || request.source === "watcher") {
|
|
14608
15640
|
return true;
|
|
14609
15641
|
}
|
|
14610
|
-
return this.registration.safeToRun && this.registration.config.indexing.autoIndex;
|
|
15642
|
+
return this.registration.safeToRun && (this.registration.config.indexing.autoIndex || request.allowDisabledAutoIndex === true);
|
|
14611
15643
|
}
|
|
14612
15644
|
shouldDeferForBattery(request) {
|
|
14613
15645
|
return this.registration.backgroundIndexingPolicy !== null && (request.source === "startup" || request.source === "watcher");
|
|
@@ -14640,17 +15672,17 @@ var AutoIndexCoordinator = class {
|
|
|
14640
15672
|
}
|
|
14641
15673
|
}
|
|
14642
15674
|
waitForBatteryRetry(delayMs) {
|
|
14643
|
-
return new Promise((
|
|
15675
|
+
return new Promise((resolve21) => {
|
|
14644
15676
|
const timer = setTimeout(() => {
|
|
14645
15677
|
if (this.batteryRetryTimer === timer) {
|
|
14646
15678
|
this.batteryRetryTimer = null;
|
|
14647
15679
|
this.resolveBatteryRetry = null;
|
|
14648
15680
|
}
|
|
14649
|
-
|
|
15681
|
+
resolve21();
|
|
14650
15682
|
}, delayMs);
|
|
14651
15683
|
timer.unref?.();
|
|
14652
15684
|
this.batteryRetryTimer = timer;
|
|
14653
|
-
this.resolveBatteryRetry =
|
|
15685
|
+
this.resolveBatteryRetry = resolve21;
|
|
14654
15686
|
});
|
|
14655
15687
|
}
|
|
14656
15688
|
cancelBatteryRetry() {
|
|
@@ -14658,9 +15690,9 @@ var AutoIndexCoordinator = class {
|
|
|
14658
15690
|
clearTimeout(this.batteryRetryTimer);
|
|
14659
15691
|
this.batteryRetryTimer = null;
|
|
14660
15692
|
}
|
|
14661
|
-
const
|
|
15693
|
+
const resolve21 = this.resolveBatteryRetry;
|
|
14662
15694
|
this.resolveBatteryRetry = null;
|
|
14663
|
-
|
|
15695
|
+
resolve21?.();
|
|
14664
15696
|
}
|
|
14665
15697
|
finishBatteryCheck(batteryCheck) {
|
|
14666
15698
|
if (this.batteryCheck !== batteryCheck) return;
|
|
@@ -14673,12 +15705,25 @@ var AutoIndexCoordinator = class {
|
|
|
14673
15705
|
}
|
|
14674
15706
|
};
|
|
14675
15707
|
function getCoordinator(projectRoot, host) {
|
|
14676
|
-
const key = coordinatorKeysByProject.get(
|
|
15708
|
+
const key = coordinatorKeysByProject.get(projectLookupKey2(projectRoot, host));
|
|
14677
15709
|
return key ? coordinators.get(key) ?? null : null;
|
|
14678
15710
|
}
|
|
14679
|
-
function
|
|
14680
|
-
|
|
15711
|
+
function synchronizeBackgroundWorker(projectRoot, host, config, safeToRun) {
|
|
15712
|
+
if (safeToRun) {
|
|
15713
|
+
updateBackgroundWorkerConfig(projectRoot, host, config);
|
|
15714
|
+
return;
|
|
15715
|
+
}
|
|
15716
|
+
void stopBackgroundWorker(projectRoot, host).catch((error) => {
|
|
15717
|
+
console.error("[codebase-index] Failed to stop background worker after project safety changed:", error);
|
|
15718
|
+
});
|
|
15719
|
+
}
|
|
15720
|
+
function configureAutoIndex(projectRoot, host, config, getIndexer, options = {}) {
|
|
15721
|
+
const projectKey = projectLookupKey2(projectRoot, host);
|
|
14681
15722
|
const safety = getProjectSafety(projectRoot, config);
|
|
15723
|
+
const synchronizeWorker = options.synchronizeBackgroundWorker ?? true;
|
|
15724
|
+
if (options.preserveManagedWorker === true && isBackgroundWorkerManaged(projectRoot, host)) {
|
|
15725
|
+
return;
|
|
15726
|
+
}
|
|
14682
15727
|
const registration = {
|
|
14683
15728
|
backgroundIndexingPolicy: createBackgroundIndexingPolicy(
|
|
14684
15729
|
config.indexing.pauseBackgroundIndexingOnBattery
|
|
@@ -14696,6 +15741,9 @@ function configureAutoIndex(projectRoot, host, config, getIndexer) {
|
|
|
14696
15741
|
const stopPrevious = previousCoordinator?.stop(true) ?? Promise.resolve();
|
|
14697
15742
|
const activation = Promise.all([previousBarrier, stopPrevious]).then(() => void 0);
|
|
14698
15743
|
coordinatorReplacementBarriers.set(projectKey, activation);
|
|
15744
|
+
if (synchronizeWorker) {
|
|
15745
|
+
synchronizeBackgroundWorker(projectRoot, host, config, safety.safeToRun);
|
|
15746
|
+
}
|
|
14699
15747
|
coordinators.delete(previousKey);
|
|
14700
15748
|
const coordinator2 = new AutoIndexCoordinator(registration);
|
|
14701
15749
|
coordinator2.activateAfter(activation);
|
|
@@ -14711,11 +15759,17 @@ function configureAutoIndex(projectRoot, host, config, getIndexer) {
|
|
|
14711
15759
|
coordinator.update(registration);
|
|
14712
15760
|
}
|
|
14713
15761
|
coordinatorKeysByProject.set(projectKey, key);
|
|
15762
|
+
if (synchronizeWorker) {
|
|
15763
|
+
synchronizeBackgroundWorker(projectRoot, host, config, safety.safeToRun);
|
|
15764
|
+
}
|
|
14714
15765
|
}
|
|
14715
|
-
function
|
|
14716
|
-
return getCoordinator(projectRoot, host)?.start(source) ?? null;
|
|
15766
|
+
function startAutoIndexForBackgroundWorker(projectRoot, host, source = "startup", allowDisabledAutoIndex = false) {
|
|
15767
|
+
return getCoordinator(projectRoot, host)?.start(source, allowDisabledAutoIndex) ?? null;
|
|
14717
15768
|
}
|
|
14718
15769
|
function requestBackgroundIndex(projectRoot, host) {
|
|
15770
|
+
if (isBackgroundWorkerManaged(projectRoot, host) && !isBackgroundWorkerLeader(projectRoot, host)) {
|
|
15771
|
+
return null;
|
|
15772
|
+
}
|
|
14719
15773
|
return getCoordinator(projectRoot, host)?.request({
|
|
14720
15774
|
checkFreshness: false,
|
|
14721
15775
|
force: false,
|
|
@@ -14755,15 +15809,23 @@ async function waitForAutoIndexForRetrieval(projectRoot, host) {
|
|
|
14755
15809
|
};
|
|
14756
15810
|
}
|
|
14757
15811
|
try {
|
|
14758
|
-
|
|
15812
|
+
const readiness = await getSearchReadiness(coordinator);
|
|
15813
|
+
if (readiness.searchable) {
|
|
15814
|
+
return { ready: true };
|
|
15815
|
+
}
|
|
15816
|
+
if (readiness.blocked) return unavailableSnapshotResult(readiness.reason);
|
|
14759
15817
|
} catch {
|
|
14760
15818
|
}
|
|
14761
|
-
const job =
|
|
15819
|
+
const job = startRetrievalRefresh(projectRoot, host, coordinator);
|
|
14762
15820
|
if (job) {
|
|
14763
15821
|
await withTimeout(job, coordinator.getWaitMs());
|
|
15822
|
+
} else if (isBackgroundWorkerManaged(projectRoot, host)) {
|
|
15823
|
+
await waitForPublishedSnapshot(coordinator, coordinator.getWaitMs());
|
|
14764
15824
|
}
|
|
14765
15825
|
try {
|
|
14766
|
-
|
|
15826
|
+
const readiness = await getSearchReadiness(coordinator);
|
|
15827
|
+
if (readiness.searchable) return { ready: true };
|
|
15828
|
+
if (readiness.blocked) return unavailableSnapshotResult(readiness.reason);
|
|
14767
15829
|
} catch {
|
|
14768
15830
|
}
|
|
14769
15831
|
const status = coordinator.snapshot();
|
|
@@ -14784,31 +15846,62 @@ async function waitForAutoIndexForRetrieval(projectRoot, host) {
|
|
|
14784
15846
|
text: `Automatic indexing is ${status.state}. Retry shortly or call index_status for progress. You can also run index_codebase explicitly.`
|
|
14785
15847
|
};
|
|
14786
15848
|
}
|
|
14787
|
-
async function
|
|
14788
|
-
|
|
15849
|
+
async function stopAutoIndexForBackgroundWorker(projectRoot, host, waitForCompletion = false) {
|
|
15850
|
+
const coordinator = getCoordinator(projectRoot, host);
|
|
15851
|
+
if (!coordinator) {
|
|
15852
|
+
return { completed: true, completion: Promise.resolve() };
|
|
15853
|
+
}
|
|
15854
|
+
return coordinator.stop(waitForCompletion);
|
|
14789
15855
|
}
|
|
14790
|
-
async function
|
|
15856
|
+
async function getSearchReadiness(coordinator) {
|
|
14791
15857
|
const indexer = coordinator.getIndexer();
|
|
14792
15858
|
if (indexer.getIndexFreshness) {
|
|
14793
15859
|
const freshness = await indexer.getIndexFreshness();
|
|
14794
|
-
|
|
15860
|
+
const searchable = freshness.readable && freshness.current && freshness.reason === "current";
|
|
15861
|
+
return {
|
|
15862
|
+
blocked: freshness.reason === "unreadable" || freshness.reason === "incompatible" || freshness.reason === "failed-batches" || freshness.reason === "migration-required",
|
|
15863
|
+
reason: freshness.reason,
|
|
15864
|
+
searchable
|
|
15865
|
+
};
|
|
15866
|
+
}
|
|
15867
|
+
const indexed = (await indexer.getStatus()).indexed;
|
|
15868
|
+
return { blocked: false, searchable: indexed };
|
|
15869
|
+
}
|
|
15870
|
+
function unavailableSnapshotResult(reason) {
|
|
15871
|
+
const detail = reason === "incompatible" ? "The existing index is incompatible with the configured embedding provider." : reason === "migration-required" ? "The existing index requires a storage migration." : reason === "failed-batches" ? "The existing index has failed embedding batches." : "The existing index is unreadable.";
|
|
15872
|
+
return {
|
|
15873
|
+
ready: false,
|
|
15874
|
+
text: `${detail} Run index_codebase before retrying retrieval.`
|
|
15875
|
+
};
|
|
15876
|
+
}
|
|
15877
|
+
function startRetrievalRefresh(projectRoot, host, coordinator) {
|
|
15878
|
+
if (isBackgroundWorkerManaged(projectRoot, host)) {
|
|
15879
|
+
requestBackgroundWorkerRefresh(projectRoot, host, true);
|
|
15880
|
+
return isBackgroundWorkerLeader(projectRoot, host) ? coordinator.currentJob() : null;
|
|
15881
|
+
}
|
|
15882
|
+
return coordinator.start("retrieval") ?? coordinator.currentJob();
|
|
15883
|
+
}
|
|
15884
|
+
async function waitForPublishedSnapshot(coordinator, waitMs) {
|
|
15885
|
+
const deadline = Date.now() + waitMs;
|
|
15886
|
+
while (Date.now() < deadline) {
|
|
15887
|
+
if ((await getSearchReadiness(coordinator)).searchable) return;
|
|
15888
|
+
await new Promise((resolve21) => setTimeout(resolve21, Math.min(250, deadline - Date.now())));
|
|
14795
15889
|
}
|
|
14796
|
-
return (await indexer.getStatus()).indexed;
|
|
14797
15890
|
}
|
|
14798
15891
|
|
|
14799
15892
|
// src/tools/config-state.ts
|
|
14800
15893
|
var import_fs13 = require("fs");
|
|
14801
|
-
var
|
|
15894
|
+
var path21 = __toESM(require("path"), 1);
|
|
14802
15895
|
|
|
14803
15896
|
// src/config/merger.ts
|
|
14804
15897
|
var import_fs12 = require("fs");
|
|
14805
|
-
var
|
|
15898
|
+
var path20 = __toESM(require("path"), 1);
|
|
14806
15899
|
|
|
14807
15900
|
// src/config/rebase.ts
|
|
14808
|
-
var
|
|
15901
|
+
var path19 = __toESM(require("path"), 1);
|
|
14809
15902
|
function isWithinRoot(rootDir, targetPath) {
|
|
14810
|
-
const relativePath =
|
|
14811
|
-
return relativePath === "" || !relativePath.startsWith("..") && !
|
|
15903
|
+
const relativePath = path19.relative(rootDir, targetPath);
|
|
15904
|
+
return relativePath === "" || !relativePath.startsWith("..") && !path19.isAbsolute(relativePath);
|
|
14812
15905
|
}
|
|
14813
15906
|
function rebasePathEntries(values, fromDir, toDir) {
|
|
14814
15907
|
if (!Array.isArray(values)) {
|
|
@@ -14816,10 +15909,10 @@ function rebasePathEntries(values, fromDir, toDir) {
|
|
|
14816
15909
|
}
|
|
14817
15910
|
return values.filter((value) => typeof value === "string").map((value) => {
|
|
14818
15911
|
const trimmed = value.trim();
|
|
14819
|
-
if (!trimmed ||
|
|
15912
|
+
if (!trimmed || path19.isAbsolute(trimmed)) {
|
|
14820
15913
|
return trimmed;
|
|
14821
15914
|
}
|
|
14822
|
-
return normalizePathSeparators(
|
|
15915
|
+
return normalizePathSeparators(path19.normalize(path19.relative(toDir, path19.resolve(fromDir, trimmed))));
|
|
14823
15916
|
}).filter(Boolean);
|
|
14824
15917
|
}
|
|
14825
15918
|
function resolveInheritedKnowledgeBaseEntries(values, sourceRoot, targetRoot) {
|
|
@@ -14831,17 +15924,17 @@ function resolveInheritedKnowledgeBaseEntries(values, sourceRoot, targetRoot) {
|
|
|
14831
15924
|
if (!trimmed) {
|
|
14832
15925
|
return trimmed;
|
|
14833
15926
|
}
|
|
14834
|
-
if (
|
|
15927
|
+
if (path19.isAbsolute(trimmed)) {
|
|
14835
15928
|
if (isWithinRoot(sourceRoot, trimmed)) {
|
|
14836
|
-
return normalizePathSeparators(
|
|
15929
|
+
return normalizePathSeparators(path19.normalize(path19.relative(sourceRoot, trimmed) || "."));
|
|
14837
15930
|
}
|
|
14838
|
-
return
|
|
15931
|
+
return path19.normalize(trimmed);
|
|
14839
15932
|
}
|
|
14840
|
-
const resolvedFromSource =
|
|
15933
|
+
const resolvedFromSource = path19.resolve(sourceRoot, trimmed);
|
|
14841
15934
|
if (isWithinRoot(sourceRoot, resolvedFromSource)) {
|
|
14842
|
-
return normalizePathSeparators(
|
|
15935
|
+
return normalizePathSeparators(path19.normalize(trimmed));
|
|
14843
15936
|
}
|
|
14844
|
-
return normalizePathSeparators(
|
|
15937
|
+
return normalizePathSeparators(path19.normalize(path19.relative(targetRoot, resolvedFromSource)));
|
|
14845
15938
|
}).filter(Boolean);
|
|
14846
15939
|
}
|
|
14847
15940
|
|
|
@@ -14879,8 +15972,8 @@ function mergeUniqueStringArray(values) {
|
|
|
14879
15972
|
return [...new Set(values.map((value) => String(value).trim()))];
|
|
14880
15973
|
}
|
|
14881
15974
|
function normalizeKnowledgeBasePath2(value) {
|
|
14882
|
-
let normalized =
|
|
14883
|
-
const root =
|
|
15975
|
+
let normalized = path20.normalize(String(value).trim());
|
|
15976
|
+
const root = path20.parse(normalized).root;
|
|
14884
15977
|
while (normalized.length > root.length && /[\\/]$/.test(normalized)) {
|
|
14885
15978
|
normalized = normalized.slice(0, -1);
|
|
14886
15979
|
}
|
|
@@ -14938,7 +16031,7 @@ function loadProjectConfigLayer(projectRoot, host) {
|
|
|
14938
16031
|
return {};
|
|
14939
16032
|
}
|
|
14940
16033
|
const normalizedConfig = { ...projectConfig };
|
|
14941
|
-
const projectConfigBaseDir =
|
|
16034
|
+
const projectConfigBaseDir = path20.dirname(path20.dirname(projectConfigPath));
|
|
14942
16035
|
if (Array.isArray(normalizedConfig.knowledgeBases)) {
|
|
14943
16036
|
normalizedConfig.knowledgeBases = resolveInheritedKnowledgeBaseEntries(
|
|
14944
16037
|
normalizedConfig.knowledgeBases,
|
|
@@ -15028,8 +16121,8 @@ function loadEditableConfig(projectRoot, host) {
|
|
|
15028
16121
|
}
|
|
15029
16122
|
function saveConfig(projectRoot, config, host) {
|
|
15030
16123
|
const configPath = getConfigPath(projectRoot, host);
|
|
15031
|
-
const configDir =
|
|
15032
|
-
const configBaseDir =
|
|
16124
|
+
const configDir = path21.dirname(configPath);
|
|
16125
|
+
const configBaseDir = path21.dirname(configDir);
|
|
15033
16126
|
if (!(0, import_fs13.existsSync)(configDir)) {
|
|
15034
16127
|
(0, import_fs13.mkdirSync)(configDir, { recursive: true });
|
|
15035
16128
|
}
|
|
@@ -15118,15 +16211,24 @@ function getOrCreateIndexer(projectRoot, host) {
|
|
|
15118
16211
|
}
|
|
15119
16212
|
const indexer = new Indexer(projectRoot, config, host);
|
|
15120
16213
|
indexerCache.set(key, indexer);
|
|
15121
|
-
configureAutoIndex(projectRoot, host, config, () => getOrCreateIndexer(projectRoot, host)
|
|
16214
|
+
configureAutoIndex(projectRoot, host, config, () => getOrCreateIndexer(projectRoot, host), {
|
|
16215
|
+
preserveManagedWorker: true,
|
|
16216
|
+
synchronizeBackgroundWorker: false
|
|
16217
|
+
});
|
|
15122
16218
|
return indexer;
|
|
15123
16219
|
}
|
|
15124
|
-
function initializeTools(projectRoot, config, host) {
|
|
16220
|
+
function initializeTools(projectRoot, config, host, options = {}) {
|
|
15125
16221
|
defaultProjectRoots.set(host, projectRoot);
|
|
15126
16222
|
const key = getIndexerCacheKey(projectRoot, host);
|
|
16223
|
+
if (options.preserveManagedWorker === true && isBackgroundWorkerManaged(projectRoot, host) && indexerCache.has(key)) {
|
|
16224
|
+
return;
|
|
16225
|
+
}
|
|
15127
16226
|
configCache.set(key, config);
|
|
15128
16227
|
indexerCache.set(key, new Indexer(projectRoot, config, host));
|
|
15129
|
-
configureAutoIndex(projectRoot, host, config, () => getOrCreateIndexer(projectRoot, host)
|
|
16228
|
+
configureAutoIndex(projectRoot, host, config, () => getOrCreateIndexer(projectRoot, host), {
|
|
16229
|
+
preserveManagedWorker: options.preserveManagedWorker,
|
|
16230
|
+
synchronizeBackgroundWorker: false
|
|
16231
|
+
});
|
|
15130
16232
|
}
|
|
15131
16233
|
function getIndexerForProject(projectRoot, host) {
|
|
15132
16234
|
const root = getProjectRoot(projectRoot, host);
|
|
@@ -15140,7 +16242,9 @@ function refreshIndexerForDirectory(projectRoot, host, config = parseConfig(load
|
|
|
15140
16242
|
const key = getIndexerCacheKey(projectRoot, host);
|
|
15141
16243
|
configCache.set(key, config);
|
|
15142
16244
|
indexerCache.set(key, new Indexer(projectRoot, config, host));
|
|
15143
|
-
configureAutoIndex(projectRoot, host, config, () => getOrCreateIndexer(projectRoot, host)
|
|
16245
|
+
configureAutoIndex(projectRoot, host, config, () => getOrCreateIndexer(projectRoot, host), {
|
|
16246
|
+
synchronizeBackgroundWorker: true
|
|
16247
|
+
});
|
|
15144
16248
|
return config;
|
|
15145
16249
|
}
|
|
15146
16250
|
var AutoIndexRetrievalUnavailableError = class extends Error {
|
|
@@ -15167,7 +16271,7 @@ function trimOrUndefined(value) {
|
|
|
15167
16271
|
return normalized || void 0;
|
|
15168
16272
|
}
|
|
15169
16273
|
function normalizeCallGraphPath(value) {
|
|
15170
|
-
let normalized =
|
|
16274
|
+
let normalized = path22.posix.normalize(value.trim().replaceAll("\\", "/"));
|
|
15171
16275
|
if (normalized.startsWith("./")) {
|
|
15172
16276
|
normalized = normalized.slice(2);
|
|
15173
16277
|
}
|
|
@@ -15360,12 +16464,12 @@ async function getCallGraphPath(projectRoot, host, from, to, maxDepth, fromFileP
|
|
|
15360
16464
|
if (fromResolution.status !== "resolved" || toResolution.status !== "resolved") {
|
|
15361
16465
|
return { from: fromResolution, to: toResolution, path: [] };
|
|
15362
16466
|
}
|
|
15363
|
-
const
|
|
16467
|
+
const path34 = await indexer.findCallPathBySymbolIds(
|
|
15364
16468
|
fromResolution.symbolId,
|
|
15365
16469
|
toResolution.symbolId,
|
|
15366
16470
|
maxDepth
|
|
15367
16471
|
);
|
|
15368
|
-
return { from: fromResolution, to: toResolution, path:
|
|
16472
|
+
return { from: fromResolution, to: toResolution, path: path34 };
|
|
15369
16473
|
}
|
|
15370
16474
|
async function runIndexCodebase(projectRoot, host, args, onProgress) {
|
|
15371
16475
|
const root = getProjectRoot(projectRoot, host);
|
|
@@ -15374,6 +16478,9 @@ async function runIndexCodebase(projectRoot, host, args, onProgress) {
|
|
|
15374
16478
|
if (args.estimateOnly) {
|
|
15375
16479
|
return { kind: "estimate", estimate: await indexer.estimateCost() };
|
|
15376
16480
|
}
|
|
16481
|
+
if (args.dryRun) {
|
|
16482
|
+
return { kind: "dryrun", dryrun: await indexer.dryRunCost() };
|
|
16483
|
+
}
|
|
15377
16484
|
const coordinated = runCoordinatedIndex(root, host, args.force ?? false, (progress) => {
|
|
15378
16485
|
if (onProgress) {
|
|
15379
16486
|
void onProgress(formatProgressTitle(progress), {
|
|
@@ -15560,8 +16667,8 @@ async function getIndexLogs(projectRoot, host, args) {
|
|
|
15560
16667
|
function addKnowledgeBase(projectRoot, host, knowledgeBasePath) {
|
|
15561
16668
|
const root = getProjectRoot(projectRoot, host);
|
|
15562
16669
|
const inputPath = knowledgeBasePath.trim();
|
|
15563
|
-
const normalizedPath3 =
|
|
15564
|
-
|
|
16670
|
+
const normalizedPath3 = path22.resolve(
|
|
16671
|
+
path22.isAbsolute(inputPath) ? inputPath : resolveKnowledgeBasePath(inputPath, root)
|
|
15565
16672
|
);
|
|
15566
16673
|
if (!(0, import_fs14.existsSync)(normalizedPath3)) {
|
|
15567
16674
|
return `Error: Directory does not exist: ${normalizedPath3}`;
|
|
@@ -15597,7 +16704,7 @@ function addKnowledgeBase(projectRoot, host, knowledgeBasePath) {
|
|
|
15597
16704
|
}
|
|
15598
16705
|
}
|
|
15599
16706
|
for (const dotDir of sensitiveDotDirs) {
|
|
15600
|
-
const sensitiveDir =
|
|
16707
|
+
const sensitiveDir = path22.join(homeDir, dotDir);
|
|
15601
16708
|
if (sensitiveDir && (realPath === sensitiveDir || realPath.startsWith(`${sensitiveDir}/`))) {
|
|
15602
16709
|
return `Error: Adding sensitive directory as knowledge base is not allowed: ${normalizedPath3}`;
|
|
15603
16710
|
}
|
|
@@ -15660,7 +16767,7 @@ function listKnowledgeBases(projectRoot, host) {
|
|
|
15660
16767
|
}
|
|
15661
16768
|
result += "\n";
|
|
15662
16769
|
}
|
|
15663
|
-
const hasHostConfig = (0, import_fs14.existsSync)(
|
|
16770
|
+
const hasHostConfig = (0, import_fs14.existsSync)(path22.join(root, getHostProjectConfigRelativePath(host)));
|
|
15664
16771
|
if (hasHostConfig) {
|
|
15665
16772
|
result += `
|
|
15666
16773
|
Config sources: 1 file(s).`;
|
|
@@ -16133,7 +17240,7 @@ async function resolveCodebaseContextUnmeasured(projectRoot, host, input) {
|
|
|
16133
17240
|
const directory = input.directory ?? void 0;
|
|
16134
17241
|
const tokenBudget = input.tokenBudget ?? void 0;
|
|
16135
17242
|
if (from && to) {
|
|
16136
|
-
const
|
|
17243
|
+
const path34 = await getCallGraphPath(
|
|
16137
17244
|
projectRoot,
|
|
16138
17245
|
host,
|
|
16139
17246
|
from,
|
|
@@ -16142,25 +17249,25 @@ async function resolveCodebaseContextUnmeasured(projectRoot, host, input) {
|
|
|
16142
17249
|
fromFilePath,
|
|
16143
17250
|
toFilePath
|
|
16144
17251
|
);
|
|
16145
|
-
const pathText = formatCallGraphPathResult(
|
|
16146
|
-
if (
|
|
17252
|
+
const pathText = formatCallGraphPathResult(path34);
|
|
17253
|
+
if (path34.path.length > 0) {
|
|
16147
17254
|
const fitted2 = fitTextToContextBudget(
|
|
16148
17255
|
pathText,
|
|
16149
17256
|
tokenBudget
|
|
16150
17257
|
);
|
|
16151
17258
|
return {
|
|
16152
17259
|
text: fitted2.text,
|
|
16153
|
-
details: fittedDetails("path", fitted2,
|
|
17260
|
+
details: fittedDetails("path", fitted2, path34.path.length)
|
|
16154
17261
|
};
|
|
16155
17262
|
}
|
|
16156
|
-
if (
|
|
17263
|
+
if (path34.from.status !== "resolved" || path34.to.status !== "resolved") {
|
|
16157
17264
|
const fitted2 = fitTextToContextBudget(pathText, tokenBudget);
|
|
16158
17265
|
return {
|
|
16159
17266
|
text: fitted2.text,
|
|
16160
17267
|
details: fittedDetails("path", fitted2, 0)
|
|
16161
17268
|
};
|
|
16162
17269
|
}
|
|
16163
|
-
const resolvedFrom =
|
|
17270
|
+
const resolvedFrom = path34.from;
|
|
16164
17271
|
const { callers } = await getCallGraphData(projectRoot, host, {
|
|
16165
17272
|
name: to,
|
|
16166
17273
|
direction: "callers",
|
|
@@ -16638,9 +17745,9 @@ function getRelevantEvidence(query) {
|
|
|
16638
17745
|
});
|
|
16639
17746
|
}
|
|
16640
17747
|
if (query.expected.acceptableFiles) {
|
|
16641
|
-
for (const
|
|
17748
|
+
for (const path34 of query.expected.acceptableFiles) {
|
|
16642
17749
|
legacyEvidence.push({
|
|
16643
|
-
path:
|
|
17750
|
+
path: path34,
|
|
16644
17751
|
...query.expected.symbol !== void 0 ? { symbol: query.expected.symbol } : {},
|
|
16645
17752
|
relevance: 1
|
|
16646
17753
|
});
|
|
@@ -16963,8 +18070,8 @@ function computeEvalMetrics(queries, perQuery, embeddingCallCount, embeddingToke
|
|
|
16963
18070
|
|
|
16964
18071
|
// src/eval/runner-config.ts
|
|
16965
18072
|
var import_fs15 = require("fs");
|
|
16966
|
-
var
|
|
16967
|
-
var
|
|
18073
|
+
var os8 = __toESM(require("os"), 1);
|
|
18074
|
+
var path23 = __toESM(require("path"), 1);
|
|
16968
18075
|
function isRecord2(value) {
|
|
16969
18076
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
16970
18077
|
}
|
|
@@ -17008,20 +18115,20 @@ function parseJsonConfigFile(filePath) {
|
|
|
17008
18115
|
}
|
|
17009
18116
|
}
|
|
17010
18117
|
function toAbsolute(projectRoot, maybeRelative) {
|
|
17011
|
-
return
|
|
18118
|
+
return path23.isAbsolute(maybeRelative) ? maybeRelative : path23.join(projectRoot, maybeRelative);
|
|
17012
18119
|
}
|
|
17013
18120
|
function isProjectScopedConfigPath(configPath) {
|
|
17014
|
-
return
|
|
18121
|
+
return path23.basename(configPath) === "codebase-index.json" && path23.basename(path23.dirname(configPath)) === ".opencode";
|
|
17015
18122
|
}
|
|
17016
18123
|
function normalizeEvalConfigKnowledgeBases(rawConfig, projectRoot, resolvedConfigPath) {
|
|
17017
18124
|
const config = rawConfig && typeof rawConfig === "object" ? { ...rawConfig } : {};
|
|
17018
18125
|
const rebaseEntries = (values) => isProjectScopedConfigPath(resolvedConfigPath) ? resolveInheritedKnowledgeBaseEntries(
|
|
17019
18126
|
values,
|
|
17020
|
-
|
|
18127
|
+
path23.dirname(path23.dirname(resolvedConfigPath)),
|
|
17021
18128
|
projectRoot
|
|
17022
18129
|
) : rebasePathEntries(
|
|
17023
18130
|
values,
|
|
17024
|
-
|
|
18131
|
+
path23.dirname(resolvedConfigPath),
|
|
17025
18132
|
projectRoot
|
|
17026
18133
|
);
|
|
17027
18134
|
if (Array.isArray(config.knowledgeBases)) {
|
|
@@ -17049,7 +18156,7 @@ function loadRawConfig(projectRoot, configPath) {
|
|
|
17049
18156
|
projectConfig
|
|
17050
18157
|
);
|
|
17051
18158
|
}
|
|
17052
|
-
const globalConfig =
|
|
18159
|
+
const globalConfig = path23.join(os8.homedir(), ".config", "opencode", "codebase-index.json");
|
|
17053
18160
|
if ((0, import_fs15.existsSync)(globalConfig)) {
|
|
17054
18161
|
return parseJsonConfigFile(globalConfig);
|
|
17055
18162
|
}
|
|
@@ -17059,10 +18166,10 @@ function getIndexRootPath(projectRoot, scope) {
|
|
|
17059
18166
|
return scope === "global" ? getGlobalIndexPath("opencode") : resolveProjectIndexPath(projectRoot, scope, "opencode");
|
|
17060
18167
|
}
|
|
17061
18168
|
function getLocalProjectIndexRoot(projectRoot) {
|
|
17062
|
-
return
|
|
18169
|
+
return path23.join(projectRoot, ".opencode", "index");
|
|
17063
18170
|
}
|
|
17064
18171
|
function getLocalProjectConfigPath(projectRoot) {
|
|
17065
|
-
return
|
|
18172
|
+
return path23.join(projectRoot, ".opencode", "codebase-index.json");
|
|
17066
18173
|
}
|
|
17067
18174
|
function clearIndexRoot(projectRoot, scope) {
|
|
17068
18175
|
const indexRoot = scope === "global" ? getIndexRootPath(projectRoot, scope) : getLocalProjectIndexRoot(projectRoot);
|
|
@@ -17084,7 +18191,7 @@ function ensureLocalEvalProjectConfig(projectRoot, configPath) {
|
|
|
17084
18191
|
projectRoot,
|
|
17085
18192
|
resolvedConfigPath
|
|
17086
18193
|
);
|
|
17087
|
-
(0, import_fs15.mkdirSync)(
|
|
18194
|
+
(0, import_fs15.mkdirSync)(path23.dirname(localConfigPath), { recursive: true });
|
|
17088
18195
|
(0, import_fs15.writeFileSync)(localConfigPath, JSON.stringify(sourceConfig, null, 2), "utf-8");
|
|
17089
18196
|
return localConfigPath;
|
|
17090
18197
|
}
|
|
@@ -17137,68 +18244,68 @@ function isStringArray4(value) {
|
|
|
17137
18244
|
function isNonEmptyString(value) {
|
|
17138
18245
|
return typeof value === "string" && value.trim().length > 0;
|
|
17139
18246
|
}
|
|
17140
|
-
function asPositiveNumber(value,
|
|
18247
|
+
function asPositiveNumber(value, path34) {
|
|
17141
18248
|
if (typeof value !== "number" || Number.isNaN(value) || value < 0) {
|
|
17142
|
-
throw new Error(`${
|
|
18249
|
+
throw new Error(`${path34} must be a non-negative number`);
|
|
17143
18250
|
}
|
|
17144
18251
|
return value;
|
|
17145
18252
|
}
|
|
17146
|
-
function parseQueryType(value,
|
|
18253
|
+
function parseQueryType(value, path34) {
|
|
17147
18254
|
if (value === "definition" || value === "implementation-intent" || value === "similarity" || value === "keyword-heavy" || value === "conceptual") {
|
|
17148
18255
|
return value;
|
|
17149
18256
|
}
|
|
17150
18257
|
throw new Error(
|
|
17151
|
-
`${
|
|
18258
|
+
`${path34} must be one of: definition, implementation-intent, similarity, keyword-heavy, conceptual`
|
|
17152
18259
|
);
|
|
17153
18260
|
}
|
|
17154
|
-
function parseExpectedRoute(value,
|
|
18261
|
+
function parseExpectedRoute(value, path34) {
|
|
17155
18262
|
if (value === void 0) return void 0;
|
|
17156
18263
|
if (value === "search" || value === "definition") return value;
|
|
17157
|
-
throw new Error(`${
|
|
18264
|
+
throw new Error(`${path34} must be one of: search, definition`);
|
|
17158
18265
|
}
|
|
17159
|
-
function parseExpectedOutcome(value,
|
|
18266
|
+
function parseExpectedOutcome(value, path34) {
|
|
17160
18267
|
if (value === void 0) return void 0;
|
|
17161
18268
|
if (value === "results" || value === "no-results") {
|
|
17162
18269
|
return value;
|
|
17163
18270
|
}
|
|
17164
|
-
throw new Error(`${
|
|
18271
|
+
throw new Error(`${path34} must be one of: results, no-results`);
|
|
17165
18272
|
}
|
|
17166
|
-
function parseRecoveryExpectation(value,
|
|
18273
|
+
function parseRecoveryExpectation(value, path34) {
|
|
17167
18274
|
if (value === void 0) return void 0;
|
|
17168
18275
|
if (value === "none" || value === "filter-relaxed") {
|
|
17169
18276
|
return value;
|
|
17170
18277
|
}
|
|
17171
|
-
throw new Error(`${
|
|
18278
|
+
throw new Error(`${path34} must be one of: none, filter-relaxed`);
|
|
17172
18279
|
}
|
|
17173
|
-
function parseQueryDifficulty(value,
|
|
18280
|
+
function parseQueryDifficulty(value, path34) {
|
|
17174
18281
|
if (value === void 0) return void 0;
|
|
17175
18282
|
if (value === "easy" || value === "medium" || value === "hard") {
|
|
17176
18283
|
return value;
|
|
17177
18284
|
}
|
|
17178
|
-
throw new Error(`${
|
|
18285
|
+
throw new Error(`${path34} must be one of: easy, medium, hard`);
|
|
17179
18286
|
}
|
|
17180
|
-
function parseQueryTags(value,
|
|
18287
|
+
function parseQueryTags(value, path34) {
|
|
17181
18288
|
if (value === void 0) return void 0;
|
|
17182
18289
|
if (!isStringArray4(value) || value.some((tag) => tag.trim().length === 0)) {
|
|
17183
|
-
throw new Error(`${
|
|
18290
|
+
throw new Error(`${path34} must be an array of non-empty strings`);
|
|
17184
18291
|
}
|
|
17185
18292
|
if (value.length > 16) {
|
|
17186
|
-
throw new Error(`${
|
|
18293
|
+
throw new Error(`${path34} must contain at most 16 tags`);
|
|
17187
18294
|
}
|
|
17188
18295
|
return value;
|
|
17189
18296
|
}
|
|
17190
|
-
function parseQueryArgs(value,
|
|
18297
|
+
function parseQueryArgs(value, path34) {
|
|
17191
18298
|
if (value === void 0) return void 0;
|
|
17192
18299
|
if (!isRecord3(value)) {
|
|
17193
|
-
throw new Error(`${
|
|
17194
|
-
}
|
|
17195
|
-
const symbol = parseStringOrUndefined(value.symbol, `${
|
|
17196
|
-
const filePath = parseStringOrUndefined(value.filePath, `${
|
|
17197
|
-
const fileType = parseStringOrUndefined(value.fileType, `${
|
|
17198
|
-
const directory = parseStringOrUndefined(value.directory, `${
|
|
17199
|
-
const callerLimit = parsePositiveIntegerOrUndefined(value.callerLimit, `${
|
|
17200
|
-
const calleeLimit = parsePositiveIntegerOrUndefined(value.calleeLimit, `${
|
|
17201
|
-
const tokenBudget = parsePositiveIntegerOrUndefined(value.tokenBudget, `${
|
|
18300
|
+
throw new Error(`${path34} must be an object`);
|
|
18301
|
+
}
|
|
18302
|
+
const symbol = parseStringOrUndefined(value.symbol, `${path34}.symbol`);
|
|
18303
|
+
const filePath = parseStringOrUndefined(value.filePath, `${path34}.filePath`);
|
|
18304
|
+
const fileType = parseStringOrUndefined(value.fileType, `${path34}.fileType`);
|
|
18305
|
+
const directory = parseStringOrUndefined(value.directory, `${path34}.directory`);
|
|
18306
|
+
const callerLimit = parsePositiveIntegerOrUndefined(value.callerLimit, `${path34}.callerLimit`);
|
|
18307
|
+
const calleeLimit = parsePositiveIntegerOrUndefined(value.calleeLimit, `${path34}.calleeLimit`);
|
|
18308
|
+
const tokenBudget = parsePositiveIntegerOrUndefined(value.tokenBudget, `${path34}.tokenBudget`);
|
|
17202
18309
|
return {
|
|
17203
18310
|
...symbol !== void 0 ? { symbol } : {},
|
|
17204
18311
|
...filePath !== void 0 ? { filePath } : {},
|
|
@@ -17209,50 +18316,50 @@ function parseQueryArgs(value, path33) {
|
|
|
17209
18316
|
...tokenBudget !== void 0 ? { tokenBudget } : {}
|
|
17210
18317
|
};
|
|
17211
18318
|
}
|
|
17212
|
-
function parsePositiveIntegerOrUndefined(value,
|
|
18319
|
+
function parsePositiveIntegerOrUndefined(value, path34) {
|
|
17213
18320
|
if (value === void 0 || value === null) return void 0;
|
|
17214
18321
|
if (typeof value !== "number" || !Number.isInteger(value) || value <= 0) {
|
|
17215
|
-
throw new Error(`${
|
|
18322
|
+
throw new Error(`${path34} must be a positive integer`);
|
|
17216
18323
|
}
|
|
17217
18324
|
return value;
|
|
17218
18325
|
}
|
|
17219
18326
|
var SEMVER_VERSION_PATTERN = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
|
|
17220
|
-
function parseSemanticVersion(value,
|
|
18327
|
+
function parseSemanticVersion(value, path34) {
|
|
17221
18328
|
if (!isNonEmptyString(value)) {
|
|
17222
|
-
throw new Error(`${
|
|
18329
|
+
throw new Error(`${path34} must be a non-empty string`);
|
|
17223
18330
|
}
|
|
17224
18331
|
if (!SEMVER_VERSION_PATTERN.test(value)) {
|
|
17225
|
-
throw new Error(`${
|
|
18332
|
+
throw new Error(`${path34} must be a valid semantic version (MAJOR.MINOR.PATCH)`);
|
|
17226
18333
|
}
|
|
17227
18334
|
return value;
|
|
17228
18335
|
}
|
|
17229
|
-
function parseRetrievalMode(value,
|
|
18336
|
+
function parseRetrievalMode(value, path34) {
|
|
17230
18337
|
if (value === void 0 || value === "search") return "search";
|
|
17231
18338
|
if (value === "context" || value === "edit-context") return value;
|
|
17232
|
-
throw new Error(`${
|
|
18339
|
+
throw new Error(`${path34} must be one of: search, context, edit-context`);
|
|
17233
18340
|
}
|
|
17234
|
-
function parseStringOrUndefined(value,
|
|
18341
|
+
function parseStringOrUndefined(value, path34) {
|
|
17235
18342
|
if (value === void 0 || value === null) return void 0;
|
|
17236
18343
|
if (!isNonEmptyString(value)) {
|
|
17237
|
-
throw new Error(`${
|
|
18344
|
+
throw new Error(`${path34} must be a non-empty string`);
|
|
17238
18345
|
}
|
|
17239
18346
|
return value;
|
|
17240
18347
|
}
|
|
17241
|
-
function parseGradedEvidence(value,
|
|
18348
|
+
function parseGradedEvidence(value, path34) {
|
|
17242
18349
|
if (value === void 0) return [];
|
|
17243
18350
|
if (!Array.isArray(value)) {
|
|
17244
|
-
throw new Error(`${
|
|
18351
|
+
throw new Error(`${path34} must be an array`);
|
|
17245
18352
|
}
|
|
17246
18353
|
return value.map((entry, index) => {
|
|
17247
18354
|
if (!isRecord3(entry)) {
|
|
17248
|
-
throw new Error(`${
|
|
18355
|
+
throw new Error(`${path34}[${index}] must be an object`);
|
|
17249
18356
|
}
|
|
17250
|
-
const evidencePath = parseStringOrUndefined(entry.path, `${
|
|
18357
|
+
const evidencePath = parseStringOrUndefined(entry.path, `${path34}[${index}].path`);
|
|
17251
18358
|
if (evidencePath === void 0) {
|
|
17252
|
-
throw new Error(`${
|
|
18359
|
+
throw new Error(`${path34}[${index}].path is required`);
|
|
17253
18360
|
}
|
|
17254
|
-
const symbol = parseStringOrUndefined(entry.symbol, `${
|
|
17255
|
-
const relevance = parseEvidenceRelevance(entry.relevance, `${
|
|
18361
|
+
const symbol = parseStringOrUndefined(entry.symbol, `${path34}[${index}].symbol`);
|
|
18362
|
+
const relevance = parseEvidenceRelevance(entry.relevance, `${path34}[${index}].relevance`);
|
|
17256
18363
|
return {
|
|
17257
18364
|
path: evidencePath,
|
|
17258
18365
|
...symbol !== void 0 ? { symbol } : {},
|
|
@@ -17260,27 +18367,27 @@ function parseGradedEvidence(value, path33) {
|
|
|
17260
18367
|
};
|
|
17261
18368
|
});
|
|
17262
18369
|
}
|
|
17263
|
-
function parseEvidenceRelevance(value,
|
|
18370
|
+
function parseEvidenceRelevance(value, path34) {
|
|
17264
18371
|
if (value === void 0) {
|
|
17265
|
-
throw new Error(`${
|
|
18372
|
+
throw new Error(`${path34} is required`);
|
|
17266
18373
|
}
|
|
17267
18374
|
if (value !== 1 && value !== 2 && value !== 3) {
|
|
17268
|
-
throw new Error(`${
|
|
18375
|
+
throw new Error(`${path34} must be 1, 2, or 3`);
|
|
17269
18376
|
}
|
|
17270
18377
|
return value;
|
|
17271
18378
|
}
|
|
17272
|
-
function parseExpectedGraphNeighbor(value,
|
|
18379
|
+
function parseExpectedGraphNeighbor(value, path34) {
|
|
17273
18380
|
if (value === void 0) return void 0;
|
|
17274
18381
|
if (!isRecord3(value)) {
|
|
17275
|
-
throw new Error(`${
|
|
18382
|
+
throw new Error(`${path34} must be an object`);
|
|
17276
18383
|
}
|
|
17277
18384
|
if (value.direction !== "caller" && value.direction !== "callee") {
|
|
17278
|
-
throw new Error(`${
|
|
18385
|
+
throw new Error(`${path34}.direction must be one of: caller, callee`);
|
|
17279
18386
|
}
|
|
17280
|
-
const filePath = parseStringOrUndefined(value.filePath, `${
|
|
17281
|
-
const symbol = parseStringOrUndefined(value.symbol, `${
|
|
18387
|
+
const filePath = parseStringOrUndefined(value.filePath, `${path34}.filePath`);
|
|
18388
|
+
const symbol = parseStringOrUndefined(value.symbol, `${path34}.symbol`);
|
|
17282
18389
|
if (filePath === void 0 && symbol === void 0) {
|
|
17283
|
-
throw new Error(`${
|
|
18390
|
+
throw new Error(`${path34} must include filePath or symbol`);
|
|
17284
18391
|
}
|
|
17285
18392
|
return {
|
|
17286
18393
|
direction: value.direction,
|
|
@@ -17288,9 +18395,9 @@ function parseExpectedGraphNeighbor(value, path33) {
|
|
|
17288
18395
|
...symbol !== void 0 ? { symbol } : {}
|
|
17289
18396
|
};
|
|
17290
18397
|
}
|
|
17291
|
-
function parseExpected(input,
|
|
18398
|
+
function parseExpected(input, path34) {
|
|
17292
18399
|
if (!isRecord3(input)) {
|
|
17293
|
-
throw new Error(`${
|
|
18400
|
+
throw new Error(`${path34} must be an object`);
|
|
17294
18401
|
}
|
|
17295
18402
|
const filePathRaw = input.filePath;
|
|
17296
18403
|
const acceptableFilesRaw = input.acceptableFiles;
|
|
@@ -17301,29 +18408,29 @@ function parseExpected(input, path33) {
|
|
|
17301
18408
|
const recoveryExpectationRaw = input.recoveryExpectation;
|
|
17302
18409
|
const gradedEvidenceRaw = input.gradedEvidence;
|
|
17303
18410
|
const graphNeighborRaw = input.graphNeighbor;
|
|
17304
|
-
const filePath = parseStringOrUndefined(filePathRaw, `${
|
|
18411
|
+
const filePath = parseStringOrUndefined(filePathRaw, `${path34}.filePath`);
|
|
17305
18412
|
const acceptableFiles = isStringArray4(acceptableFilesRaw) ? acceptableFilesRaw : void 0;
|
|
17306
|
-
const gradedEvidence = parseGradedEvidence(gradedEvidenceRaw, `${
|
|
17307
|
-
const graphNeighbor = parseExpectedGraphNeighbor(graphNeighborRaw, `${
|
|
17308
|
-
const expectedOutcome = parseExpectedOutcome(expectedOutcomeRaw, `${
|
|
18413
|
+
const gradedEvidence = parseGradedEvidence(gradedEvidenceRaw, `${path34}.gradedEvidence`);
|
|
18414
|
+
const graphNeighbor = parseExpectedGraphNeighbor(graphNeighborRaw, `${path34}.graphNeighbor`);
|
|
18415
|
+
const expectedOutcome = parseExpectedOutcome(expectedOutcomeRaw, `${path34}.expectedOutcome`);
|
|
17309
18416
|
if (expectedOutcome !== "no-results" && !filePath && (!acceptableFiles || acceptableFiles.length === 0) && gradedEvidence.length === 0) {
|
|
17310
18417
|
throw new Error(
|
|
17311
|
-
`${
|
|
18418
|
+
`${path34} must include expected.filePath, expected.acceptableFiles, or expected.gradedEvidence`
|
|
17312
18419
|
);
|
|
17313
18420
|
}
|
|
17314
18421
|
if (acceptableFilesRaw !== void 0 && !isStringArray4(acceptableFilesRaw)) {
|
|
17315
|
-
throw new Error(`${
|
|
18422
|
+
throw new Error(`${path34}.acceptableFiles must be an array of strings`);
|
|
17316
18423
|
}
|
|
17317
18424
|
if (symbolRaw !== void 0 && typeof symbolRaw !== "string") {
|
|
17318
|
-
throw new Error(`${
|
|
18425
|
+
throw new Error(`${path34}.symbol must be a string when provided`);
|
|
17319
18426
|
}
|
|
17320
18427
|
if (branchRaw !== void 0 && typeof branchRaw !== "string") {
|
|
17321
|
-
throw new Error(`${
|
|
18428
|
+
throw new Error(`${path34}.branch must be a string when provided`);
|
|
17322
18429
|
}
|
|
17323
|
-
const expectedRoute = parseExpectedRoute(expectedRouteRaw, `${
|
|
18430
|
+
const expectedRoute = parseExpectedRoute(expectedRouteRaw, `${path34}.expectedRoute`);
|
|
17324
18431
|
const recoveryExpectation = parseRecoveryExpectation(
|
|
17325
18432
|
recoveryExpectationRaw,
|
|
17326
|
-
`${
|
|
18433
|
+
`${path34}.recoveryExpectation`
|
|
17327
18434
|
);
|
|
17328
18435
|
return {
|
|
17329
18436
|
filePath,
|
|
@@ -17337,13 +18444,13 @@ function parseExpected(input, path33) {
|
|
|
17337
18444
|
...graphNeighbor !== void 0 ? { graphNeighbor } : {}
|
|
17338
18445
|
};
|
|
17339
18446
|
}
|
|
17340
|
-
function parseQueryLanguage(value,
|
|
17341
|
-
return parseStringOrUndefined(value,
|
|
18447
|
+
function parseQueryLanguage(value, path34) {
|
|
18448
|
+
return parseStringOrUndefined(value, path34);
|
|
17342
18449
|
}
|
|
17343
18450
|
function parseQuery(input, index) {
|
|
17344
|
-
const
|
|
18451
|
+
const path34 = `queries[${index}]`;
|
|
17345
18452
|
if (!isRecord3(input)) {
|
|
17346
|
-
throw new Error(`${
|
|
18453
|
+
throw new Error(`${path34} must be an object`);
|
|
17347
18454
|
}
|
|
17348
18455
|
const id = input.id;
|
|
17349
18456
|
const query = input.query;
|
|
@@ -17355,21 +18462,21 @@ function parseQuery(input, index) {
|
|
|
17355
18462
|
const tags = input.tags;
|
|
17356
18463
|
const args = input.args;
|
|
17357
18464
|
if (typeof id !== "string" || id.trim().length === 0) {
|
|
17358
|
-
throw new Error(`${
|
|
18465
|
+
throw new Error(`${path34}.id must be a non-empty string`);
|
|
17359
18466
|
}
|
|
17360
18467
|
if (typeof query !== "string" || query.trim().length === 0) {
|
|
17361
|
-
throw new Error(`${
|
|
18468
|
+
throw new Error(`${path34}.query must be a non-empty string`);
|
|
17362
18469
|
}
|
|
17363
18470
|
return {
|
|
17364
18471
|
id,
|
|
17365
18472
|
query,
|
|
17366
|
-
queryType: parseQueryType(queryType, `${
|
|
17367
|
-
retrievalMode: parseRetrievalMode(retrievalMode, `${
|
|
17368
|
-
language: parseQueryLanguage(language, `${
|
|
17369
|
-
difficulty: parseQueryDifficulty(difficulty, `${
|
|
17370
|
-
args: parseQueryArgs(args, `${
|
|
17371
|
-
tags: parseQueryTags(tags, `${
|
|
17372
|
-
expected: parseExpected(expected, `${
|
|
18473
|
+
queryType: parseQueryType(queryType, `${path34}.queryType`),
|
|
18474
|
+
retrievalMode: parseRetrievalMode(retrievalMode, `${path34}.retrievalMode`),
|
|
18475
|
+
language: parseQueryLanguage(language, `${path34}.language`),
|
|
18476
|
+
difficulty: parseQueryDifficulty(difficulty, `${path34}.difficulty`),
|
|
18477
|
+
args: parseQueryArgs(args, `${path34}.args`),
|
|
18478
|
+
tags: parseQueryTags(tags, `${path34}.tags`),
|
|
18479
|
+
expected: parseExpected(expected, `${path34}.expected`)
|
|
17373
18480
|
};
|
|
17374
18481
|
}
|
|
17375
18482
|
function parseGoldenDataset(raw, sourceLabel) {
|
|
@@ -17785,13 +18892,13 @@ async function runEvaluation(options) {
|
|
|
17785
18892
|
};
|
|
17786
18893
|
const outputDir = createRunDirectory(toAbsolute(options.projectRoot, options.outputRoot));
|
|
17787
18894
|
const perQueryArtifact = buildPerQueryArtifact(perQuery);
|
|
17788
|
-
writeJson(
|
|
17789
|
-
writeJson(
|
|
18895
|
+
writeJson(path24.join(outputDir, "summary.json"), summary);
|
|
18896
|
+
writeJson(path24.join(outputDir, "per-query.json"), perQueryArtifact);
|
|
17790
18897
|
let comparison;
|
|
17791
18898
|
if (againstPath) {
|
|
17792
18899
|
const baseline = loadSummary(againstPath);
|
|
17793
18900
|
comparison = compareSummaries(summary, baseline, againstPath);
|
|
17794
|
-
writeJson(
|
|
18901
|
+
writeJson(path24.join(outputDir, "compare.json"), comparison);
|
|
17795
18902
|
}
|
|
17796
18903
|
let gate;
|
|
17797
18904
|
if (options.ciMode) {
|
|
@@ -17804,7 +18911,7 @@ async function runEvaluation(options) {
|
|
|
17804
18911
|
if ((0, import_fs17.existsSync)(resolvedBaseline)) {
|
|
17805
18912
|
const baselineSummary = loadSummary(resolvedBaseline);
|
|
17806
18913
|
comparison = compareSummaries(summary, baselineSummary, resolvedBaseline);
|
|
17807
|
-
writeJson(
|
|
18914
|
+
writeJson(path24.join(outputDir, "compare.json"), comparison);
|
|
17808
18915
|
} else if (budget.failOnMissingBaseline) {
|
|
17809
18916
|
throw new Error(
|
|
17810
18917
|
`Budget baseline is missing: ${resolvedBaseline}. Set failOnMissingBaseline=false to allow CI run without baseline.`
|
|
@@ -17814,7 +18921,7 @@ async function runEvaluation(options) {
|
|
|
17814
18921
|
gate = evaluateBudgetGate(budget, summary, comparison);
|
|
17815
18922
|
}
|
|
17816
18923
|
const markdown = createSummaryMarkdown(summary, comparison, gate);
|
|
17817
|
-
writeText(
|
|
18924
|
+
writeText(path24.join(outputDir, "summary.md"), markdown);
|
|
17818
18925
|
return { outputDir, summary, perQuery, comparison, gate };
|
|
17819
18926
|
} finally {
|
|
17820
18927
|
await indexer.close();
|
|
@@ -17872,23 +18979,23 @@ async function runSweep(options, sweep) {
|
|
|
17872
18979
|
bestByMrrAt10,
|
|
17873
18980
|
bestByP95Latency
|
|
17874
18981
|
};
|
|
17875
|
-
writeJson(
|
|
18982
|
+
writeJson(path24.join(outputDir, "compare.json"), aggregate);
|
|
17876
18983
|
const md = createSummaryMarkdown(
|
|
17877
18984
|
bestByHitAt5?.summary ?? runs[0].summary,
|
|
17878
18985
|
bestByHitAt5?.comparison,
|
|
17879
18986
|
void 0,
|
|
17880
18987
|
aggregate
|
|
17881
18988
|
);
|
|
17882
|
-
writeText(
|
|
17883
|
-
writeJson(
|
|
18989
|
+
writeText(path24.join(outputDir, "summary.md"), md);
|
|
18990
|
+
writeJson(path24.join(outputDir, "summary.json"), bestByHitAt5?.summary ?? runs[0].summary);
|
|
17884
18991
|
return { outputDir, aggregate };
|
|
17885
18992
|
}
|
|
17886
18993
|
|
|
17887
18994
|
// src/eval/cli.ts
|
|
17888
|
-
var
|
|
18995
|
+
var path26 = __toESM(require("path"), 1);
|
|
17889
18996
|
|
|
17890
18997
|
// src/eval/cli-parser.ts
|
|
17891
|
-
var
|
|
18998
|
+
var path25 = __toESM(require("path"), 1);
|
|
17892
18999
|
function printUsage() {
|
|
17893
19000
|
console.log(`
|
|
17894
19001
|
Usage:
|
|
@@ -17960,12 +19067,12 @@ function parseEvalArgs(argv, cwd) {
|
|
|
17960
19067
|
const arg = argv[i];
|
|
17961
19068
|
const next = argv[i + 1];
|
|
17962
19069
|
if (arg === "--project" && next) {
|
|
17963
|
-
parsed.projectRoot =
|
|
19070
|
+
parsed.projectRoot = path25.resolve(cwd, next);
|
|
17964
19071
|
i += 1;
|
|
17965
19072
|
continue;
|
|
17966
19073
|
}
|
|
17967
19074
|
if (arg === "--config" && next) {
|
|
17968
|
-
parsed.configPath =
|
|
19075
|
+
parsed.configPath = path25.resolve(cwd, next);
|
|
17969
19076
|
i += 1;
|
|
17970
19077
|
continue;
|
|
17971
19078
|
}
|
|
@@ -18161,22 +19268,22 @@ async function handleEvalCommand(args, cwd) {
|
|
|
18161
19268
|
if (!parsed.againstPath.endsWith(".json")) {
|
|
18162
19269
|
throw new Error("eval diff --against must point to a summary JSON file");
|
|
18163
19270
|
}
|
|
18164
|
-
const currentSummary = loadSummary(
|
|
19271
|
+
const currentSummary = loadSummary(path26.resolve(parsed.projectRoot, currentPath), {
|
|
18165
19272
|
allowLegacyDiversityMetrics: true
|
|
18166
19273
|
});
|
|
18167
|
-
const baselineSummary = loadSummary(
|
|
19274
|
+
const baselineSummary = loadSummary(path26.resolve(parsed.projectRoot, parsed.againstPath), {
|
|
18168
19275
|
allowLegacyDiversityMetrics: true
|
|
18169
19276
|
});
|
|
18170
19277
|
const comparison = compareSummaries(
|
|
18171
19278
|
currentSummary,
|
|
18172
19279
|
baselineSummary,
|
|
18173
|
-
|
|
19280
|
+
path26.resolve(parsed.projectRoot, parsed.againstPath)
|
|
18174
19281
|
);
|
|
18175
|
-
const outputDir = createRunDirectory(
|
|
19282
|
+
const outputDir = createRunDirectory(path26.resolve(parsed.projectRoot, parsed.outputRoot));
|
|
18176
19283
|
const summaryMd = createSummaryMarkdown(currentSummary, comparison);
|
|
18177
|
-
writeJson(
|
|
18178
|
-
writeText(
|
|
18179
|
-
writeJson(
|
|
19284
|
+
writeJson(path26.join(outputDir, "compare.json"), comparison);
|
|
19285
|
+
writeText(path26.join(outputDir, "summary.md"), summaryMd);
|
|
19286
|
+
writeJson(path26.join(outputDir, "summary.json"), currentSummary);
|
|
18180
19287
|
console.log(`Eval diff complete. Artifacts: ${outputDir}`);
|
|
18181
19288
|
return 0;
|
|
18182
19289
|
}
|
|
@@ -18301,6 +19408,7 @@ async function executeCodebaseEditContext(projectRoot, host, args) {
|
|
|
18301
19408
|
async function executeIndexCodebase(projectRoot, host, args, onProgress) {
|
|
18302
19409
|
const result = await runIndexCodebase(projectRoot, host, args, onProgress);
|
|
18303
19410
|
if (result.kind === "estimate") return { text: formatCostEstimate(result.estimate) };
|
|
19411
|
+
if (result.kind === "dryrun") return { text: formatDryRunEstimate(result.dryrun) };
|
|
18304
19412
|
if (result.kind === "busy") return { text: result.text, isError: true };
|
|
18305
19413
|
if (result.kind === "message") return { text: result.text };
|
|
18306
19414
|
return { text: formatIndexStats(result.stats, args.verbose ?? false) };
|
|
@@ -18337,7 +19445,7 @@ async function executeCallGraph(projectRoot, host, args) {
|
|
|
18337
19445
|
return { text: formatCallGraphResult(await getCallGraphData(projectRoot, host, args)) };
|
|
18338
19446
|
}
|
|
18339
19447
|
async function executeCallGraphPath(projectRoot, host, args) {
|
|
18340
|
-
const
|
|
19448
|
+
const path34 = await getCallGraphPath(
|
|
18341
19449
|
projectRoot,
|
|
18342
19450
|
host,
|
|
18343
19451
|
args.from,
|
|
@@ -18346,7 +19454,7 @@ async function executeCallGraphPath(projectRoot, host, args) {
|
|
|
18346
19454
|
args.fromFilePath,
|
|
18347
19455
|
args.toFilePath
|
|
18348
19456
|
);
|
|
18349
|
-
return { text: formatCallGraphPathResult(
|
|
19457
|
+
return { text: formatCallGraphPathResult(path34) };
|
|
18350
19458
|
}
|
|
18351
19459
|
async function executeCodeCommunities(projectRoot, host, args) {
|
|
18352
19460
|
const result = await getCodeCommunities(projectRoot, host, args);
|
|
@@ -18628,6 +19736,7 @@ ${formatCodebasePeek(results)}`;
|
|
|
18628
19736
|
{
|
|
18629
19737
|
force: allowNullAsUndefined(import_zod2.z.boolean().optional().default(false)).describe("Force reindex even if already indexed"),
|
|
18630
19738
|
estimateOnly: allowNullAsUndefined(import_zod2.z.boolean().optional().default(false)).describe("Only show cost estimate without indexing"),
|
|
19739
|
+
dryRun: allowNullAsUndefined(import_zod2.z.boolean().optional().default(false)).describe("Parse the file set and report the exact embedding token total without indexing. Read-only; the index is not changed. The total is the value 'Tokens used' climbs to for a force index (and an upper bound for an incremental)."),
|
|
18631
19740
|
verbose: allowNullAsUndefined(import_zod2.z.boolean().optional().default(false)).describe("Show detailed info about skipped files and parsing failures")
|
|
18632
19741
|
},
|
|
18633
19742
|
async (args) => {
|
|
@@ -18840,9 +19949,64 @@ ${formatSearchResults(results)}` }] };
|
|
|
18840
19949
|
}
|
|
18841
19950
|
|
|
18842
19951
|
// src/adapters/mcp/server.ts
|
|
19952
|
+
var mcpWorkerReferences = /* @__PURE__ */ new Map();
|
|
19953
|
+
var mcpWorkerTeardowns = /* @__PURE__ */ new Map();
|
|
19954
|
+
function retainMcpBackgroundWorker(projectRoot, host) {
|
|
19955
|
+
const key = getBackgroundWorkerProjectKey(projectRoot, host);
|
|
19956
|
+
mcpWorkerReferences.set(key, (mcpWorkerReferences.get(key) ?? 0) + 1);
|
|
19957
|
+
}
|
|
19958
|
+
async function releaseMcpBackgroundWorker(projectRoot, host) {
|
|
19959
|
+
const key = getBackgroundWorkerProjectKey(projectRoot, host);
|
|
19960
|
+
const references = mcpWorkerReferences.get(key) ?? 0;
|
|
19961
|
+
if (references > 1) {
|
|
19962
|
+
mcpWorkerReferences.set(key, references - 1);
|
|
19963
|
+
return;
|
|
19964
|
+
}
|
|
19965
|
+
mcpWorkerReferences.delete(key);
|
|
19966
|
+
const teardown = stopBackgroundWorker(projectRoot, host);
|
|
19967
|
+
mcpWorkerTeardowns.set(key, teardown);
|
|
19968
|
+
try {
|
|
19969
|
+
await teardown;
|
|
19970
|
+
} finally {
|
|
19971
|
+
if (mcpWorkerTeardowns.get(key) === teardown) {
|
|
19972
|
+
mcpWorkerTeardowns.delete(key);
|
|
19973
|
+
}
|
|
19974
|
+
}
|
|
19975
|
+
}
|
|
18843
19976
|
function getServerInstructions(host) {
|
|
18844
19977
|
const hostText = `host ${host}`;
|
|
18845
|
-
return `This MCP server is the preferred codebase-understanding path for ${hostText}. Start a repository task with index_status when index readiness or freshness is unknown. Use codebase_context as the preferred first entry point because it returns a token-budgeted location pack and routes to definitions or call-graph helpers when symbol intent is present. Keep the default tokenBudget for normal discovery, then use implementation_lookup, codebase_search, or a targeted file read only for selected locations that need source content. Use codebase_peek for direct conceptual location lookup. For exact identifiers or exhaustive matches, use grep. After identifying symbols, use call_graph or call_graph_path to trace dependencies. If the index is unavailable, run index_codebase, then retry the retrieval tool.`;
|
|
19978
|
+
return `This MCP server is the preferred codebase-understanding path for ${hostText}. Start a repository task with index_status when index readiness or freshness is unknown. Use codebase_context as the preferred first entry point because it returns a token-budgeted location pack and routes to definitions or call-graph helpers when symbol intent is present. For code changes with a known or suspected symbol target, optionally call codebase_edit_context as a compact pre-edit step for bounded source plus direct callers and callees before broad file reads. Keep the default tokenBudget for normal discovery, then use implementation_lookup, codebase_search, or a targeted file read only for selected locations that need source content. Use codebase_peek for direct conceptual location lookup. For exact identifiers or exhaustive matches, use grep. After identifying symbols, use call_graph or call_graph_path to trace dependencies. If the index is unavailable, run index_codebase, then retry the retrieval tool.`;
|
|
19979
|
+
}
|
|
19980
|
+
function configureMcpBackgroundWorker(projectRoot, config, host, watcherFactory, watcherFactoryForConfig) {
|
|
19981
|
+
if (!getProjectSafety(projectRoot, config).safeToRun) {
|
|
19982
|
+
return { managesWorker: false };
|
|
19983
|
+
}
|
|
19984
|
+
if (isBackgroundWorkerManaged(projectRoot, host)) {
|
|
19985
|
+
const key = getBackgroundWorkerProjectKey(projectRoot, host);
|
|
19986
|
+
if ((mcpWorkerReferences.get(key) ?? 0) === 0 && !mcpWorkerTeardowns.has(key)) {
|
|
19987
|
+
return { managesWorker: false };
|
|
19988
|
+
}
|
|
19989
|
+
if (watcherFactory !== void 0) {
|
|
19990
|
+
attachBackgroundWorkerWatcher(projectRoot, host, watcherFactory, watcherFactoryForConfig);
|
|
19991
|
+
}
|
|
19992
|
+
if (mcpWorkerTeardowns.has(key) || isBackgroundWorkerStopping(projectRoot, host)) {
|
|
19993
|
+
requestBackgroundWorker(projectRoot, host);
|
|
19994
|
+
}
|
|
19995
|
+
return { managesWorker: true };
|
|
19996
|
+
}
|
|
19997
|
+
configureBackgroundWorker(projectRoot, host, config, {
|
|
19998
|
+
startAutoIndex: (source, allowDisabledAutoIndex) => {
|
|
19999
|
+
startAutoIndexForBackgroundWorker(projectRoot, host, source, allowDisabledAutoIndex);
|
|
20000
|
+
},
|
|
20001
|
+
stopAutoIndex: () => stopAutoIndexForBackgroundWorker(projectRoot, host),
|
|
20002
|
+
watcherFactory,
|
|
20003
|
+
watcherFactoryForConfig
|
|
20004
|
+
});
|
|
20005
|
+
return { managesWorker: true };
|
|
20006
|
+
}
|
|
20007
|
+
function attachMcpBackgroundWatcher(projectRoot, config, host, watcherFactory, watcherFactoryForConfig) {
|
|
20008
|
+
configureMcpBackgroundWorker(projectRoot, config, host, watcherFactory, watcherFactoryForConfig);
|
|
20009
|
+
return waitForBackgroundWorkerStart(projectRoot, host);
|
|
18846
20010
|
}
|
|
18847
20011
|
function createMcpServer(projectRoot, config, host) {
|
|
18848
20012
|
const server = new import_mcp.McpServer({
|
|
@@ -18851,11 +20015,14 @@ function createMcpServer(projectRoot, config, host) {
|
|
|
18851
20015
|
}, {
|
|
18852
20016
|
instructions: getServerInstructions(host)
|
|
18853
20017
|
});
|
|
18854
|
-
initializeTools(projectRoot, config, host);
|
|
18855
|
-
|
|
20018
|
+
initializeTools(projectRoot, config, host, { preserveManagedWorker: true });
|
|
20019
|
+
const backgroundWorker = configureMcpBackgroundWorker(projectRoot, config, host);
|
|
20020
|
+
if (backgroundWorker.managesWorker) {
|
|
20021
|
+
retainMcpBackgroundWorker(projectRoot, host);
|
|
20022
|
+
}
|
|
18856
20023
|
let stopCoordinationPromise = null;
|
|
18857
20024
|
const stopCoordination = () => {
|
|
18858
|
-
stopCoordinationPromise ??=
|
|
20025
|
+
stopCoordinationPromise ??= backgroundWorker.managesWorker ? releaseMcpBackgroundWorker(projectRoot, host) : Promise.resolve();
|
|
18859
20026
|
return stopCoordinationPromise;
|
|
18860
20027
|
};
|
|
18861
20028
|
const closeProtocol = server.server.close.bind(server.server);
|
|
@@ -18871,7 +20038,9 @@ function createMcpServer(projectRoot, config, host) {
|
|
|
18871
20038
|
const onServerClose = server.server.onclose;
|
|
18872
20039
|
server.server.onclose = () => {
|
|
18873
20040
|
onServerClose?.();
|
|
18874
|
-
void stopCoordination()
|
|
20041
|
+
void stopCoordination().catch((error) => {
|
|
20042
|
+
console.error("[codebase-index] Failed to stop MCP background worker after transport close:", error);
|
|
20043
|
+
});
|
|
18875
20044
|
};
|
|
18876
20045
|
registerMcpTools(server, {
|
|
18877
20046
|
projectRoot,
|
|
@@ -18886,7 +20055,7 @@ var import_fs19 = require("fs");
|
|
|
18886
20055
|
|
|
18887
20056
|
// node_modules/chokidar/index.js
|
|
18888
20057
|
var import_node_events = require("events");
|
|
18889
|
-
var
|
|
20058
|
+
var import_node_fs3 = require("fs");
|
|
18890
20059
|
var import_promises3 = require("fs/promises");
|
|
18891
20060
|
var sp2 = __toESM(require("path"), 1);
|
|
18892
20061
|
|
|
@@ -18974,7 +20143,7 @@ var ReaddirpStream = class extends import_node_stream.Readable {
|
|
|
18974
20143
|
this._directoryFilter = normalizeFilter(opts.directoryFilter);
|
|
18975
20144
|
const statMethod = opts.lstat ? import_promises.lstat : import_promises.stat;
|
|
18976
20145
|
if (wantBigintFsStats) {
|
|
18977
|
-
this._stat = (
|
|
20146
|
+
this._stat = (path34) => statMethod(path34, { bigint: true });
|
|
18978
20147
|
} else {
|
|
18979
20148
|
this._stat = statMethod;
|
|
18980
20149
|
}
|
|
@@ -18999,8 +20168,8 @@ var ReaddirpStream = class extends import_node_stream.Readable {
|
|
|
18999
20168
|
const par = this.parent;
|
|
19000
20169
|
const fil = par && par.files;
|
|
19001
20170
|
if (fil && fil.length > 0) {
|
|
19002
|
-
const { path:
|
|
19003
|
-
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent,
|
|
20171
|
+
const { path: path34, depth } = par;
|
|
20172
|
+
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path34));
|
|
19004
20173
|
const awaited = await Promise.all(slice);
|
|
19005
20174
|
for (const entry of awaited) {
|
|
19006
20175
|
if (!entry)
|
|
@@ -19040,21 +20209,21 @@ var ReaddirpStream = class extends import_node_stream.Readable {
|
|
|
19040
20209
|
this.reading = false;
|
|
19041
20210
|
}
|
|
19042
20211
|
}
|
|
19043
|
-
async _exploreDir(
|
|
20212
|
+
async _exploreDir(path34, depth) {
|
|
19044
20213
|
let files;
|
|
19045
20214
|
try {
|
|
19046
|
-
files = await (0, import_promises.readdir)(
|
|
20215
|
+
files = await (0, import_promises.readdir)(path34, this._rdOptions);
|
|
19047
20216
|
} catch (error) {
|
|
19048
20217
|
this._onError(error);
|
|
19049
20218
|
}
|
|
19050
|
-
return { files, depth, path:
|
|
20219
|
+
return { files, depth, path: path34 };
|
|
19051
20220
|
}
|
|
19052
|
-
async _formatEntry(dirent,
|
|
20221
|
+
async _formatEntry(dirent, path34) {
|
|
19053
20222
|
let entry;
|
|
19054
|
-
const
|
|
20223
|
+
const basename9 = this._isDirent ? dirent.name : dirent;
|
|
19055
20224
|
try {
|
|
19056
|
-
const fullPath = (0, import_node_path.resolve)((0, import_node_path.join)(
|
|
19057
|
-
entry = { path: (0, import_node_path.relative)(this._root, fullPath), fullPath, basename:
|
|
20225
|
+
const fullPath = (0, import_node_path.resolve)((0, import_node_path.join)(path34, basename9));
|
|
20226
|
+
entry = { path: (0, import_node_path.relative)(this._root, fullPath), fullPath, basename: basename9 };
|
|
19058
20227
|
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
19059
20228
|
} catch (err) {
|
|
19060
20229
|
this._onError(err);
|
|
@@ -19124,7 +20293,7 @@ function readdirp(root, options = {}) {
|
|
|
19124
20293
|
}
|
|
19125
20294
|
|
|
19126
20295
|
// node_modules/chokidar/handler.js
|
|
19127
|
-
var
|
|
20296
|
+
var import_node_fs2 = require("fs");
|
|
19128
20297
|
var import_promises2 = require("fs/promises");
|
|
19129
20298
|
var import_node_os = require("os");
|
|
19130
20299
|
var sp = __toESM(require("path"), 1);
|
|
@@ -19453,16 +20622,16 @@ var delFromSet = (main, prop, item) => {
|
|
|
19453
20622
|
};
|
|
19454
20623
|
var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
|
|
19455
20624
|
var FsWatchInstances = /* @__PURE__ */ new Map();
|
|
19456
|
-
function createFsWatchInstance(
|
|
20625
|
+
function createFsWatchInstance(path34, options, listener, errHandler, emitRaw) {
|
|
19457
20626
|
const handleEvent = (rawEvent, evPath) => {
|
|
19458
|
-
listener(
|
|
19459
|
-
emitRaw(rawEvent, evPath, { watchedPath:
|
|
19460
|
-
if (evPath &&
|
|
19461
|
-
fsWatchBroadcast(sp.resolve(
|
|
20627
|
+
listener(path34);
|
|
20628
|
+
emitRaw(rawEvent, evPath, { watchedPath: path34 });
|
|
20629
|
+
if (evPath && path34 !== evPath) {
|
|
20630
|
+
fsWatchBroadcast(sp.resolve(path34, evPath), KEY_LISTENERS, sp.join(path34, evPath));
|
|
19462
20631
|
}
|
|
19463
20632
|
};
|
|
19464
20633
|
try {
|
|
19465
|
-
return (0,
|
|
20634
|
+
return (0, import_node_fs2.watch)(path34, {
|
|
19466
20635
|
persistent: options.persistent
|
|
19467
20636
|
}, handleEvent);
|
|
19468
20637
|
} catch (error) {
|
|
@@ -19478,12 +20647,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
|
|
|
19478
20647
|
listener(val1, val2, val3);
|
|
19479
20648
|
});
|
|
19480
20649
|
};
|
|
19481
|
-
var setFsWatchListener = (
|
|
20650
|
+
var setFsWatchListener = (path34, fullPath, options, handlers) => {
|
|
19482
20651
|
const { listener, errHandler, rawEmitter } = handlers;
|
|
19483
20652
|
let cont = FsWatchInstances.get(fullPath);
|
|
19484
20653
|
let watcher;
|
|
19485
20654
|
if (!options.persistent) {
|
|
19486
|
-
watcher = createFsWatchInstance(
|
|
20655
|
+
watcher = createFsWatchInstance(path34, options, listener, errHandler, rawEmitter);
|
|
19487
20656
|
if (!watcher)
|
|
19488
20657
|
return;
|
|
19489
20658
|
return watcher.close.bind(watcher);
|
|
@@ -19494,7 +20663,7 @@ var setFsWatchListener = (path33, fullPath, options, handlers) => {
|
|
|
19494
20663
|
addAndConvert(cont, KEY_RAW, rawEmitter);
|
|
19495
20664
|
} else {
|
|
19496
20665
|
watcher = createFsWatchInstance(
|
|
19497
|
-
|
|
20666
|
+
path34,
|
|
19498
20667
|
options,
|
|
19499
20668
|
fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
|
|
19500
20669
|
errHandler,
|
|
@@ -19509,7 +20678,7 @@ var setFsWatchListener = (path33, fullPath, options, handlers) => {
|
|
|
19509
20678
|
cont.watcherUnusable = true;
|
|
19510
20679
|
if (isWindows && error.code === "EPERM") {
|
|
19511
20680
|
try {
|
|
19512
|
-
const fd = await (0, import_promises2.open)(
|
|
20681
|
+
const fd = await (0, import_promises2.open)(path34, "r");
|
|
19513
20682
|
await fd.close();
|
|
19514
20683
|
broadcastErr(error);
|
|
19515
20684
|
} catch (err) {
|
|
@@ -19540,12 +20709,12 @@ var setFsWatchListener = (path33, fullPath, options, handlers) => {
|
|
|
19540
20709
|
};
|
|
19541
20710
|
};
|
|
19542
20711
|
var FsWatchFileInstances = /* @__PURE__ */ new Map();
|
|
19543
|
-
var setFsWatchFileListener = (
|
|
20712
|
+
var setFsWatchFileListener = (path34, fullPath, options, handlers) => {
|
|
19544
20713
|
const { listener, rawEmitter } = handlers;
|
|
19545
20714
|
let cont = FsWatchFileInstances.get(fullPath);
|
|
19546
20715
|
const copts = cont && cont.options;
|
|
19547
20716
|
if (copts && (copts.persistent < options.persistent || copts.interval > options.interval)) {
|
|
19548
|
-
(0,
|
|
20717
|
+
(0, import_node_fs2.unwatchFile)(fullPath);
|
|
19549
20718
|
cont = void 0;
|
|
19550
20719
|
}
|
|
19551
20720
|
if (cont) {
|
|
@@ -19556,13 +20725,13 @@ var setFsWatchFileListener = (path33, fullPath, options, handlers) => {
|
|
|
19556
20725
|
listeners: listener,
|
|
19557
20726
|
rawEmitters: rawEmitter,
|
|
19558
20727
|
options,
|
|
19559
|
-
watcher: (0,
|
|
20728
|
+
watcher: (0, import_node_fs2.watchFile)(fullPath, options, (curr, prev) => {
|
|
19560
20729
|
foreach(cont.rawEmitters, (rawEmitter2) => {
|
|
19561
20730
|
rawEmitter2(EV.CHANGE, fullPath, { curr, prev });
|
|
19562
20731
|
});
|
|
19563
20732
|
const currmtime = curr.mtimeMs;
|
|
19564
20733
|
if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
|
|
19565
|
-
foreach(cont.listeners, (listener2) => listener2(
|
|
20734
|
+
foreach(cont.listeners, (listener2) => listener2(path34, curr));
|
|
19566
20735
|
}
|
|
19567
20736
|
})
|
|
19568
20737
|
};
|
|
@@ -19573,7 +20742,7 @@ var setFsWatchFileListener = (path33, fullPath, options, handlers) => {
|
|
|
19573
20742
|
delFromSet(cont, KEY_RAW, rawEmitter);
|
|
19574
20743
|
if (isEmptySet(cont.listeners)) {
|
|
19575
20744
|
FsWatchFileInstances.delete(fullPath);
|
|
19576
|
-
(0,
|
|
20745
|
+
(0, import_node_fs2.unwatchFile)(fullPath);
|
|
19577
20746
|
cont.options = cont.watcher = void 0;
|
|
19578
20747
|
Object.freeze(cont);
|
|
19579
20748
|
}
|
|
@@ -19592,13 +20761,13 @@ var NodeFsHandler = class {
|
|
|
19592
20761
|
* @param listener on fs change
|
|
19593
20762
|
* @returns closer for the watcher instance
|
|
19594
20763
|
*/
|
|
19595
|
-
_watchWithNodeFs(
|
|
20764
|
+
_watchWithNodeFs(path34, listener) {
|
|
19596
20765
|
const opts = this.fsw.options;
|
|
19597
|
-
const directory = sp.dirname(
|
|
19598
|
-
const
|
|
20766
|
+
const directory = sp.dirname(path34);
|
|
20767
|
+
const basename9 = sp.basename(path34);
|
|
19599
20768
|
const parent = this.fsw._getWatchedDir(directory);
|
|
19600
|
-
parent.add(
|
|
19601
|
-
const absolutePath = sp.resolve(
|
|
20769
|
+
parent.add(basename9);
|
|
20770
|
+
const absolutePath = sp.resolve(path34);
|
|
19602
20771
|
const options = {
|
|
19603
20772
|
persistent: opts.persistent
|
|
19604
20773
|
};
|
|
@@ -19607,13 +20776,13 @@ var NodeFsHandler = class {
|
|
|
19607
20776
|
let closer;
|
|
19608
20777
|
if (opts.usePolling) {
|
|
19609
20778
|
const enableBin = opts.interval !== opts.binaryInterval;
|
|
19610
|
-
options.interval = enableBin && isBinaryPath(
|
|
19611
|
-
closer = setFsWatchFileListener(
|
|
20779
|
+
options.interval = enableBin && isBinaryPath(basename9) ? opts.binaryInterval : opts.interval;
|
|
20780
|
+
closer = setFsWatchFileListener(path34, absolutePath, options, {
|
|
19612
20781
|
listener,
|
|
19613
20782
|
rawEmitter: this.fsw._emitRaw
|
|
19614
20783
|
});
|
|
19615
20784
|
} else {
|
|
19616
|
-
closer = setFsWatchListener(
|
|
20785
|
+
closer = setFsWatchListener(path34, absolutePath, options, {
|
|
19617
20786
|
listener,
|
|
19618
20787
|
errHandler: this._boundHandleError,
|
|
19619
20788
|
rawEmitter: this.fsw._emitRaw
|
|
@@ -19629,13 +20798,13 @@ var NodeFsHandler = class {
|
|
|
19629
20798
|
if (this.fsw.closed) {
|
|
19630
20799
|
return;
|
|
19631
20800
|
}
|
|
19632
|
-
const
|
|
19633
|
-
const
|
|
19634
|
-
const parent = this.fsw._getWatchedDir(
|
|
20801
|
+
const dirname16 = sp.dirname(file);
|
|
20802
|
+
const basename9 = sp.basename(file);
|
|
20803
|
+
const parent = this.fsw._getWatchedDir(dirname16);
|
|
19635
20804
|
let prevStats = stats;
|
|
19636
|
-
if (parent.has(
|
|
20805
|
+
if (parent.has(basename9))
|
|
19637
20806
|
return;
|
|
19638
|
-
const listener = async (
|
|
20807
|
+
const listener = async (path34, newStats) => {
|
|
19639
20808
|
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
|
|
19640
20809
|
return;
|
|
19641
20810
|
if (!newStats || newStats.mtimeMs === 0) {
|
|
@@ -19649,18 +20818,18 @@ var NodeFsHandler = class {
|
|
|
19649
20818
|
this.fsw._emit(EV.CHANGE, file, newStats2);
|
|
19650
20819
|
}
|
|
19651
20820
|
if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
|
|
19652
|
-
this.fsw._closeFile(
|
|
20821
|
+
this.fsw._closeFile(path34);
|
|
19653
20822
|
prevStats = newStats2;
|
|
19654
20823
|
const closer2 = this._watchWithNodeFs(file, listener);
|
|
19655
20824
|
if (closer2)
|
|
19656
|
-
this.fsw._addPathCloser(
|
|
20825
|
+
this.fsw._addPathCloser(path34, closer2);
|
|
19657
20826
|
} else {
|
|
19658
20827
|
prevStats = newStats2;
|
|
19659
20828
|
}
|
|
19660
20829
|
} catch (error) {
|
|
19661
|
-
this.fsw._remove(
|
|
20830
|
+
this.fsw._remove(dirname16, basename9);
|
|
19662
20831
|
}
|
|
19663
|
-
} else if (parent.has(
|
|
20832
|
+
} else if (parent.has(basename9)) {
|
|
19664
20833
|
const at = newStats.atimeMs;
|
|
19665
20834
|
const mt = newStats.mtimeMs;
|
|
19666
20835
|
if (!at || at <= mt || mt !== prevStats.mtimeMs) {
|
|
@@ -19685,7 +20854,7 @@ var NodeFsHandler = class {
|
|
|
19685
20854
|
* @param item basename of this item
|
|
19686
20855
|
* @returns true if no more processing is needed for this entry.
|
|
19687
20856
|
*/
|
|
19688
|
-
async _handleSymlink(entry, directory,
|
|
20857
|
+
async _handleSymlink(entry, directory, path34, item) {
|
|
19689
20858
|
if (this.fsw.closed) {
|
|
19690
20859
|
return;
|
|
19691
20860
|
}
|
|
@@ -19695,7 +20864,7 @@ var NodeFsHandler = class {
|
|
|
19695
20864
|
this.fsw._incrReadyCount();
|
|
19696
20865
|
let linkPath;
|
|
19697
20866
|
try {
|
|
19698
|
-
linkPath = await (0, import_promises2.realpath)(
|
|
20867
|
+
linkPath = await (0, import_promises2.realpath)(path34);
|
|
19699
20868
|
} catch (e) {
|
|
19700
20869
|
this.fsw._emitReady();
|
|
19701
20870
|
return true;
|
|
@@ -19705,12 +20874,12 @@ var NodeFsHandler = class {
|
|
|
19705
20874
|
if (dir.has(item)) {
|
|
19706
20875
|
if (this.fsw._symlinkPaths.get(full) !== linkPath) {
|
|
19707
20876
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
19708
|
-
this.fsw._emit(EV.CHANGE,
|
|
20877
|
+
this.fsw._emit(EV.CHANGE, path34, entry.stats);
|
|
19709
20878
|
}
|
|
19710
20879
|
} else {
|
|
19711
20880
|
dir.add(item);
|
|
19712
20881
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
19713
|
-
this.fsw._emit(EV.ADD,
|
|
20882
|
+
this.fsw._emit(EV.ADD, path34, entry.stats);
|
|
19714
20883
|
}
|
|
19715
20884
|
this.fsw._emitReady();
|
|
19716
20885
|
return true;
|
|
@@ -19740,9 +20909,9 @@ var NodeFsHandler = class {
|
|
|
19740
20909
|
return;
|
|
19741
20910
|
}
|
|
19742
20911
|
const item = entry.path;
|
|
19743
|
-
let
|
|
20912
|
+
let path34 = sp.join(directory, item);
|
|
19744
20913
|
current.add(item);
|
|
19745
|
-
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory,
|
|
20914
|
+
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path34, item)) {
|
|
19746
20915
|
return;
|
|
19747
20916
|
}
|
|
19748
20917
|
if (this.fsw.closed) {
|
|
@@ -19751,11 +20920,11 @@ var NodeFsHandler = class {
|
|
|
19751
20920
|
}
|
|
19752
20921
|
if (item === target || !target && !previous.has(item)) {
|
|
19753
20922
|
this.fsw._incrReadyCount();
|
|
19754
|
-
|
|
19755
|
-
this._addToNodeFs(
|
|
20923
|
+
path34 = sp.join(dir, sp.relative(dir, path34));
|
|
20924
|
+
this._addToNodeFs(path34, initialAdd, wh, depth + 1);
|
|
19756
20925
|
}
|
|
19757
20926
|
}).on(EV.ERROR, this._boundHandleError);
|
|
19758
|
-
return new Promise((
|
|
20927
|
+
return new Promise((resolve21, reject) => {
|
|
19759
20928
|
if (!stream)
|
|
19760
20929
|
return reject();
|
|
19761
20930
|
stream.once(STR_END, () => {
|
|
@@ -19764,7 +20933,7 @@ var NodeFsHandler = class {
|
|
|
19764
20933
|
return;
|
|
19765
20934
|
}
|
|
19766
20935
|
const wasThrottled = throttler ? throttler.clear() : false;
|
|
19767
|
-
|
|
20936
|
+
resolve21(void 0);
|
|
19768
20937
|
previous.getChildren().filter((item) => {
|
|
19769
20938
|
return item !== directory && !current.has(item);
|
|
19770
20939
|
}).forEach((item) => {
|
|
@@ -19821,13 +20990,13 @@ var NodeFsHandler = class {
|
|
|
19821
20990
|
* @param depth Child path actually targeted for watch
|
|
19822
20991
|
* @param target Child path actually targeted for watch
|
|
19823
20992
|
*/
|
|
19824
|
-
async _addToNodeFs(
|
|
20993
|
+
async _addToNodeFs(path34, initialAdd, priorWh, depth, target) {
|
|
19825
20994
|
const ready = this.fsw._emitReady;
|
|
19826
|
-
if (this.fsw._isIgnored(
|
|
20995
|
+
if (this.fsw._isIgnored(path34) || this.fsw.closed) {
|
|
19827
20996
|
ready();
|
|
19828
20997
|
return false;
|
|
19829
20998
|
}
|
|
19830
|
-
const wh = this.fsw._getWatchHelpers(
|
|
20999
|
+
const wh = this.fsw._getWatchHelpers(path34);
|
|
19831
21000
|
if (priorWh) {
|
|
19832
21001
|
wh.filterPath = (entry) => priorWh.filterPath(entry);
|
|
19833
21002
|
wh.filterDir = (entry) => priorWh.filterDir(entry);
|
|
@@ -19843,8 +21012,8 @@ var NodeFsHandler = class {
|
|
|
19843
21012
|
const follow = this.fsw.options.followSymlinks;
|
|
19844
21013
|
let closer;
|
|
19845
21014
|
if (stats.isDirectory()) {
|
|
19846
|
-
const absPath = sp.resolve(
|
|
19847
|
-
const targetPath = follow ? await (0, import_promises2.realpath)(
|
|
21015
|
+
const absPath = sp.resolve(path34);
|
|
21016
|
+
const targetPath = follow ? await (0, import_promises2.realpath)(path34) : path34;
|
|
19848
21017
|
if (this.fsw.closed)
|
|
19849
21018
|
return;
|
|
19850
21019
|
closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
|
|
@@ -19854,29 +21023,29 @@ var NodeFsHandler = class {
|
|
|
19854
21023
|
this.fsw._symlinkPaths.set(absPath, targetPath);
|
|
19855
21024
|
}
|
|
19856
21025
|
} else if (stats.isSymbolicLink()) {
|
|
19857
|
-
const targetPath = follow ? await (0, import_promises2.realpath)(
|
|
21026
|
+
const targetPath = follow ? await (0, import_promises2.realpath)(path34) : path34;
|
|
19858
21027
|
if (this.fsw.closed)
|
|
19859
21028
|
return;
|
|
19860
21029
|
const parent = sp.dirname(wh.watchPath);
|
|
19861
21030
|
this.fsw._getWatchedDir(parent).add(wh.watchPath);
|
|
19862
21031
|
this.fsw._emit(EV.ADD, wh.watchPath, stats);
|
|
19863
|
-
closer = await this._handleDir(parent, stats, initialAdd, depth,
|
|
21032
|
+
closer = await this._handleDir(parent, stats, initialAdd, depth, path34, wh, targetPath);
|
|
19864
21033
|
if (this.fsw.closed)
|
|
19865
21034
|
return;
|
|
19866
21035
|
if (targetPath !== void 0) {
|
|
19867
|
-
this.fsw._symlinkPaths.set(sp.resolve(
|
|
21036
|
+
this.fsw._symlinkPaths.set(sp.resolve(path34), targetPath);
|
|
19868
21037
|
}
|
|
19869
21038
|
} else {
|
|
19870
21039
|
closer = this._handleFile(wh.watchPath, stats, initialAdd);
|
|
19871
21040
|
}
|
|
19872
21041
|
ready();
|
|
19873
21042
|
if (closer)
|
|
19874
|
-
this.fsw._addPathCloser(
|
|
21043
|
+
this.fsw._addPathCloser(path34, closer);
|
|
19875
21044
|
return false;
|
|
19876
21045
|
} catch (error) {
|
|
19877
21046
|
if (this.fsw._handleError(error)) {
|
|
19878
21047
|
ready();
|
|
19879
|
-
return
|
|
21048
|
+
return path34;
|
|
19880
21049
|
}
|
|
19881
21050
|
}
|
|
19882
21051
|
}
|
|
@@ -19919,24 +21088,24 @@ function createPattern(matcher) {
|
|
|
19919
21088
|
}
|
|
19920
21089
|
return () => false;
|
|
19921
21090
|
}
|
|
19922
|
-
function normalizePath3(
|
|
19923
|
-
if (typeof
|
|
21091
|
+
function normalizePath3(path34) {
|
|
21092
|
+
if (typeof path34 !== "string")
|
|
19924
21093
|
throw new Error("string expected");
|
|
19925
|
-
|
|
19926
|
-
|
|
21094
|
+
path34 = sp2.normalize(path34);
|
|
21095
|
+
path34 = path34.replace(/\\/g, "/");
|
|
19927
21096
|
let prepend = false;
|
|
19928
|
-
if (
|
|
21097
|
+
if (path34.startsWith("//"))
|
|
19929
21098
|
prepend = true;
|
|
19930
|
-
|
|
21099
|
+
path34 = path34.replace(DOUBLE_SLASH_RE, "/");
|
|
19931
21100
|
if (prepend)
|
|
19932
|
-
|
|
19933
|
-
return
|
|
21101
|
+
path34 = "/" + path34;
|
|
21102
|
+
return path34;
|
|
19934
21103
|
}
|
|
19935
21104
|
function matchPatterns(patterns, testString, stats) {
|
|
19936
|
-
const
|
|
21105
|
+
const path34 = normalizePath3(testString);
|
|
19937
21106
|
for (let index = 0; index < patterns.length; index++) {
|
|
19938
21107
|
const pattern = patterns[index];
|
|
19939
|
-
if (pattern(
|
|
21108
|
+
if (pattern(path34, stats)) {
|
|
19940
21109
|
return true;
|
|
19941
21110
|
}
|
|
19942
21111
|
}
|
|
@@ -19974,19 +21143,19 @@ var toUnix = (string) => {
|
|
|
19974
21143
|
}
|
|
19975
21144
|
return str;
|
|
19976
21145
|
};
|
|
19977
|
-
var normalizePathToUnix = (
|
|
19978
|
-
var normalizeIgnored = (cwd = "") => (
|
|
19979
|
-
if (typeof
|
|
19980
|
-
return normalizePathToUnix(sp2.isAbsolute(
|
|
21146
|
+
var normalizePathToUnix = (path34) => toUnix(sp2.normalize(toUnix(path34)));
|
|
21147
|
+
var normalizeIgnored = (cwd = "") => (path34) => {
|
|
21148
|
+
if (typeof path34 === "string") {
|
|
21149
|
+
return normalizePathToUnix(sp2.isAbsolute(path34) ? path34 : sp2.join(cwd, path34));
|
|
19981
21150
|
} else {
|
|
19982
|
-
return
|
|
21151
|
+
return path34;
|
|
19983
21152
|
}
|
|
19984
21153
|
};
|
|
19985
|
-
var getAbsolutePath = (
|
|
19986
|
-
if (sp2.isAbsolute(
|
|
19987
|
-
return
|
|
21154
|
+
var getAbsolutePath = (path34, cwd) => {
|
|
21155
|
+
if (sp2.isAbsolute(path34)) {
|
|
21156
|
+
return path34;
|
|
19988
21157
|
}
|
|
19989
|
-
return sp2.join(cwd,
|
|
21158
|
+
return sp2.join(cwd, path34);
|
|
19990
21159
|
};
|
|
19991
21160
|
var EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
|
|
19992
21161
|
var DirEntry = class {
|
|
@@ -20051,10 +21220,10 @@ var WatchHelper = class {
|
|
|
20051
21220
|
dirParts;
|
|
20052
21221
|
followSymlinks;
|
|
20053
21222
|
statMethod;
|
|
20054
|
-
constructor(
|
|
21223
|
+
constructor(path34, follow, fsw) {
|
|
20055
21224
|
this.fsw = fsw;
|
|
20056
|
-
const watchPath =
|
|
20057
|
-
this.path =
|
|
21225
|
+
const watchPath = path34;
|
|
21226
|
+
this.path = path34 = path34.replace(REPLACER_RE, "");
|
|
20058
21227
|
this.watchPath = watchPath;
|
|
20059
21228
|
this.fullWatchPath = sp2.resolve(watchPath);
|
|
20060
21229
|
this.dirParts = [];
|
|
@@ -20194,20 +21363,20 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
20194
21363
|
this._closePromise = void 0;
|
|
20195
21364
|
let paths = unifyPaths(paths_);
|
|
20196
21365
|
if (cwd) {
|
|
20197
|
-
paths = paths.map((
|
|
20198
|
-
const absPath = getAbsolutePath(
|
|
21366
|
+
paths = paths.map((path34) => {
|
|
21367
|
+
const absPath = getAbsolutePath(path34, cwd);
|
|
20199
21368
|
return absPath;
|
|
20200
21369
|
});
|
|
20201
21370
|
}
|
|
20202
|
-
paths.forEach((
|
|
20203
|
-
this._removeIgnoredPath(
|
|
21371
|
+
paths.forEach((path34) => {
|
|
21372
|
+
this._removeIgnoredPath(path34);
|
|
20204
21373
|
});
|
|
20205
21374
|
this._userIgnored = void 0;
|
|
20206
21375
|
if (!this._readyCount)
|
|
20207
21376
|
this._readyCount = 0;
|
|
20208
21377
|
this._readyCount += paths.length;
|
|
20209
|
-
Promise.all(paths.map(async (
|
|
20210
|
-
const res = await this._nodeFsHandler._addToNodeFs(
|
|
21378
|
+
Promise.all(paths.map(async (path34) => {
|
|
21379
|
+
const res = await this._nodeFsHandler._addToNodeFs(path34, !_internal, void 0, 0, _origAdd);
|
|
20211
21380
|
if (res)
|
|
20212
21381
|
this._emitReady();
|
|
20213
21382
|
return res;
|
|
@@ -20229,17 +21398,17 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
20229
21398
|
return this;
|
|
20230
21399
|
const paths = unifyPaths(paths_);
|
|
20231
21400
|
const { cwd } = this.options;
|
|
20232
|
-
paths.forEach((
|
|
20233
|
-
if (!sp2.isAbsolute(
|
|
21401
|
+
paths.forEach((path34) => {
|
|
21402
|
+
if (!sp2.isAbsolute(path34) && !this._closers.has(path34)) {
|
|
20234
21403
|
if (cwd)
|
|
20235
|
-
|
|
20236
|
-
|
|
21404
|
+
path34 = sp2.join(cwd, path34);
|
|
21405
|
+
path34 = sp2.resolve(path34);
|
|
20237
21406
|
}
|
|
20238
|
-
this._closePath(
|
|
20239
|
-
this._addIgnoredPath(
|
|
20240
|
-
if (this._watched.has(
|
|
21407
|
+
this._closePath(path34);
|
|
21408
|
+
this._addIgnoredPath(path34);
|
|
21409
|
+
if (this._watched.has(path34)) {
|
|
20241
21410
|
this._addIgnoredPath({
|
|
20242
|
-
path:
|
|
21411
|
+
path: path34,
|
|
20243
21412
|
recursive: true
|
|
20244
21413
|
});
|
|
20245
21414
|
}
|
|
@@ -20303,38 +21472,38 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
20303
21472
|
* @param stats arguments to be passed with event
|
|
20304
21473
|
* @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
|
|
20305
21474
|
*/
|
|
20306
|
-
async _emit(event,
|
|
21475
|
+
async _emit(event, path34, stats) {
|
|
20307
21476
|
if (this.closed)
|
|
20308
21477
|
return;
|
|
20309
21478
|
const opts = this.options;
|
|
20310
21479
|
if (isWindows)
|
|
20311
|
-
|
|
21480
|
+
path34 = sp2.normalize(path34);
|
|
20312
21481
|
if (opts.cwd)
|
|
20313
|
-
|
|
20314
|
-
const args = [
|
|
21482
|
+
path34 = sp2.relative(opts.cwd, path34);
|
|
21483
|
+
const args = [path34];
|
|
20315
21484
|
if (stats != null)
|
|
20316
21485
|
args.push(stats);
|
|
20317
21486
|
const awf = opts.awaitWriteFinish;
|
|
20318
21487
|
let pw;
|
|
20319
|
-
if (awf && (pw = this._pendingWrites.get(
|
|
21488
|
+
if (awf && (pw = this._pendingWrites.get(path34))) {
|
|
20320
21489
|
pw.lastChange = /* @__PURE__ */ new Date();
|
|
20321
21490
|
return this;
|
|
20322
21491
|
}
|
|
20323
21492
|
if (opts.atomic) {
|
|
20324
21493
|
if (event === EVENTS.UNLINK) {
|
|
20325
|
-
this._pendingUnlinks.set(
|
|
21494
|
+
this._pendingUnlinks.set(path34, [event, ...args]);
|
|
20326
21495
|
setTimeout(() => {
|
|
20327
|
-
this._pendingUnlinks.forEach((entry,
|
|
21496
|
+
this._pendingUnlinks.forEach((entry, path35) => {
|
|
20328
21497
|
this.emit(...entry);
|
|
20329
21498
|
this.emit(EVENTS.ALL, ...entry);
|
|
20330
|
-
this._pendingUnlinks.delete(
|
|
21499
|
+
this._pendingUnlinks.delete(path35);
|
|
20331
21500
|
});
|
|
20332
21501
|
}, typeof opts.atomic === "number" ? opts.atomic : 100);
|
|
20333
21502
|
return this;
|
|
20334
21503
|
}
|
|
20335
|
-
if (event === EVENTS.ADD && this._pendingUnlinks.has(
|
|
21504
|
+
if (event === EVENTS.ADD && this._pendingUnlinks.has(path34)) {
|
|
20336
21505
|
event = EVENTS.CHANGE;
|
|
20337
|
-
this._pendingUnlinks.delete(
|
|
21506
|
+
this._pendingUnlinks.delete(path34);
|
|
20338
21507
|
}
|
|
20339
21508
|
}
|
|
20340
21509
|
if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
|
|
@@ -20352,16 +21521,16 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
20352
21521
|
this.emitWithAll(event, args);
|
|
20353
21522
|
}
|
|
20354
21523
|
};
|
|
20355
|
-
this._awaitWriteFinish(
|
|
21524
|
+
this._awaitWriteFinish(path34, awf.stabilityThreshold, event, awfEmit);
|
|
20356
21525
|
return this;
|
|
20357
21526
|
}
|
|
20358
21527
|
if (event === EVENTS.CHANGE) {
|
|
20359
|
-
const isThrottled = !this._throttle(EVENTS.CHANGE,
|
|
21528
|
+
const isThrottled = !this._throttle(EVENTS.CHANGE, path34, 50);
|
|
20360
21529
|
if (isThrottled)
|
|
20361
21530
|
return this;
|
|
20362
21531
|
}
|
|
20363
21532
|
if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
|
|
20364
|
-
const fullPath = opts.cwd ? sp2.join(opts.cwd,
|
|
21533
|
+
const fullPath = opts.cwd ? sp2.join(opts.cwd, path34) : path34;
|
|
20365
21534
|
let stats2;
|
|
20366
21535
|
try {
|
|
20367
21536
|
stats2 = await (0, import_promises3.stat)(fullPath);
|
|
@@ -20392,23 +21561,23 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
20392
21561
|
* @param timeout duration of time to suppress duplicate actions
|
|
20393
21562
|
* @returns tracking object or false if action should be suppressed
|
|
20394
21563
|
*/
|
|
20395
|
-
_throttle(actionType,
|
|
21564
|
+
_throttle(actionType, path34, timeout) {
|
|
20396
21565
|
if (!this._throttled.has(actionType)) {
|
|
20397
21566
|
this._throttled.set(actionType, /* @__PURE__ */ new Map());
|
|
20398
21567
|
}
|
|
20399
21568
|
const action = this._throttled.get(actionType);
|
|
20400
21569
|
if (!action)
|
|
20401
21570
|
throw new Error("invalid throttle");
|
|
20402
|
-
const actionPath = action.get(
|
|
21571
|
+
const actionPath = action.get(path34);
|
|
20403
21572
|
if (actionPath) {
|
|
20404
21573
|
actionPath.count++;
|
|
20405
21574
|
return false;
|
|
20406
21575
|
}
|
|
20407
21576
|
let timeoutObject;
|
|
20408
21577
|
const clear = () => {
|
|
20409
|
-
const item = action.get(
|
|
21578
|
+
const item = action.get(path34);
|
|
20410
21579
|
const count = item ? item.count : 0;
|
|
20411
|
-
action.delete(
|
|
21580
|
+
action.delete(path34);
|
|
20412
21581
|
clearTimeout(timeoutObject);
|
|
20413
21582
|
if (item)
|
|
20414
21583
|
clearTimeout(item.timeoutObject);
|
|
@@ -20416,7 +21585,7 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
20416
21585
|
};
|
|
20417
21586
|
timeoutObject = setTimeout(clear, timeout);
|
|
20418
21587
|
const thr = { timeoutObject, clear, count: 0 };
|
|
20419
|
-
action.set(
|
|
21588
|
+
action.set(path34, thr);
|
|
20420
21589
|
return thr;
|
|
20421
21590
|
}
|
|
20422
21591
|
_incrReadyCount() {
|
|
@@ -20430,44 +21599,44 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
20430
21599
|
* @param event
|
|
20431
21600
|
* @param awfEmit Callback to be called when ready for event to be emitted.
|
|
20432
21601
|
*/
|
|
20433
|
-
_awaitWriteFinish(
|
|
21602
|
+
_awaitWriteFinish(path34, threshold, event, awfEmit) {
|
|
20434
21603
|
const awf = this.options.awaitWriteFinish;
|
|
20435
21604
|
if (typeof awf !== "object")
|
|
20436
21605
|
return;
|
|
20437
21606
|
const pollInterval = awf.pollInterval;
|
|
20438
21607
|
let timeoutHandler;
|
|
20439
|
-
let fullPath =
|
|
20440
|
-
if (this.options.cwd && !sp2.isAbsolute(
|
|
20441
|
-
fullPath = sp2.join(this.options.cwd,
|
|
21608
|
+
let fullPath = path34;
|
|
21609
|
+
if (this.options.cwd && !sp2.isAbsolute(path34)) {
|
|
21610
|
+
fullPath = sp2.join(this.options.cwd, path34);
|
|
20442
21611
|
}
|
|
20443
21612
|
const now2 = /* @__PURE__ */ new Date();
|
|
20444
21613
|
const writes = this._pendingWrites;
|
|
20445
21614
|
function awaitWriteFinishFn(prevStat) {
|
|
20446
|
-
(0,
|
|
20447
|
-
if (err || !writes.has(
|
|
21615
|
+
(0, import_node_fs3.stat)(fullPath, (err, curStat) => {
|
|
21616
|
+
if (err || !writes.has(path34)) {
|
|
20448
21617
|
if (err && err.code !== "ENOENT")
|
|
20449
21618
|
awfEmit(err);
|
|
20450
21619
|
return;
|
|
20451
21620
|
}
|
|
20452
21621
|
const now3 = Number(/* @__PURE__ */ new Date());
|
|
20453
21622
|
if (prevStat && curStat.size !== prevStat.size) {
|
|
20454
|
-
writes.get(
|
|
21623
|
+
writes.get(path34).lastChange = now3;
|
|
20455
21624
|
}
|
|
20456
|
-
const pw = writes.get(
|
|
21625
|
+
const pw = writes.get(path34);
|
|
20457
21626
|
const df = now3 - pw.lastChange;
|
|
20458
21627
|
if (df >= threshold) {
|
|
20459
|
-
writes.delete(
|
|
21628
|
+
writes.delete(path34);
|
|
20460
21629
|
awfEmit(void 0, curStat);
|
|
20461
21630
|
} else {
|
|
20462
21631
|
timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
|
|
20463
21632
|
}
|
|
20464
21633
|
});
|
|
20465
21634
|
}
|
|
20466
|
-
if (!writes.has(
|
|
20467
|
-
writes.set(
|
|
21635
|
+
if (!writes.has(path34)) {
|
|
21636
|
+
writes.set(path34, {
|
|
20468
21637
|
lastChange: now2,
|
|
20469
21638
|
cancelWait: () => {
|
|
20470
|
-
writes.delete(
|
|
21639
|
+
writes.delete(path34);
|
|
20471
21640
|
clearTimeout(timeoutHandler);
|
|
20472
21641
|
return event;
|
|
20473
21642
|
}
|
|
@@ -20478,8 +21647,8 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
20478
21647
|
/**
|
|
20479
21648
|
* Determines whether user has asked to ignore this path.
|
|
20480
21649
|
*/
|
|
20481
|
-
_isIgnored(
|
|
20482
|
-
if (this.options.atomic && DOT_RE.test(
|
|
21650
|
+
_isIgnored(path34, stats) {
|
|
21651
|
+
if (this.options.atomic && DOT_RE.test(path34))
|
|
20483
21652
|
return true;
|
|
20484
21653
|
if (!this._userIgnored) {
|
|
20485
21654
|
const { cwd } = this.options;
|
|
@@ -20489,17 +21658,17 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
20489
21658
|
const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
|
|
20490
21659
|
this._userIgnored = anymatch(list, void 0);
|
|
20491
21660
|
}
|
|
20492
|
-
return this._userIgnored(
|
|
21661
|
+
return this._userIgnored(path34, stats);
|
|
20493
21662
|
}
|
|
20494
|
-
_isntIgnored(
|
|
20495
|
-
return !this._isIgnored(
|
|
21663
|
+
_isntIgnored(path34, stat5) {
|
|
21664
|
+
return !this._isIgnored(path34, stat5);
|
|
20496
21665
|
}
|
|
20497
21666
|
/**
|
|
20498
21667
|
* Provides a set of common helpers and properties relating to symlink handling.
|
|
20499
21668
|
* @param path file or directory pattern being watched
|
|
20500
21669
|
*/
|
|
20501
|
-
_getWatchHelpers(
|
|
20502
|
-
return new WatchHelper(
|
|
21670
|
+
_getWatchHelpers(path34) {
|
|
21671
|
+
return new WatchHelper(path34, this.options.followSymlinks, this);
|
|
20503
21672
|
}
|
|
20504
21673
|
// Directory helpers
|
|
20505
21674
|
// -----------------
|
|
@@ -20531,63 +21700,63 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
20531
21700
|
* @param item base path of item/directory
|
|
20532
21701
|
*/
|
|
20533
21702
|
_remove(directory, item, isDirectory) {
|
|
20534
|
-
const
|
|
20535
|
-
const fullPath = sp2.resolve(
|
|
20536
|
-
isDirectory = isDirectory != null ? isDirectory : this._watched.has(
|
|
20537
|
-
if (!this._throttle("remove",
|
|
21703
|
+
const path34 = sp2.join(directory, item);
|
|
21704
|
+
const fullPath = sp2.resolve(path34);
|
|
21705
|
+
isDirectory = isDirectory != null ? isDirectory : this._watched.has(path34) || this._watched.has(fullPath);
|
|
21706
|
+
if (!this._throttle("remove", path34, 100))
|
|
20538
21707
|
return;
|
|
20539
21708
|
if (!isDirectory && this._watched.size === 1) {
|
|
20540
21709
|
this.add(directory, item, true);
|
|
20541
21710
|
}
|
|
20542
|
-
const wp = this._getWatchedDir(
|
|
21711
|
+
const wp = this._getWatchedDir(path34);
|
|
20543
21712
|
const nestedDirectoryChildren = wp.getChildren();
|
|
20544
|
-
nestedDirectoryChildren.forEach((nested) => this._remove(
|
|
21713
|
+
nestedDirectoryChildren.forEach((nested) => this._remove(path34, nested));
|
|
20545
21714
|
const parent = this._getWatchedDir(directory);
|
|
20546
21715
|
const wasTracked = parent.has(item);
|
|
20547
21716
|
parent.remove(item);
|
|
20548
21717
|
if (this._symlinkPaths.has(fullPath)) {
|
|
20549
21718
|
this._symlinkPaths.delete(fullPath);
|
|
20550
21719
|
}
|
|
20551
|
-
let relPath =
|
|
21720
|
+
let relPath = path34;
|
|
20552
21721
|
if (this.options.cwd)
|
|
20553
|
-
relPath = sp2.relative(this.options.cwd,
|
|
21722
|
+
relPath = sp2.relative(this.options.cwd, path34);
|
|
20554
21723
|
if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
|
|
20555
21724
|
const event = this._pendingWrites.get(relPath).cancelWait();
|
|
20556
21725
|
if (event === EVENTS.ADD)
|
|
20557
21726
|
return;
|
|
20558
21727
|
}
|
|
20559
|
-
this._watched.delete(
|
|
21728
|
+
this._watched.delete(path34);
|
|
20560
21729
|
this._watched.delete(fullPath);
|
|
20561
21730
|
const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
|
|
20562
|
-
if (wasTracked && !this._isIgnored(
|
|
20563
|
-
this._emit(eventName,
|
|
20564
|
-
this._closePath(
|
|
21731
|
+
if (wasTracked && !this._isIgnored(path34))
|
|
21732
|
+
this._emit(eventName, path34);
|
|
21733
|
+
this._closePath(path34);
|
|
20565
21734
|
}
|
|
20566
21735
|
/**
|
|
20567
21736
|
* Closes all watchers for a path
|
|
20568
21737
|
*/
|
|
20569
|
-
_closePath(
|
|
20570
|
-
this._closeFile(
|
|
20571
|
-
const dir = sp2.dirname(
|
|
20572
|
-
this._getWatchedDir(dir).remove(sp2.basename(
|
|
21738
|
+
_closePath(path34) {
|
|
21739
|
+
this._closeFile(path34);
|
|
21740
|
+
const dir = sp2.dirname(path34);
|
|
21741
|
+
this._getWatchedDir(dir).remove(sp2.basename(path34));
|
|
20573
21742
|
}
|
|
20574
21743
|
/**
|
|
20575
21744
|
* Closes only file-specific watchers
|
|
20576
21745
|
*/
|
|
20577
|
-
_closeFile(
|
|
20578
|
-
const closers = this._closers.get(
|
|
21746
|
+
_closeFile(path34) {
|
|
21747
|
+
const closers = this._closers.get(path34);
|
|
20579
21748
|
if (!closers)
|
|
20580
21749
|
return;
|
|
20581
21750
|
closers.forEach((closer) => closer());
|
|
20582
|
-
this._closers.delete(
|
|
21751
|
+
this._closers.delete(path34);
|
|
20583
21752
|
}
|
|
20584
|
-
_addPathCloser(
|
|
21753
|
+
_addPathCloser(path34, closer) {
|
|
20585
21754
|
if (!closer)
|
|
20586
21755
|
return;
|
|
20587
|
-
let list = this._closers.get(
|
|
21756
|
+
let list = this._closers.get(path34);
|
|
20588
21757
|
if (!list) {
|
|
20589
21758
|
list = [];
|
|
20590
|
-
this._closers.set(
|
|
21759
|
+
this._closers.set(path34, list);
|
|
20591
21760
|
}
|
|
20592
21761
|
list.push(closer);
|
|
20593
21762
|
}
|
|
@@ -20617,11 +21786,11 @@ function watch(paths, options = {}) {
|
|
|
20617
21786
|
var chokidar_default = { watch, FSWatcher };
|
|
20618
21787
|
|
|
20619
21788
|
// src/watcher/file-watcher.ts
|
|
20620
|
-
var
|
|
21789
|
+
var path29 = __toESM(require("path"), 1);
|
|
20621
21790
|
|
|
20622
21791
|
// src/watcher/native-recursive-watcher.ts
|
|
20623
|
-
var
|
|
20624
|
-
var
|
|
21792
|
+
var import_node_fs4 = require("fs");
|
|
21793
|
+
var path27 = __toESM(require("path"), 1);
|
|
20625
21794
|
var NativeRecursiveWatcher = class {
|
|
20626
21795
|
constructor(root, onChange, options = {}) {
|
|
20627
21796
|
this.root = root;
|
|
@@ -20669,26 +21838,26 @@ var NativeRecursiveWatcher = class {
|
|
|
20669
21838
|
toAbsolutePath(filename) {
|
|
20670
21839
|
if (filename == null) return null;
|
|
20671
21840
|
const normalizedFilename = typeof filename === "string" ? filename : filename.toString();
|
|
20672
|
-
const absolutePath =
|
|
20673
|
-
const relativePath =
|
|
20674
|
-
const outsideRoot = relativePath === ".." || relativePath.startsWith(`..${
|
|
21841
|
+
const absolutePath = path27.resolve(this.root, normalizedFilename);
|
|
21842
|
+
const relativePath = path27.relative(this.root, absolutePath);
|
|
21843
|
+
const outsideRoot = relativePath === ".." || relativePath.startsWith(`..${path27.sep}`) || path27.isAbsolute(relativePath);
|
|
20675
21844
|
return outsideRoot ? null : absolutePath;
|
|
20676
21845
|
}
|
|
20677
|
-
defaultWatchFactory = (root, listener, options) => (0,
|
|
21846
|
+
defaultWatchFactory = (root, listener, options) => (0, import_node_fs4.watch)(root, options, listener);
|
|
20678
21847
|
};
|
|
20679
21848
|
|
|
20680
21849
|
// src/watcher/snapshot.ts
|
|
20681
21850
|
var fsPromises4 = __toESM(require("fs/promises"), 1);
|
|
20682
|
-
var
|
|
21851
|
+
var path28 = __toESM(require("path"), 1);
|
|
20683
21852
|
async function buildFileSnapshotScan(projectRoot, config, configPaths = []) {
|
|
20684
|
-
const normalizedProjectRoot =
|
|
21853
|
+
const normalizedProjectRoot = path28.resolve(projectRoot);
|
|
20685
21854
|
const ignoreFilter = createIgnoreFilter(normalizedProjectRoot);
|
|
20686
21855
|
const includePatterns = [...config.include, ...config.additionalInclude ?? []];
|
|
20687
21856
|
const maxDepth = config.indexing?.maxDepth ?? -1;
|
|
20688
21857
|
const snapshot = /* @__PURE__ */ new Map();
|
|
20689
21858
|
const unreadablePrefixes = /* @__PURE__ */ new Set();
|
|
20690
21859
|
const includeFile = async (filePath) => {
|
|
20691
|
-
const normalizedPath3 =
|
|
21860
|
+
const normalizedPath3 = path28.resolve(filePath);
|
|
20692
21861
|
if (!shouldIncludeFile(normalizedPath3, normalizedProjectRoot, includePatterns, config.exclude, ignoreFilter)) return;
|
|
20693
21862
|
const stat5 = await readStatIfFile(normalizedPath3, unreadablePrefixes);
|
|
20694
21863
|
if (stat5) snapshot.set(normalizedPath3, { size: stat5.size, mtimeMs: stat5.mtimeMs });
|
|
@@ -20700,16 +21869,16 @@ async function buildFileSnapshotScan(projectRoot, config, configPaths = []) {
|
|
|
20700
21869
|
} catch (error) {
|
|
20701
21870
|
if (isMissingFsError(error)) return;
|
|
20702
21871
|
if (isPermissionFsError(error)) {
|
|
20703
|
-
unreadablePrefixes.add(
|
|
21872
|
+
unreadablePrefixes.add(path28.resolve(directoryPath));
|
|
20704
21873
|
return;
|
|
20705
21874
|
}
|
|
20706
21875
|
throw error;
|
|
20707
21876
|
}
|
|
20708
21877
|
for (const entry of entries) {
|
|
20709
|
-
const fullPath =
|
|
20710
|
-
const relativePath =
|
|
21878
|
+
const fullPath = path28.join(directoryPath, entry.name);
|
|
21879
|
+
const relativePath = path28.relative(normalizedProjectRoot, fullPath);
|
|
20711
21880
|
if (entry.isDirectory()) {
|
|
20712
|
-
if (hasFilteredPathSegment(relativePath,
|
|
21881
|
+
if (hasFilteredPathSegment(relativePath, path28.sep) || isRestrictedDirectory(relativePath, path28.sep)) continue;
|
|
20713
21882
|
if (ignoreFilter.ignores(relativePath)) continue;
|
|
20714
21883
|
if (maxDepth === -1 || depth < maxDepth) await walk(fullPath, depth + 1);
|
|
20715
21884
|
} else if (entry.isFile()) {
|
|
@@ -20722,19 +21891,19 @@ async function buildFileSnapshotScan(projectRoot, config, configPaths = []) {
|
|
|
20722
21891
|
return { entries: snapshot, unreadablePrefixes };
|
|
20723
21892
|
}
|
|
20724
21893
|
async function buildFileSnapshotForPathScan(projectRoot, config, configPaths, targetPath) {
|
|
20725
|
-
const normalizedProjectRoot =
|
|
20726
|
-
const normalizedTargetPath =
|
|
21894
|
+
const normalizedProjectRoot = path28.resolve(projectRoot);
|
|
21895
|
+
const normalizedTargetPath = path28.resolve(targetPath);
|
|
20727
21896
|
if (!isWithinPath(normalizedProjectRoot, normalizedTargetPath)) {
|
|
20728
21897
|
return { entries: /* @__PURE__ */ new Map(), unreadablePrefixes: /* @__PURE__ */ new Set() };
|
|
20729
21898
|
}
|
|
20730
21899
|
const ignoreFilter = createIgnoreFilter(normalizedProjectRoot);
|
|
20731
21900
|
const includePatterns = [...config.include, ...config.additionalInclude ?? []];
|
|
20732
21901
|
const maxDepth = config.indexing?.maxDepth ?? -1;
|
|
20733
|
-
const explicitConfigPaths = new Set(configPaths.map((configPath) =>
|
|
21902
|
+
const explicitConfigPaths = new Set(configPaths.map((configPath) => path28.resolve(configPath)));
|
|
20734
21903
|
const snapshot = /* @__PURE__ */ new Map();
|
|
20735
21904
|
const unreadablePrefixes = /* @__PURE__ */ new Set();
|
|
20736
21905
|
const includeFile = async (filePath) => {
|
|
20737
|
-
const normalizedPath3 =
|
|
21906
|
+
const normalizedPath3 = path28.resolve(filePath);
|
|
20738
21907
|
if (!explicitConfigPaths.has(normalizedPath3) && !shouldIncludeFile(
|
|
20739
21908
|
normalizedPath3,
|
|
20740
21909
|
normalizedProjectRoot,
|
|
@@ -20752,16 +21921,16 @@ async function buildFileSnapshotForPathScan(projectRoot, config, configPaths, ta
|
|
|
20752
21921
|
} catch (error) {
|
|
20753
21922
|
if (isMissingFsError(error)) return;
|
|
20754
21923
|
if (isPermissionFsError(error)) {
|
|
20755
|
-
unreadablePrefixes.add(
|
|
21924
|
+
unreadablePrefixes.add(path28.resolve(directoryPath));
|
|
20756
21925
|
return;
|
|
20757
21926
|
}
|
|
20758
21927
|
throw error;
|
|
20759
21928
|
}
|
|
20760
21929
|
for (const entry of entries) {
|
|
20761
|
-
const fullPath =
|
|
20762
|
-
const relativePath =
|
|
21930
|
+
const fullPath = path28.join(directoryPath, entry.name);
|
|
21931
|
+
const relativePath = path28.relative(normalizedProjectRoot, fullPath);
|
|
20763
21932
|
if (entry.isDirectory()) {
|
|
20764
|
-
if (hasFilteredPathSegment(relativePath,
|
|
21933
|
+
if (hasFilteredPathSegment(relativePath, path28.sep) || isRestrictedDirectory(relativePath, path28.sep)) continue;
|
|
20765
21934
|
if (ignoreFilter.ignores(relativePath)) continue;
|
|
20766
21935
|
if (maxDepth === -1 || depth < maxDepth) await walk(fullPath, depth + 1);
|
|
20767
21936
|
} else if (entry.isFile()) {
|
|
@@ -20785,7 +21954,7 @@ function completeFileSnapshot(previous, scan) {
|
|
|
20785
21954
|
return completed;
|
|
20786
21955
|
}
|
|
20787
21956
|
async function includeExplicitConfigPaths(snapshot, unreadablePrefixes, configPaths) {
|
|
20788
|
-
for (const configPath of [...new Set(configPaths.map((value) =>
|
|
21957
|
+
for (const configPath of [...new Set(configPaths.map((value) => path28.resolve(value)))]) {
|
|
20789
21958
|
if (snapshot.has(configPath)) continue;
|
|
20790
21959
|
const stat5 = await readStatIfFile(configPath, unreadablePrefixes);
|
|
20791
21960
|
if (stat5) snapshot.set(configPath, { size: stat5.size, mtimeMs: stat5.mtimeMs });
|
|
@@ -20795,12 +21964,12 @@ async function includeExplicitConfigPathsInPath(snapshot, unreadablePrefixes, co
|
|
|
20795
21964
|
await includeExplicitConfigPaths(
|
|
20796
21965
|
snapshot,
|
|
20797
21966
|
unreadablePrefixes,
|
|
20798
|
-
configPaths.filter((configPath) => isWithinPath(targetPath,
|
|
21967
|
+
configPaths.filter((configPath) => isWithinPath(targetPath, path28.resolve(configPath)))
|
|
20799
21968
|
);
|
|
20800
21969
|
}
|
|
20801
21970
|
function isWithinPath(parentPath, childPath) {
|
|
20802
|
-
const relativePath =
|
|
20803
|
-
return relativePath === "" || !relativePath.startsWith(`..${
|
|
21971
|
+
const relativePath = path28.relative(parentPath, childPath);
|
|
21972
|
+
return relativePath === "" || !relativePath.startsWith(`..${path28.sep}`) && relativePath !== ".." && !path28.isAbsolute(relativePath);
|
|
20804
21973
|
}
|
|
20805
21974
|
async function readStatIfFile(filePath, unreadablePrefixes) {
|
|
20806
21975
|
try {
|
|
@@ -20809,7 +21978,7 @@ async function readStatIfFile(filePath, unreadablePrefixes) {
|
|
|
20809
21978
|
} catch (error) {
|
|
20810
21979
|
if (isMissingFsError(error)) return null;
|
|
20811
21980
|
if (isPermissionFsError(error)) {
|
|
20812
|
-
unreadablePrefixes.add(
|
|
21981
|
+
unreadablePrefixes.add(path28.resolve(filePath));
|
|
20813
21982
|
return null;
|
|
20814
21983
|
}
|
|
20815
21984
|
throw error;
|
|
@@ -20946,8 +22115,8 @@ var FileWatcher = class {
|
|
|
20946
22115
|
this.createWatcher();
|
|
20947
22116
|
}
|
|
20948
22117
|
resetReady() {
|
|
20949
|
-
this.readyPromise = new Promise((
|
|
20950
|
-
this.resolveReady =
|
|
22118
|
+
this.readyPromise = new Promise((resolve21) => {
|
|
22119
|
+
this.resolveReady = resolve21;
|
|
20951
22120
|
});
|
|
20952
22121
|
this.startupReadySignals = 1;
|
|
20953
22122
|
}
|
|
@@ -20978,7 +22147,7 @@ var FileWatcher = class {
|
|
|
20978
22147
|
const resolvedWatchTargets = watchTargets ?? this.getFullChokidarWatchTargets();
|
|
20979
22148
|
const watcherOptions = {
|
|
20980
22149
|
ignored: (filePath) => {
|
|
20981
|
-
const relativePath =
|
|
22150
|
+
const relativePath = path29.relative(this.projectRoot, filePath);
|
|
20982
22151
|
if (!relativePath) return false;
|
|
20983
22152
|
if (this.isProjectConfigPathOrAncestor(relativePath)) {
|
|
20984
22153
|
return false;
|
|
@@ -20986,10 +22155,10 @@ var FileWatcher = class {
|
|
|
20986
22155
|
if (this.isOutsideProjectPath(relativePath)) {
|
|
20987
22156
|
return true;
|
|
20988
22157
|
}
|
|
20989
|
-
if (hasFilteredPathSegment(relativePath,
|
|
22158
|
+
if (hasFilteredPathSegment(relativePath, path29.sep)) {
|
|
20990
22159
|
return true;
|
|
20991
22160
|
}
|
|
20992
|
-
if (isRestrictedDirectory(relativePath,
|
|
22161
|
+
if (isRestrictedDirectory(relativePath, path29.sep)) {
|
|
20993
22162
|
return true;
|
|
20994
22163
|
}
|
|
20995
22164
|
if (ignoreFilter.ignores(relativePath)) {
|
|
@@ -21080,13 +22249,13 @@ var FileWatcher = class {
|
|
|
21080
22249
|
getExternalConfigWatchTargets() {
|
|
21081
22250
|
return [...new Set(
|
|
21082
22251
|
this.projectConfigPaths.filter((projectConfigPath) => {
|
|
21083
|
-
const relativeConfigPath =
|
|
22252
|
+
const relativeConfigPath = path29.relative(this.projectRoot, projectConfigPath);
|
|
21084
22253
|
return this.isOutsideProjectPath(relativeConfigPath);
|
|
21085
22254
|
}).map((projectConfigPath) => {
|
|
21086
22255
|
if ((0, import_fs19.existsSync)(projectConfigPath)) {
|
|
21087
22256
|
return projectConfigPath;
|
|
21088
22257
|
}
|
|
21089
|
-
return this.getNearestExistingDirectory(
|
|
22258
|
+
return this.getNearestExistingDirectory(path29.dirname(projectConfigPath));
|
|
21090
22259
|
})
|
|
21091
22260
|
)];
|
|
21092
22261
|
}
|
|
@@ -21148,7 +22317,7 @@ var FileWatcher = class {
|
|
|
21148
22317
|
}
|
|
21149
22318
|
scheduleNativeReconciliation(generation, filePath) {
|
|
21150
22319
|
if (!this.isCurrentNativeSetup(generation)) return;
|
|
21151
|
-
const requiresFullReconciliation = filePath ===
|
|
22320
|
+
const requiresFullReconciliation = filePath === path29.join(this.projectRoot, ".gitignore");
|
|
21152
22321
|
const invalidatedPath = requiresFullReconciliation ? null : filePath;
|
|
21153
22322
|
this.nativeInvalidatedPaths.set(invalidatedPath, invalidatedPath !== null);
|
|
21154
22323
|
if (this.nativeReconcileTimer) {
|
|
@@ -21243,23 +22412,23 @@ var FileWatcher = class {
|
|
|
21243
22412
|
this.scheduleFlush();
|
|
21244
22413
|
}
|
|
21245
22414
|
isProjectConfigPath(filePath) {
|
|
21246
|
-
const relativePath =
|
|
21247
|
-
const normalizedRelativePath =
|
|
22415
|
+
const relativePath = path29.relative(this.projectRoot, filePath);
|
|
22416
|
+
const normalizedRelativePath = path29.normalize(relativePath);
|
|
21248
22417
|
return this.getProjectConfigRelativePaths().some((configPath) => configPath === normalizedRelativePath);
|
|
21249
22418
|
}
|
|
21250
22419
|
isProjectConfigPathOrAncestor(relativePath) {
|
|
21251
|
-
const normalizedRelativePath =
|
|
22420
|
+
const normalizedRelativePath = path29.normalize(relativePath);
|
|
21252
22421
|
return this.getProjectConfigRelativePaths().some(
|
|
21253
|
-
(configPath) => configPath === normalizedRelativePath || configPath.startsWith(`${normalizedRelativePath}${
|
|
22422
|
+
(configPath) => configPath === normalizedRelativePath || configPath.startsWith(`${normalizedRelativePath}${path29.sep}`)
|
|
21254
22423
|
);
|
|
21255
22424
|
}
|
|
21256
22425
|
isOutsideProjectPath(relativePath) {
|
|
21257
|
-
return relativePath === ".." || relativePath.startsWith(`..${
|
|
22426
|
+
return relativePath === ".." || relativePath.startsWith(`..${path29.sep}`) || path29.isAbsolute(relativePath);
|
|
21258
22427
|
}
|
|
21259
22428
|
getNearestExistingDirectory(directoryPath) {
|
|
21260
22429
|
let candidate = directoryPath;
|
|
21261
22430
|
while (!(0, import_fs19.existsSync)(candidate)) {
|
|
21262
|
-
const parent =
|
|
22431
|
+
const parent = path29.dirname(candidate);
|
|
21263
22432
|
if (parent === candidate) break;
|
|
21264
22433
|
candidate = parent;
|
|
21265
22434
|
}
|
|
@@ -21267,7 +22436,7 @@ var FileWatcher = class {
|
|
|
21267
22436
|
}
|
|
21268
22437
|
getProjectConfigRelativePaths() {
|
|
21269
22438
|
return this.projectConfigPaths.map(
|
|
21270
|
-
(configPath) =>
|
|
22439
|
+
(configPath) => path29.normalize(path29.relative(this.projectRoot, configPath))
|
|
21271
22440
|
);
|
|
21272
22441
|
}
|
|
21273
22442
|
getConfigPathStates() {
|
|
@@ -21325,7 +22494,7 @@ var FileWatcher = class {
|
|
|
21325
22494
|
return;
|
|
21326
22495
|
}
|
|
21327
22496
|
const changes = Array.from(this.pendingChanges.entries()).map(
|
|
21328
|
-
([
|
|
22497
|
+
([path34, type]) => ({ path: path34, type })
|
|
21329
22498
|
);
|
|
21330
22499
|
this.pendingChanges.clear();
|
|
21331
22500
|
try {
|
|
@@ -21371,7 +22540,7 @@ var FileWatcher = class {
|
|
|
21371
22540
|
};
|
|
21372
22541
|
|
|
21373
22542
|
// src/watcher/git-head-watcher.ts
|
|
21374
|
-
var
|
|
22543
|
+
var path30 = __toESM(require("path"), 1);
|
|
21375
22544
|
var GitHeadWatcher = class {
|
|
21376
22545
|
watcher = null;
|
|
21377
22546
|
projectRoot;
|
|
@@ -21393,13 +22562,13 @@ var GitHeadWatcher = class {
|
|
|
21393
22562
|
this.readyPromise = Promise.resolve();
|
|
21394
22563
|
return;
|
|
21395
22564
|
}
|
|
21396
|
-
this.readyPromise = new Promise((
|
|
21397
|
-
this.resolveReady =
|
|
22565
|
+
this.readyPromise = new Promise((resolve21) => {
|
|
22566
|
+
this.resolveReady = resolve21;
|
|
21398
22567
|
});
|
|
21399
22568
|
this.onBranchChange = handler;
|
|
21400
22569
|
this.currentBranch = getCurrentBranch(this.projectRoot);
|
|
21401
22570
|
const headPath = getHeadPath(this.projectRoot);
|
|
21402
|
-
const refsPath =
|
|
22571
|
+
const refsPath = path30.join(this.projectRoot, ".git", "refs", "heads");
|
|
21403
22572
|
this.watcher = chokidar_default.watch([headPath, refsPath], {
|
|
21404
22573
|
persistent: true,
|
|
21405
22574
|
ignoreInitial: true,
|
|
@@ -21467,7 +22636,9 @@ var GitHeadWatcher = class {
|
|
|
21467
22636
|
function createWatcherWithIndexer(getIndexer, projectRoot, config, host, options = {}) {
|
|
21468
22637
|
const fileWatcher = new FileWatcher(projectRoot, config, host, options);
|
|
21469
22638
|
const configPaths = getConfigPaths(projectRoot, host, options);
|
|
21470
|
-
configureAutoIndex(projectRoot, host, parseConfig(config), getIndexer
|
|
22639
|
+
configureAutoIndex(projectRoot, host, parseConfig(config), getIndexer, {
|
|
22640
|
+
synchronizeBackgroundWorker: false
|
|
22641
|
+
});
|
|
21471
22642
|
let stopped = false;
|
|
21472
22643
|
const requestReindex = () => {
|
|
21473
22644
|
if (stopped) return;
|
|
@@ -21487,7 +22658,9 @@ function createWatcherWithIndexer(getIndexer, projectRoot, config, host, options
|
|
|
21487
22658
|
const parsedConfig = options.configPath ? parseConfig(loadConfigFile(options.configPath)) : void 0;
|
|
21488
22659
|
const refreshedConfig = refreshIndexerForDirectory(projectRoot, host, parsedConfig);
|
|
21489
22660
|
if (refreshedConfig) {
|
|
21490
|
-
configureAutoIndex(projectRoot, host, refreshedConfig, getIndexer
|
|
22661
|
+
configureAutoIndex(projectRoot, host, refreshedConfig, getIndexer, {
|
|
22662
|
+
synchronizeBackgroundWorker: false
|
|
22663
|
+
});
|
|
21491
22664
|
}
|
|
21492
22665
|
}
|
|
21493
22666
|
requestReindex();
|
|
@@ -21535,7 +22708,7 @@ function getConfigPaths(projectRoot, host, options) {
|
|
|
21535
22708
|
|
|
21536
22709
|
// src/tools/visualize/activity.ts
|
|
21537
22710
|
var import_child_process5 = require("child_process");
|
|
21538
|
-
var
|
|
22711
|
+
var path31 = __toESM(require("path"), 1);
|
|
21539
22712
|
function attachRecentActivity(data, projectRoot) {
|
|
21540
22713
|
const activity = readGitActivity(projectRoot);
|
|
21541
22714
|
const changes = activity.size > 0 ? buildGitChanges(data, activity, projectRoot) : buildGraphChanges(data);
|
|
@@ -21697,7 +22870,7 @@ function normalizePath4(filePath) {
|
|
|
21697
22870
|
return filePath.replace(/\\/g, "/");
|
|
21698
22871
|
}
|
|
21699
22872
|
function toGitRelativePath(projectRoot, filePath) {
|
|
21700
|
-
const relativePath =
|
|
22873
|
+
const relativePath = path31.isAbsolute(filePath) ? path31.relative(projectRoot, filePath) : filePath;
|
|
21701
22874
|
return normalizePath4(relativePath);
|
|
21702
22875
|
}
|
|
21703
22876
|
|
|
@@ -21955,7 +23128,7 @@ render();
|
|
|
21955
23128
|
}
|
|
21956
23129
|
|
|
21957
23130
|
// src/tools/visualize/transform.ts
|
|
21958
|
-
var
|
|
23131
|
+
var path32 = __toESM(require("path"), 1);
|
|
21959
23132
|
|
|
21960
23133
|
// src/tools/visualize/modules.ts
|
|
21961
23134
|
var MAX_MODULES = 18;
|
|
@@ -22215,7 +23388,7 @@ function transformForVisualization(symbols, edges, options = {}) {
|
|
|
22215
23388
|
filePath: s.filePath,
|
|
22216
23389
|
kind: s.kind,
|
|
22217
23390
|
line: s.startLine,
|
|
22218
|
-
directory:
|
|
23391
|
+
directory: path32.dirname(s.filePath),
|
|
22219
23392
|
moduleId: "",
|
|
22220
23393
|
moduleLabel: ""
|
|
22221
23394
|
}));
|
|
@@ -22243,9 +23416,9 @@ function parseArgs(argv) {
|
|
|
22243
23416
|
let host = "opencode";
|
|
22244
23417
|
for (let i = 2; i < argv.length; i++) {
|
|
22245
23418
|
if (argv[i] === "--project" && argv[i + 1]) {
|
|
22246
|
-
project =
|
|
23419
|
+
project = path33.resolve(argv[++i]);
|
|
22247
23420
|
} else if (argv[i] === "--config" && argv[i + 1]) {
|
|
22248
|
-
config =
|
|
23421
|
+
config = path33.resolve(argv[++i]);
|
|
22249
23422
|
} else if (argv[i] === "--host" && argv[i + 1]) {
|
|
22250
23423
|
host = parseHostMode(argv[++i]);
|
|
22251
23424
|
} else if (argv[i] === "--host") {
|
|
@@ -22260,6 +23433,7 @@ function parseIndexArgs(argv, cwd) {
|
|
|
22260
23433
|
let config;
|
|
22261
23434
|
let force = false;
|
|
22262
23435
|
let estimateOnly = false;
|
|
23436
|
+
let dryRun = false;
|
|
22263
23437
|
let verbose = false;
|
|
22264
23438
|
for (let i = 0; i < argv.length; i += 1) {
|
|
22265
23439
|
const arg = argv[i];
|
|
@@ -22272,7 +23446,7 @@ function parseIndexArgs(argv, cwd) {
|
|
|
22272
23446
|
if (!arg.startsWith("--project=")) {
|
|
22273
23447
|
i += 1;
|
|
22274
23448
|
}
|
|
22275
|
-
project =
|
|
23449
|
+
project = path33.resolve(cwd, value);
|
|
22276
23450
|
continue;
|
|
22277
23451
|
}
|
|
22278
23452
|
if (arg === "--config" || arg.startsWith("--config=")) {
|
|
@@ -22283,7 +23457,7 @@ function parseIndexArgs(argv, cwd) {
|
|
|
22283
23457
|
if (!arg.startsWith("--config=")) {
|
|
22284
23458
|
i += 1;
|
|
22285
23459
|
}
|
|
22286
|
-
config =
|
|
23460
|
+
config = path33.resolve(cwd, value);
|
|
22287
23461
|
continue;
|
|
22288
23462
|
}
|
|
22289
23463
|
if (arg === "--host" || arg.startsWith("--host=")) {
|
|
@@ -22297,13 +23471,16 @@ function parseIndexArgs(argv, cwd) {
|
|
|
22297
23471
|
host = parseHostMode(value);
|
|
22298
23472
|
continue;
|
|
22299
23473
|
}
|
|
22300
|
-
if (arg === "--force" || arg === "--estimate-only" || arg === "--verbose") {
|
|
23474
|
+
if (arg === "--force" || arg === "--estimate-only" || arg === "--dry-run" || arg === "--verbose") {
|
|
22301
23475
|
if (arg === "--force") {
|
|
22302
23476
|
force = true;
|
|
22303
23477
|
}
|
|
22304
23478
|
if (arg === "--estimate-only") {
|
|
22305
23479
|
estimateOnly = true;
|
|
22306
23480
|
}
|
|
23481
|
+
if (arg === "--dry-run") {
|
|
23482
|
+
dryRun = true;
|
|
23483
|
+
}
|
|
22307
23484
|
if (arg === "--verbose") {
|
|
22308
23485
|
verbose = true;
|
|
22309
23486
|
}
|
|
@@ -22314,7 +23491,7 @@ function parseIndexArgs(argv, cwd) {
|
|
|
22314
23491
|
}
|
|
22315
23492
|
throw new Error(`Unknown index option: ${arg}`);
|
|
22316
23493
|
}
|
|
22317
|
-
return { project, host, config, force, estimateOnly, verbose };
|
|
23494
|
+
return { project, host, config, force, estimateOnly, dryRun, verbose };
|
|
22318
23495
|
}
|
|
22319
23496
|
function loadCliRawConfig(args) {
|
|
22320
23497
|
return args.config ? loadConfigFile(args.config) : loadMergedConfig(args.project, args.host);
|
|
@@ -22331,6 +23508,7 @@ Options:
|
|
|
22331
23508
|
--config <path> Explicit JSON config path
|
|
22332
23509
|
--force Rebuild index even if already up to date
|
|
22333
23510
|
--estimate-only Estimate indexing cost only
|
|
23511
|
+
--dry-run Parse only; report the exact embedding token total without indexing
|
|
22334
23512
|
--verbose Include detailed final index statistics
|
|
22335
23513
|
--help Show this message
|
|
22336
23514
|
|
|
@@ -22349,7 +23527,7 @@ function parseVisualizeArgs(argv, cwd) {
|
|
|
22349
23527
|
for (let i = 0; i < argv.length; i++) {
|
|
22350
23528
|
const arg = argv[i];
|
|
22351
23529
|
if (arg === "--project" && argv[i + 1]) {
|
|
22352
|
-
project =
|
|
23530
|
+
project = path33.resolve(argv[++i]);
|
|
22353
23531
|
} else if (arg === "--max" && argv[i + 1]) {
|
|
22354
23532
|
maxNodes = Number(argv[++i]);
|
|
22355
23533
|
} else if (arg.startsWith("--max=") || arg.startsWith("max=")) {
|
|
@@ -22386,7 +23564,7 @@ async function handleVisualizeCommand(argv, cwd) {
|
|
|
22386
23564
|
console.error("No connected symbols found. Retry with: npm run visualize -- orphans");
|
|
22387
23565
|
return 1;
|
|
22388
23566
|
}
|
|
22389
|
-
const outputPath =
|
|
23567
|
+
const outputPath = path33.join(os9.tmpdir(), `call-graph-${Date.now()}.html`);
|
|
22390
23568
|
(0, import_fs20.writeFileSync)(outputPath, generateVisualizationHtml(vizData), "utf-8");
|
|
22391
23569
|
console.log(`Temporal call graph visualization generated: ${outputPath}`);
|
|
22392
23570
|
console.log(`Nodes: ${vizData.nodes.length} | Edges: ${vizData.edges.length}`);
|
|
@@ -22418,7 +23596,6 @@ async function runMcpCli(argv) {
|
|
|
22418
23596
|
const config = parseConfig(rawConfig);
|
|
22419
23597
|
const server = createMcpServer(args.project, config, args.host);
|
|
22420
23598
|
const transport = new import_stdio.StdioServerTransport();
|
|
22421
|
-
let watcher = null;
|
|
22422
23599
|
let shutdownPromise;
|
|
22423
23600
|
const onServerClose = server.server.onclose;
|
|
22424
23601
|
const shutdown = () => {
|
|
@@ -22432,16 +23609,19 @@ async function runMcpCli(argv) {
|
|
|
22432
23609
|
shutdownPromise = (async () => {
|
|
22433
23610
|
let exitCode = 0;
|
|
22434
23611
|
try {
|
|
22435
|
-
await
|
|
22436
|
-
} catch (error) {
|
|
22437
|
-
exitCode = 1;
|
|
22438
|
-
console.error("Failed to stop MCP file watcher cleanly:", error);
|
|
22439
|
-
}
|
|
22440
|
-
try {
|
|
22441
|
-
await stopAutoIndex(args.project, args.host);
|
|
23612
|
+
await stopBackgroundWorker(args.project, args.host);
|
|
22442
23613
|
} catch (error) {
|
|
22443
23614
|
exitCode = 1;
|
|
22444
|
-
|
|
23615
|
+
if (error instanceof BackgroundWorkerStopError) {
|
|
23616
|
+
if (error.watcherError !== void 0) {
|
|
23617
|
+
console.error("Failed to stop MCP file watcher cleanly:", error.watcherError);
|
|
23618
|
+
}
|
|
23619
|
+
if (error.autoIndexError !== void 0) {
|
|
23620
|
+
console.error("Failed to stop automatic indexing cleanly:", error.autoIndexError);
|
|
23621
|
+
}
|
|
23622
|
+
} else {
|
|
23623
|
+
console.error("Failed to stop automatic indexing cleanly:", error);
|
|
23624
|
+
}
|
|
22445
23625
|
}
|
|
22446
23626
|
try {
|
|
22447
23627
|
await server.close();
|
|
@@ -22470,19 +23650,25 @@ async function runMcpCli(argv) {
|
|
|
22470
23650
|
process.once("SIGHUP", requestShutdown);
|
|
22471
23651
|
process.once("SIGTERM", requestShutdown);
|
|
22472
23652
|
}
|
|
22473
|
-
await server.connect(transport);
|
|
22474
|
-
if (shutdownPromise) return;
|
|
22475
23653
|
const isHomeDir = isHomeDirectory(args.project);
|
|
22476
23654
|
const isValidProject = !isHomeDir && (!config.indexing.requireProjectMarker || hasProjectMarker(args.project));
|
|
22477
|
-
|
|
22478
|
-
|
|
22479
|
-
|
|
22480
|
-
|
|
22481
|
-
|
|
22482
|
-
|
|
22483
|
-
|
|
22484
|
-
|
|
22485
|
-
|
|
23655
|
+
const watcherFactoryForConfig = (refreshedConfig) => refreshedConfig.indexing.watchFiles && !isHomeDirectory(args.project) && (!refreshedConfig.indexing.requireProjectMarker || hasProjectMarker(args.project)) ? () => createWatcherWithIndexer(
|
|
23656
|
+
() => getIndexerForProject(args.project, args.host),
|
|
23657
|
+
args.project,
|
|
23658
|
+
refreshedConfig,
|
|
23659
|
+
args.host,
|
|
23660
|
+
args.config ? { configPath: args.config } : {}
|
|
23661
|
+
) : null;
|
|
23662
|
+
await server.connect(transport);
|
|
23663
|
+
if (shutdownPromise) return;
|
|
23664
|
+
await attachMcpBackgroundWatcher(
|
|
23665
|
+
args.project,
|
|
23666
|
+
config,
|
|
23667
|
+
args.host,
|
|
23668
|
+
config.indexing.watchFiles && isValidProject ? watcherFactoryForConfig(config) : null,
|
|
23669
|
+
watcherFactoryForConfig
|
|
23670
|
+
);
|
|
23671
|
+
if (shutdownPromise) return;
|
|
22486
23672
|
}
|
|
22487
23673
|
function printIndexProgress(onProgress, title, metadata) {
|
|
22488
23674
|
const details = Object.entries(metadata).filter(([, value]) => value !== void 0 && value !== null).map(([key, value]) => `${key}=${isSensitiveKey(key) ? "[REDACTED]" : String(value)}`).join(" ");
|
|
@@ -22526,6 +23712,7 @@ async function handleIndexCommand(argv, cwd, deps = {}) {
|
|
|
22526
23712
|
const indexArgs = {
|
|
22527
23713
|
force: parsedArgs.force,
|
|
22528
23714
|
estimateOnly: parsedArgs.estimateOnly,
|
|
23715
|
+
dryRun: parsedArgs.dryRun,
|
|
22529
23716
|
verbose: parsedArgs.verbose
|
|
22530
23717
|
};
|
|
22531
23718
|
const result = await runIndex(parsedArgs.project, parsedArgs.host, indexArgs, (title, metadata) => {
|