opencode-codebase-index 0.25.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/dist/cbi.cjs +1254 -258
- package/dist/cbi.cjs.map +1 -1
- package/dist/cbi.js +1318 -313
- package/dist/cbi.js.map +1 -1
- package/dist/cli.cjs +1617 -528
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +1654 -556
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +1519 -530
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1583 -585
- package/dist/index.js.map +1 -1
- package/dist/pi-extension.cjs +1492 -484
- package/dist/pi-extension.cjs.map +1 -1
- package/dist/pi-extension.js +1548 -531
- 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 +1 -1
package/dist/index.cjs
CHANGED
|
@@ -333,7 +333,7 @@ var require_ignore = __commonJS({
|
|
|
333
333
|
// path matching.
|
|
334
334
|
// - check `string` either `MODE_IGNORE` or `MODE_CHECK_IGNORE`
|
|
335
335
|
// @returns {TestResult} true if a file is ignored
|
|
336
|
-
test(
|
|
336
|
+
test(path31, checkUnignored, mode) {
|
|
337
337
|
let ignored = false;
|
|
338
338
|
let unignored = false;
|
|
339
339
|
let matchedRule;
|
|
@@ -342,7 +342,7 @@ var require_ignore = __commonJS({
|
|
|
342
342
|
if (unignored === negative && ignored !== unignored || negative && !ignored && !unignored && !checkUnignored) {
|
|
343
343
|
return;
|
|
344
344
|
}
|
|
345
|
-
const matched = rule[mode].test(
|
|
345
|
+
const matched = rule[mode].test(path31);
|
|
346
346
|
if (!matched) {
|
|
347
347
|
return;
|
|
348
348
|
}
|
|
@@ -363,17 +363,17 @@ var require_ignore = __commonJS({
|
|
|
363
363
|
var throwError = (message, Ctor) => {
|
|
364
364
|
throw new Ctor(message);
|
|
365
365
|
};
|
|
366
|
-
var checkPath = (
|
|
367
|
-
if (!isString(
|
|
366
|
+
var checkPath = (path31, originalPath, doThrow) => {
|
|
367
|
+
if (!isString(path31)) {
|
|
368
368
|
return doThrow(
|
|
369
369
|
`path must be a string, but got \`${originalPath}\``,
|
|
370
370
|
TypeError
|
|
371
371
|
);
|
|
372
372
|
}
|
|
373
|
-
if (!
|
|
373
|
+
if (!path31) {
|
|
374
374
|
return doThrow(`path must not be empty`, TypeError);
|
|
375
375
|
}
|
|
376
|
-
if (checkPath.isNotRelative(
|
|
376
|
+
if (checkPath.isNotRelative(path31)) {
|
|
377
377
|
const r = "`path.relative()`d";
|
|
378
378
|
return doThrow(
|
|
379
379
|
`path should be a ${r} string, but got "${originalPath}"`,
|
|
@@ -382,7 +382,7 @@ var require_ignore = __commonJS({
|
|
|
382
382
|
}
|
|
383
383
|
return true;
|
|
384
384
|
};
|
|
385
|
-
var isNotRelative = (
|
|
385
|
+
var isNotRelative = (path31) => REGEX_TEST_INVALID_PATH.test(path31);
|
|
386
386
|
checkPath.isNotRelative = isNotRelative;
|
|
387
387
|
checkPath.convert = (p) => p;
|
|
388
388
|
var Ignore2 = class {
|
|
@@ -412,19 +412,19 @@ var require_ignore = __commonJS({
|
|
|
412
412
|
}
|
|
413
413
|
// @returns {TestResult}
|
|
414
414
|
_test(originalPath, cache, checkUnignored, slices) {
|
|
415
|
-
const
|
|
415
|
+
const path31 = originalPath && checkPath.convert(originalPath);
|
|
416
416
|
checkPath(
|
|
417
|
-
|
|
417
|
+
path31,
|
|
418
418
|
originalPath,
|
|
419
419
|
this._strictPathCheck ? throwError : RETURN_FALSE
|
|
420
420
|
);
|
|
421
|
-
return this._t(
|
|
421
|
+
return this._t(path31, cache, checkUnignored, slices);
|
|
422
422
|
}
|
|
423
|
-
checkIgnore(
|
|
424
|
-
if (!REGEX_TEST_TRAILING_SLASH.test(
|
|
425
|
-
return this.test(
|
|
423
|
+
checkIgnore(path31) {
|
|
424
|
+
if (!REGEX_TEST_TRAILING_SLASH.test(path31)) {
|
|
425
|
+
return this.test(path31);
|
|
426
426
|
}
|
|
427
|
-
const slices =
|
|
427
|
+
const slices = path31.split(SLASH2).filter(Boolean);
|
|
428
428
|
slices.pop();
|
|
429
429
|
if (slices.length) {
|
|
430
430
|
const parent = this._t(
|
|
@@ -437,18 +437,18 @@ var require_ignore = __commonJS({
|
|
|
437
437
|
return parent;
|
|
438
438
|
}
|
|
439
439
|
}
|
|
440
|
-
return this._rules.test(
|
|
440
|
+
return this._rules.test(path31, false, MODE_CHECK_IGNORE);
|
|
441
441
|
}
|
|
442
|
-
_t(
|
|
443
|
-
if (
|
|
444
|
-
return cache[
|
|
442
|
+
_t(path31, cache, checkUnignored, slices) {
|
|
443
|
+
if (path31 in cache) {
|
|
444
|
+
return cache[path31];
|
|
445
445
|
}
|
|
446
446
|
if (!slices) {
|
|
447
|
-
slices =
|
|
447
|
+
slices = path31.split(SLASH2).filter(Boolean);
|
|
448
448
|
}
|
|
449
449
|
slices.pop();
|
|
450
450
|
if (!slices.length) {
|
|
451
|
-
return cache[
|
|
451
|
+
return cache[path31] = this._rules.test(path31, checkUnignored, MODE_IGNORE);
|
|
452
452
|
}
|
|
453
453
|
const parent = this._t(
|
|
454
454
|
slices.join(SLASH2) + SLASH2,
|
|
@@ -456,29 +456,29 @@ var require_ignore = __commonJS({
|
|
|
456
456
|
checkUnignored,
|
|
457
457
|
slices
|
|
458
458
|
);
|
|
459
|
-
return cache[
|
|
459
|
+
return cache[path31] = parent.ignored ? parent : this._rules.test(path31, checkUnignored, MODE_IGNORE);
|
|
460
460
|
}
|
|
461
|
-
ignores(
|
|
462
|
-
return this._test(
|
|
461
|
+
ignores(path31) {
|
|
462
|
+
return this._test(path31, this._ignoreCache, false).ignored;
|
|
463
463
|
}
|
|
464
464
|
createFilter() {
|
|
465
|
-
return (
|
|
465
|
+
return (path31) => !this.ignores(path31);
|
|
466
466
|
}
|
|
467
467
|
filter(paths) {
|
|
468
468
|
return makeArray(paths).filter(this.createFilter());
|
|
469
469
|
}
|
|
470
470
|
// @returns {TestResult}
|
|
471
|
-
test(
|
|
472
|
-
return this._test(
|
|
471
|
+
test(path31) {
|
|
472
|
+
return this._test(path31, this._testCache, true);
|
|
473
473
|
}
|
|
474
474
|
};
|
|
475
475
|
var factory = (options) => new Ignore2(options);
|
|
476
|
-
var isPathValid = (
|
|
476
|
+
var isPathValid = (path31) => checkPath(path31 && checkPath.convert(path31), path31, RETURN_FALSE);
|
|
477
477
|
var setupWindows = () => {
|
|
478
478
|
const makePosix = (str) => /^\\\\\?\\/.test(str) || /["<>|\u0000-\u001F]+/u.test(str) ? str : str.replace(/\\/g, "/");
|
|
479
479
|
checkPath.convert = makePosix;
|
|
480
480
|
const REGEX_TEST_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i;
|
|
481
|
-
checkPath.isNotRelative = (
|
|
481
|
+
checkPath.isNotRelative = (path31) => REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path31) || isNotRelative(path31);
|
|
482
482
|
};
|
|
483
483
|
if (
|
|
484
484
|
// Detect `process` so that it can run in browsers.
|
|
@@ -663,7 +663,7 @@ __export(index_exports, {
|
|
|
663
663
|
module.exports = __toCommonJS(index_exports);
|
|
664
664
|
|
|
665
665
|
// src/adapters/opencode.ts
|
|
666
|
-
var
|
|
666
|
+
var path30 = __toESM(require("path"), 1);
|
|
667
667
|
var import_url = require("url");
|
|
668
668
|
|
|
669
669
|
// src/config/constants.ts
|
|
@@ -1762,7 +1762,7 @@ function loadMergedConfig(projectRoot, host) {
|
|
|
1762
1762
|
|
|
1763
1763
|
// src/tools/operations.ts
|
|
1764
1764
|
var import_fs13 = require("fs");
|
|
1765
|
-
var
|
|
1765
|
+
var path21 = __toESM(require("path"), 1);
|
|
1766
1766
|
|
|
1767
1767
|
// src/tools/knowledge-base-paths.ts
|
|
1768
1768
|
var path8 = __toESM(require("path"), 1);
|
|
@@ -2611,8 +2611,8 @@ function formatExactSearchHandoff(results) {
|
|
|
2611
2611
|
}
|
|
2612
2612
|
function formatContextEvidence(result, index) {
|
|
2613
2613
|
const symbol = result.name ? ` ${JSON.stringify(compactEvidenceValue(result.name, 80))}` : "";
|
|
2614
|
-
const
|
|
2615
|
-
return `[${index}] ${result.chunkType}${symbol} in ${
|
|
2614
|
+
const path31 = compactEvidenceValue(result.filePath, 120);
|
|
2615
|
+
return `[${index}] ${result.chunkType}${symbol} in ${path31}:${result.startLine}-${result.endLine} (score ${result.score.toFixed(2)})`;
|
|
2616
2616
|
}
|
|
2617
2617
|
function formatContextPack(heading, selected, candidateCount, duplicateCount, limitOmittedCount, budgetOmittedCount, includeExactSearchHandoff) {
|
|
2618
2618
|
const lines = selected.map((result, index) => formatContextEvidence(result, index + 1));
|
|
@@ -3255,8 +3255,8 @@ function formatEffectivenessMetrics(snapshot) {
|
|
|
3255
3255
|
|
|
3256
3256
|
// src/utils/auto-index.ts
|
|
3257
3257
|
var import_fs7 = require("fs");
|
|
3258
|
-
var
|
|
3259
|
-
var
|
|
3258
|
+
var os4 = __toESM(require("os"), 1);
|
|
3259
|
+
var path12 = __toESM(require("path"), 1);
|
|
3260
3260
|
|
|
3261
3261
|
// src/indexer/index-lock.ts
|
|
3262
3262
|
var import_crypto = require("crypto");
|
|
@@ -3503,7 +3503,7 @@ function removeDeadReclaimMarker(lockPath, expectedOwner) {
|
|
|
3503
3503
|
return true;
|
|
3504
3504
|
}
|
|
3505
3505
|
function reclaimDeadOwner(indexPath, lockPath, expectedOwner) {
|
|
3506
|
-
const
|
|
3506
|
+
const reclaimPath2 = path9.join(lockPath, RECLAIM_DIRECTORY_NAME);
|
|
3507
3507
|
const reclaimOwner = {
|
|
3508
3508
|
pid: process.pid,
|
|
3509
3509
|
hostname: os2.hostname(),
|
|
@@ -3512,19 +3512,19 @@ function reclaimDeadOwner(indexPath, lockPath, expectedOwner) {
|
|
|
3512
3512
|
expectedOwnerToken: expectedOwner.token
|
|
3513
3513
|
};
|
|
3514
3514
|
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
3515
|
-
if (publishJsonDirectory(
|
|
3515
|
+
if (publishJsonDirectory(reclaimPath2, reclaimOwner)) break;
|
|
3516
3516
|
if (attempt === 0 && removeDeadReclaimMarker(lockPath, expectedOwner)) continue;
|
|
3517
3517
|
return false;
|
|
3518
3518
|
}
|
|
3519
3519
|
try {
|
|
3520
|
-
const currentReclaimer = readReclaimOwner(
|
|
3520
|
+
const currentReclaimer = readReclaimOwner(reclaimPath2);
|
|
3521
3521
|
const currentOwner = readDirectoryOwner(lockPath);
|
|
3522
3522
|
if (!currentReclaimer || !sameReclaimOwner(currentReclaimer, reclaimOwner) || !currentOwner || !sameOwner(currentOwner, expectedOwner) || getOwnerLiveness(currentOwner) !== "dead") {
|
|
3523
3523
|
return false;
|
|
3524
3524
|
}
|
|
3525
3525
|
publishRecoveryMarker(indexPath, expectedOwner);
|
|
3526
3526
|
const ownerBeforeQuarantine = readDirectoryOwner(lockPath);
|
|
3527
|
-
const reclaimerBeforeQuarantine = readReclaimOwner(
|
|
3527
|
+
const reclaimerBeforeQuarantine = readReclaimOwner(reclaimPath2);
|
|
3528
3528
|
if (!ownerBeforeQuarantine || !sameOwner(ownerBeforeQuarantine, expectedOwner) || getOwnerLiveness(ownerBeforeQuarantine) !== "dead" || !reclaimerBeforeQuarantine || !sameReclaimOwner(reclaimerBeforeQuarantine, reclaimOwner)) {
|
|
3529
3529
|
return false;
|
|
3530
3530
|
}
|
|
@@ -3694,10 +3694,884 @@ function completeLeaseRecovery(lease) {
|
|
|
3694
3694
|
}
|
|
3695
3695
|
}
|
|
3696
3696
|
|
|
3697
|
+
// src/utils/background-worker.ts
|
|
3698
|
+
var import_node_crypto = require("crypto");
|
|
3699
|
+
var import_node_fs = require("fs");
|
|
3700
|
+
var os3 = __toESM(require("os"), 1);
|
|
3701
|
+
var path10 = __toESM(require("path"), 1);
|
|
3702
|
+
var OWNER_FILE_NAME2 = "owner.json";
|
|
3703
|
+
var HEARTBEAT_FILE_PREFIX = "heartbeat.";
|
|
3704
|
+
var RECLAIM_DIRECTORY_NAME2 = "reclaim";
|
|
3705
|
+
var REFRESH_REQUEST_FILE_NAME = "refresh-request.json";
|
|
3706
|
+
var HEARTBEAT_INTERVAL_MS = 5e3;
|
|
3707
|
+
var STALE_LEASE_MS = 3e4;
|
|
3708
|
+
var RETRY_DELAY_MS = 5e3;
|
|
3709
|
+
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;
|
|
3710
|
+
var BackgroundWorkerStopError = class extends Error {
|
|
3711
|
+
constructor(watcherError, autoIndexError) {
|
|
3712
|
+
super("Failed to stop background worker");
|
|
3713
|
+
this.watcherError = watcherError;
|
|
3714
|
+
this.autoIndexError = autoIndexError;
|
|
3715
|
+
this.name = "BackgroundWorkerStopError";
|
|
3716
|
+
}
|
|
3717
|
+
watcherError;
|
|
3718
|
+
autoIndexError;
|
|
3719
|
+
};
|
|
3720
|
+
var workers = /* @__PURE__ */ new Map();
|
|
3721
|
+
var workerKeysByProject = /* @__PURE__ */ new Map();
|
|
3722
|
+
var workerReplacementBarriers = /* @__PURE__ */ new Map();
|
|
3723
|
+
function getErrorCode2(error) {
|
|
3724
|
+
return typeof error === "object" && error !== null && "code" in error ? String(error.code) : void 0;
|
|
3725
|
+
}
|
|
3726
|
+
function canonicalizePath(targetPath) {
|
|
3727
|
+
const resolved = path10.resolve(targetPath);
|
|
3728
|
+
if ((0, import_node_fs.existsSync)(resolved)) {
|
|
3729
|
+
try {
|
|
3730
|
+
return import_node_fs.realpathSync.native(resolved);
|
|
3731
|
+
} catch {
|
|
3732
|
+
return resolved;
|
|
3733
|
+
}
|
|
3734
|
+
}
|
|
3735
|
+
const parent = path10.dirname(resolved);
|
|
3736
|
+
if (parent === resolved) return resolved;
|
|
3737
|
+
return path10.join(canonicalizePath(parent), path10.basename(resolved));
|
|
3738
|
+
}
|
|
3739
|
+
function projectLookupKey(projectRoot, host) {
|
|
3740
|
+
return `${host}::${canonicalizePath(projectRoot)}`;
|
|
3741
|
+
}
|
|
3742
|
+
function resolveIdentity(projectRoot, config, host) {
|
|
3743
|
+
const canonicalProjectRoot = canonicalizePath(projectRoot);
|
|
3744
|
+
const canonicalIndexPath = canonicalizePath(resolveProjectIndexPath(projectRoot, config.scope, host));
|
|
3745
|
+
return {
|
|
3746
|
+
canonicalIndexPath,
|
|
3747
|
+
canonicalProjectRoot,
|
|
3748
|
+
key: `${canonicalIndexPath}::${canonicalProjectRoot}`
|
|
3749
|
+
};
|
|
3750
|
+
}
|
|
3751
|
+
function controllerKey(identity, host) {
|
|
3752
|
+
return `${identity.key}::${host}`;
|
|
3753
|
+
}
|
|
3754
|
+
function leaseDirectoryName(identity) {
|
|
3755
|
+
const hash = (0, import_node_crypto.createHash)("sha256").update(identity.key).digest("hex").slice(0, 32);
|
|
3756
|
+
return `background-worker.${hash}.lease`;
|
|
3757
|
+
}
|
|
3758
|
+
function leasePathFor(identity) {
|
|
3759
|
+
return path10.join(identity.canonicalIndexPath, leaseDirectoryName(identity));
|
|
3760
|
+
}
|
|
3761
|
+
function parseOwner2(value) {
|
|
3762
|
+
if (typeof value !== "object" || value === null) return null;
|
|
3763
|
+
const candidate = value;
|
|
3764
|
+
if (candidate.version !== 1) return null;
|
|
3765
|
+
if (!Number.isInteger(candidate.pid) || (candidate.pid ?? 0) <= 0) return null;
|
|
3766
|
+
if (typeof candidate.hostname !== "string" || candidate.hostname.length === 0) return null;
|
|
3767
|
+
if (typeof candidate.startedAt !== "string" || Number.isNaN(Date.parse(candidate.startedAt))) return null;
|
|
3768
|
+
if (typeof candidate.heartbeatAt !== "string" || Number.isNaN(Date.parse(candidate.heartbeatAt))) return null;
|
|
3769
|
+
if (typeof candidate.projectRoot !== "string" || candidate.projectRoot.length === 0) return null;
|
|
3770
|
+
if (typeof candidate.indexPath !== "string" || candidate.indexPath.length === 0) return null;
|
|
3771
|
+
if (typeof candidate.token !== "string" || !UUID_PATTERN2.test(candidate.token)) return null;
|
|
3772
|
+
return candidate;
|
|
3773
|
+
}
|
|
3774
|
+
function parseHeartbeat(value, expectedToken) {
|
|
3775
|
+
if (typeof value !== "object" || value === null) return null;
|
|
3776
|
+
const candidate = value;
|
|
3777
|
+
if (candidate.version !== 1 || candidate.token !== expectedToken) return null;
|
|
3778
|
+
if (typeof candidate.heartbeatAt !== "string" || Number.isNaN(Date.parse(candidate.heartbeatAt))) return null;
|
|
3779
|
+
return candidate;
|
|
3780
|
+
}
|
|
3781
|
+
function parseReclaimOwner2(value) {
|
|
3782
|
+
if (typeof value !== "object" || value === null) return null;
|
|
3783
|
+
const candidate = value;
|
|
3784
|
+
if (candidate.version !== 1) return null;
|
|
3785
|
+
if (!Number.isInteger(candidate.pid) || (candidate.pid ?? 0) <= 0) return null;
|
|
3786
|
+
if (typeof candidate.hostname !== "string" || candidate.hostname.length === 0) return null;
|
|
3787
|
+
if (typeof candidate.startedAt !== "string" || Number.isNaN(Date.parse(candidate.startedAt))) return null;
|
|
3788
|
+
if (typeof candidate.token !== "string" || !UUID_PATTERN2.test(candidate.token)) return null;
|
|
3789
|
+
if (candidate.expectedOwnerToken !== null && (typeof candidate.expectedOwnerToken !== "string" || !UUID_PATTERN2.test(candidate.expectedOwnerToken))) return null;
|
|
3790
|
+
return candidate;
|
|
3791
|
+
}
|
|
3792
|
+
function heartbeatPath(leasePath, token) {
|
|
3793
|
+
return path10.join(leasePath, `${HEARTBEAT_FILE_PREFIX}${token}.json`);
|
|
3794
|
+
}
|
|
3795
|
+
function reclaimPath(leasePath) {
|
|
3796
|
+
return path10.join(leasePath, RECLAIM_DIRECTORY_NAME2);
|
|
3797
|
+
}
|
|
3798
|
+
function refreshRequestPath(leasePath) {
|
|
3799
|
+
return path10.join(leasePath, REFRESH_REQUEST_FILE_NAME);
|
|
3800
|
+
}
|
|
3801
|
+
function readLeaseOwner(leasePath) {
|
|
3802
|
+
try {
|
|
3803
|
+
return parseOwner2(JSON.parse((0, import_node_fs.readFileSync)(path10.join(leasePath, OWNER_FILE_NAME2), "utf-8")));
|
|
3804
|
+
} catch {
|
|
3805
|
+
return null;
|
|
3806
|
+
}
|
|
3807
|
+
}
|
|
3808
|
+
function readOwner(leasePath) {
|
|
3809
|
+
const owner = readLeaseOwner(leasePath);
|
|
3810
|
+
if (!owner) return null;
|
|
3811
|
+
try {
|
|
3812
|
+
const heartbeat = parseHeartbeat(
|
|
3813
|
+
JSON.parse((0, import_node_fs.readFileSync)(heartbeatPath(leasePath, owner.token), "utf-8")),
|
|
3814
|
+
owner.token
|
|
3815
|
+
);
|
|
3816
|
+
return heartbeat ? { ...owner, heartbeatAt: heartbeat.heartbeatAt } : owner;
|
|
3817
|
+
} catch {
|
|
3818
|
+
return owner;
|
|
3819
|
+
}
|
|
3820
|
+
}
|
|
3821
|
+
function readReclaimOwner2(leasePath) {
|
|
3822
|
+
try {
|
|
3823
|
+
return parseReclaimOwner2(JSON.parse((0, import_node_fs.readFileSync)(path10.join(reclaimPath(leasePath), OWNER_FILE_NAME2), "utf-8")));
|
|
3824
|
+
} catch {
|
|
3825
|
+
return null;
|
|
3826
|
+
}
|
|
3827
|
+
}
|
|
3828
|
+
function ownerLiveness(owner) {
|
|
3829
|
+
if (owner.hostname !== os3.hostname()) return "unknown";
|
|
3830
|
+
try {
|
|
3831
|
+
process.kill(owner.pid, 0);
|
|
3832
|
+
return "alive";
|
|
3833
|
+
} catch (error) {
|
|
3834
|
+
const code = getErrorCode2(error);
|
|
3835
|
+
if (code === "ESRCH") return "dead";
|
|
3836
|
+
if (code === "EPERM") return "alive";
|
|
3837
|
+
return "unknown";
|
|
3838
|
+
}
|
|
3839
|
+
}
|
|
3840
|
+
function isHeartbeatExpired(owner) {
|
|
3841
|
+
return Date.now() - Date.parse(owner.heartbeatAt) >= STALE_LEASE_MS;
|
|
3842
|
+
}
|
|
3843
|
+
function sameOwner2(left, right) {
|
|
3844
|
+
return left.pid === right.pid && left.hostname === right.hostname && left.token === right.token;
|
|
3845
|
+
}
|
|
3846
|
+
function writeHeartbeat(leasePath, owner) {
|
|
3847
|
+
const targetPath = heartbeatPath(leasePath, owner.token);
|
|
3848
|
+
const temporaryPath = `${targetPath}.tmp.${process.pid}.${owner.token}.${(0, import_node_crypto.randomUUID)()}`;
|
|
3849
|
+
const heartbeat = {
|
|
3850
|
+
version: 1,
|
|
3851
|
+
token: owner.token,
|
|
3852
|
+
heartbeatAt: owner.heartbeatAt
|
|
3853
|
+
};
|
|
3854
|
+
try {
|
|
3855
|
+
(0, import_node_fs.writeFileSync)(temporaryPath, JSON.stringify(heartbeat), {
|
|
3856
|
+
encoding: "utf-8",
|
|
3857
|
+
flag: "wx",
|
|
3858
|
+
mode: 384
|
|
3859
|
+
});
|
|
3860
|
+
(0, import_node_fs.renameSync)(temporaryPath, targetPath);
|
|
3861
|
+
const currentOwner = readLeaseOwner(leasePath);
|
|
3862
|
+
return currentOwner !== null && sameOwner2(currentOwner, owner);
|
|
3863
|
+
} finally {
|
|
3864
|
+
if ((0, import_node_fs.existsSync)(temporaryPath)) (0, import_node_fs.rmSync)(temporaryPath, { force: true });
|
|
3865
|
+
}
|
|
3866
|
+
}
|
|
3867
|
+
function requestRefreshFromLeader(leasePath, allowDisabledAutoIndex) {
|
|
3868
|
+
const requestPath = refreshRequestPath(leasePath);
|
|
3869
|
+
const temporaryPath = `${requestPath}.tmp.${process.pid}.${(0, import_node_crypto.randomUUID)()}`;
|
|
3870
|
+
try {
|
|
3871
|
+
const request = {
|
|
3872
|
+
allowDisabledAutoIndex,
|
|
3873
|
+
requestedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3874
|
+
version: 1
|
|
3875
|
+
};
|
|
3876
|
+
(0, import_node_fs.writeFileSync)(temporaryPath, JSON.stringify(request), {
|
|
3877
|
+
encoding: "utf-8",
|
|
3878
|
+
flag: "wx",
|
|
3879
|
+
mode: 384
|
|
3880
|
+
});
|
|
3881
|
+
(0, import_node_fs.renameSync)(temporaryPath, requestPath);
|
|
3882
|
+
} catch (error) {
|
|
3883
|
+
if (getErrorCode2(error) !== "ENOENT") {
|
|
3884
|
+
console.error("[codebase-index] Failed to request background index refresh from the project worker:", error);
|
|
3885
|
+
}
|
|
3886
|
+
} finally {
|
|
3887
|
+
if ((0, import_node_fs.existsSync)(temporaryPath)) (0, import_node_fs.rmSync)(temporaryPath, { force: true });
|
|
3888
|
+
}
|
|
3889
|
+
}
|
|
3890
|
+
function consumeRefreshRequest(leasePath) {
|
|
3891
|
+
const requestPath = refreshRequestPath(leasePath);
|
|
3892
|
+
const claimedPath = `${requestPath}.handling.${process.pid}.${(0, import_node_crypto.randomUUID)()}`;
|
|
3893
|
+
try {
|
|
3894
|
+
(0, import_node_fs.renameSync)(requestPath, claimedPath);
|
|
3895
|
+
} catch (error) {
|
|
3896
|
+
if (getErrorCode2(error) === "ENOENT") return null;
|
|
3897
|
+
throw error;
|
|
3898
|
+
}
|
|
3899
|
+
try {
|
|
3900
|
+
const value = JSON.parse((0, import_node_fs.readFileSync)(claimedPath, "utf-8"));
|
|
3901
|
+
return {
|
|
3902
|
+
allowDisabledAutoIndex: value.version === 1 && value.allowDisabledAutoIndex === true,
|
|
3903
|
+
requestedAt: typeof value.requestedAt === "string" ? value.requestedAt : (/* @__PURE__ */ new Date()).toISOString(),
|
|
3904
|
+
version: 1
|
|
3905
|
+
};
|
|
3906
|
+
} catch {
|
|
3907
|
+
return { allowDisabledAutoIndex: false, requestedAt: (/* @__PURE__ */ new Date()).toISOString(), version: 1 };
|
|
3908
|
+
} finally {
|
|
3909
|
+
(0, import_node_fs.rmSync)(claimedPath, { force: true });
|
|
3910
|
+
}
|
|
3911
|
+
}
|
|
3912
|
+
function publishLease(leasePath, owner) {
|
|
3913
|
+
const candidatePath = `${leasePath}.candidate.${process.pid}.${owner.token}`;
|
|
3914
|
+
try {
|
|
3915
|
+
(0, import_node_fs.mkdirSync)(candidatePath, { mode: 448 });
|
|
3916
|
+
} catch (error) {
|
|
3917
|
+
if (getErrorCode2(error) === "ENOENT") return false;
|
|
3918
|
+
throw error;
|
|
3919
|
+
}
|
|
3920
|
+
try {
|
|
3921
|
+
(0, import_node_fs.writeFileSync)(path10.join(candidatePath, OWNER_FILE_NAME2), JSON.stringify(owner), {
|
|
3922
|
+
encoding: "utf-8",
|
|
3923
|
+
flag: "wx",
|
|
3924
|
+
mode: 384
|
|
3925
|
+
});
|
|
3926
|
+
if ((0, import_node_fs.existsSync)(leasePath)) return false;
|
|
3927
|
+
try {
|
|
3928
|
+
(0, import_node_fs.renameSync)(candidatePath, leasePath);
|
|
3929
|
+
return true;
|
|
3930
|
+
} catch (error) {
|
|
3931
|
+
if ((0, import_node_fs.existsSync)(leasePath) || getErrorCode2(error) === "ENOENT") return false;
|
|
3932
|
+
throw error;
|
|
3933
|
+
}
|
|
3934
|
+
} finally {
|
|
3935
|
+
if ((0, import_node_fs.existsSync)(candidatePath)) (0, import_node_fs.rmSync)(candidatePath, { recursive: true, force: true });
|
|
3936
|
+
}
|
|
3937
|
+
}
|
|
3938
|
+
function sameReclaimOwner2(left, right) {
|
|
3939
|
+
return left.pid === right.pid && left.hostname === right.hostname && left.token === right.token && left.expectedOwnerToken === right.expectedOwnerToken;
|
|
3940
|
+
}
|
|
3941
|
+
function reclaimerLiveness(owner) {
|
|
3942
|
+
return ownerLiveness(owner);
|
|
3943
|
+
}
|
|
3944
|
+
function isReclaimMarkerExpired(leasePath, owner) {
|
|
3945
|
+
const startedAt = owner ? Date.parse(owner.startedAt) : (() => {
|
|
3946
|
+
try {
|
|
3947
|
+
return (0, import_node_fs.lstatSync)(reclaimPath(leasePath)).mtimeMs;
|
|
3948
|
+
} catch {
|
|
3949
|
+
return Date.now();
|
|
3950
|
+
}
|
|
3951
|
+
})();
|
|
3952
|
+
return Date.now() - startedAt >= STALE_LEASE_MS;
|
|
3953
|
+
}
|
|
3954
|
+
function hasActiveReclaimMarker(leasePath, owner) {
|
|
3955
|
+
const marker = readReclaimOwner2(leasePath);
|
|
3956
|
+
return marker !== null && marker.expectedOwnerToken === owner.token && (marker.hostname !== os3.hostname() || ownerLiveness(owner) !== "alive");
|
|
3957
|
+
}
|
|
3958
|
+
function publishReclaimMarker(leasePath, expectedOwner) {
|
|
3959
|
+
const markerPath = reclaimPath(leasePath);
|
|
3960
|
+
const owner = {
|
|
3961
|
+
version: 1,
|
|
3962
|
+
pid: process.pid,
|
|
3963
|
+
hostname: os3.hostname(),
|
|
3964
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3965
|
+
token: (0, import_node_crypto.randomUUID)(),
|
|
3966
|
+
expectedOwnerToken: expectedOwner?.token ?? null
|
|
3967
|
+
};
|
|
3968
|
+
try {
|
|
3969
|
+
(0, import_node_fs.mkdirSync)(markerPath, { mode: 448 });
|
|
3970
|
+
} catch (error) {
|
|
3971
|
+
if (getErrorCode2(error) === "EEXIST" || getErrorCode2(error) === "ENOENT") return null;
|
|
3972
|
+
throw error;
|
|
3973
|
+
}
|
|
3974
|
+
try {
|
|
3975
|
+
(0, import_node_fs.writeFileSync)(path10.join(markerPath, OWNER_FILE_NAME2), JSON.stringify(owner), {
|
|
3976
|
+
encoding: "utf-8",
|
|
3977
|
+
flag: "wx",
|
|
3978
|
+
mode: 384
|
|
3979
|
+
});
|
|
3980
|
+
return owner;
|
|
3981
|
+
} catch (error) {
|
|
3982
|
+
(0, import_node_fs.rmSync)(markerPath, { recursive: true, force: true });
|
|
3983
|
+
throw error;
|
|
3984
|
+
}
|
|
3985
|
+
}
|
|
3986
|
+
function removeExpiredReclaimMarker(leasePath, expectedOwner) {
|
|
3987
|
+
const marker = readReclaimOwner2(leasePath);
|
|
3988
|
+
const markerPath = reclaimPath(leasePath);
|
|
3989
|
+
if (!(0, import_node_fs.existsSync)(markerPath)) return false;
|
|
3990
|
+
if (marker && marker.expectedOwnerToken !== (expectedOwner?.token ?? null)) return false;
|
|
3991
|
+
if (marker && (reclaimerLiveness(marker) === "alive" || !isReclaimMarkerExpired(leasePath, marker))) return false;
|
|
3992
|
+
if (!marker && !isReclaimMarkerExpired(leasePath, null)) return false;
|
|
3993
|
+
const staleMarkerPath = `${markerPath}.stale.${marker?.pid ?? process.pid}.${marker?.token ?? (0, import_node_crypto.randomUUID)()}.${(0, import_node_crypto.randomUUID)()}`;
|
|
3994
|
+
try {
|
|
3995
|
+
(0, import_node_fs.renameSync)(markerPath, staleMarkerPath);
|
|
3996
|
+
} catch (error) {
|
|
3997
|
+
if (getErrorCode2(error) === "ENOENT") return false;
|
|
3998
|
+
throw error;
|
|
3999
|
+
}
|
|
4000
|
+
try {
|
|
4001
|
+
let claimedMarker = null;
|
|
4002
|
+
try {
|
|
4003
|
+
claimedMarker = parseReclaimOwner2(
|
|
4004
|
+
JSON.parse((0, import_node_fs.readFileSync)(path10.join(staleMarkerPath, OWNER_FILE_NAME2), "utf-8"))
|
|
4005
|
+
);
|
|
4006
|
+
} catch {
|
|
4007
|
+
claimedMarker = null;
|
|
4008
|
+
}
|
|
4009
|
+
const markerMatches = marker ? claimedMarker !== null && sameReclaimOwner2(claimedMarker, marker) : claimedMarker === null;
|
|
4010
|
+
if (!markerMatches || !canReclaimLease(leasePath, expectedOwner)) {
|
|
4011
|
+
if (!(0, import_node_fs.existsSync)(markerPath) && (0, import_node_fs.existsSync)(staleMarkerPath)) (0, import_node_fs.renameSync)(staleMarkerPath, markerPath);
|
|
4012
|
+
return false;
|
|
4013
|
+
}
|
|
4014
|
+
(0, import_node_fs.rmSync)(staleMarkerPath, { recursive: true, force: true });
|
|
4015
|
+
return true;
|
|
4016
|
+
} catch (error) {
|
|
4017
|
+
if (getErrorCode2(error) === "ENOENT") return false;
|
|
4018
|
+
throw error;
|
|
4019
|
+
}
|
|
4020
|
+
}
|
|
4021
|
+
function canReclaimLease(leasePath, expectedOwner) {
|
|
4022
|
+
if (!(0, import_node_fs.existsSync)(leasePath)) return false;
|
|
4023
|
+
if (!expectedOwner) return false;
|
|
4024
|
+
const currentOwner = readOwner(leasePath);
|
|
4025
|
+
if (!currentOwner || !sameOwner2(currentOwner, expectedOwner)) return false;
|
|
4026
|
+
if (currentOwner.hostname === os3.hostname()) {
|
|
4027
|
+
return ownerLiveness(currentOwner) === "dead";
|
|
4028
|
+
}
|
|
4029
|
+
return isHeartbeatExpired(currentOwner);
|
|
4030
|
+
}
|
|
4031
|
+
function reclaimLease(leasePath, expectedOwner) {
|
|
4032
|
+
let marker = null;
|
|
4033
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
4034
|
+
marker = publishReclaimMarker(leasePath, expectedOwner);
|
|
4035
|
+
if (marker) break;
|
|
4036
|
+
if (attempt === 0 && removeExpiredReclaimMarker(leasePath, expectedOwner)) continue;
|
|
4037
|
+
return false;
|
|
4038
|
+
}
|
|
4039
|
+
if (!marker) return false;
|
|
4040
|
+
const markerPath = reclaimPath(leasePath);
|
|
4041
|
+
try {
|
|
4042
|
+
const currentMarker = readReclaimOwner2(leasePath);
|
|
4043
|
+
if (!currentMarker || !sameReclaimOwner2(currentMarker, marker) || !canReclaimLease(leasePath, expectedOwner)) {
|
|
4044
|
+
return false;
|
|
4045
|
+
}
|
|
4046
|
+
const stalePath = `${leasePath}.stale.${process.pid}.${marker.token}`;
|
|
4047
|
+
(0, import_node_fs.renameSync)(leasePath, stalePath);
|
|
4048
|
+
const quarantinedOwner = readOwner(stalePath);
|
|
4049
|
+
const quarantinedMarker = readReclaimOwner2(stalePath);
|
|
4050
|
+
if (!quarantinedMarker || !sameReclaimOwner2(quarantinedMarker, marker) || expectedOwner !== null && (!quarantinedOwner || !sameOwner2(quarantinedOwner, expectedOwner))) {
|
|
4051
|
+
if (!(0, import_node_fs.existsSync)(leasePath) && (0, import_node_fs.existsSync)(stalePath)) (0, import_node_fs.renameSync)(stalePath, leasePath);
|
|
4052
|
+
return false;
|
|
4053
|
+
}
|
|
4054
|
+
(0, import_node_fs.rmSync)(stalePath, { recursive: true, force: true });
|
|
4055
|
+
return true;
|
|
4056
|
+
} catch (error) {
|
|
4057
|
+
if (getErrorCode2(error) === "ENOENT") return false;
|
|
4058
|
+
throw error;
|
|
4059
|
+
} finally {
|
|
4060
|
+
const currentMarker = readReclaimOwner2(leasePath);
|
|
4061
|
+
if (currentMarker && sameReclaimOwner2(currentMarker, marker)) {
|
|
4062
|
+
(0, import_node_fs.rmSync)(markerPath, { recursive: true, force: true });
|
|
4063
|
+
}
|
|
4064
|
+
}
|
|
4065
|
+
}
|
|
4066
|
+
function acquireLease(identity) {
|
|
4067
|
+
(0, import_node_fs.mkdirSync)(identity.canonicalIndexPath, { recursive: true, mode: 448 });
|
|
4068
|
+
const canonicalIndexPath = import_node_fs.realpathSync.native(identity.canonicalIndexPath);
|
|
4069
|
+
const leasePath = path10.join(canonicalIndexPath, leaseDirectoryName({ ...identity, canonicalIndexPath }));
|
|
4070
|
+
for (let attempt = 0; attempt < 4; attempt += 1) {
|
|
4071
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
4072
|
+
const owner = {
|
|
4073
|
+
version: 1,
|
|
4074
|
+
pid: process.pid,
|
|
4075
|
+
hostname: os3.hostname(),
|
|
4076
|
+
startedAt: timestamp,
|
|
4077
|
+
heartbeatAt: timestamp,
|
|
4078
|
+
projectRoot: identity.canonicalProjectRoot,
|
|
4079
|
+
indexPath: canonicalIndexPath,
|
|
4080
|
+
token: (0, import_node_crypto.randomUUID)()
|
|
4081
|
+
};
|
|
4082
|
+
if (publishLease(leasePath, owner)) {
|
|
4083
|
+
return { leasePath, owner };
|
|
4084
|
+
}
|
|
4085
|
+
const existingOwner = readOwner(leasePath);
|
|
4086
|
+
if (existingOwner) {
|
|
4087
|
+
if (canReclaimLease(leasePath, existingOwner) && reclaimLease(leasePath, existingOwner)) continue;
|
|
4088
|
+
return null;
|
|
4089
|
+
}
|
|
4090
|
+
return null;
|
|
4091
|
+
}
|
|
4092
|
+
return null;
|
|
4093
|
+
}
|
|
4094
|
+
function releaseLease(lease) {
|
|
4095
|
+
const currentOwner = readOwner(lease.leasePath);
|
|
4096
|
+
if (!currentOwner || !sameOwner2(currentOwner, lease.owner)) return false;
|
|
4097
|
+
const releasePath = `${lease.leasePath}.release.${lease.owner.pid}.${lease.owner.token}`;
|
|
4098
|
+
try {
|
|
4099
|
+
(0, import_node_fs.renameSync)(lease.leasePath, releasePath);
|
|
4100
|
+
} catch (error) {
|
|
4101
|
+
if (getErrorCode2(error) === "ENOENT") return false;
|
|
4102
|
+
throw error;
|
|
4103
|
+
}
|
|
4104
|
+
const claimedOwner = readOwner(releasePath);
|
|
4105
|
+
if (!claimedOwner || !sameOwner2(claimedOwner, lease.owner)) {
|
|
4106
|
+
if (!(0, import_node_fs.existsSync)(lease.leasePath) && (0, import_node_fs.existsSync)(releasePath)) {
|
|
4107
|
+
(0, import_node_fs.renameSync)(releasePath, lease.leasePath);
|
|
4108
|
+
}
|
|
4109
|
+
return false;
|
|
4110
|
+
}
|
|
4111
|
+
(0, import_node_fs.rmSync)(releasePath, { recursive: true, force: true });
|
|
4112
|
+
return true;
|
|
4113
|
+
}
|
|
4114
|
+
var BackgroundWorkerController = class {
|
|
4115
|
+
constructor(projectRoot, host, config, hooks, identity) {
|
|
4116
|
+
this.projectRoot = projectRoot;
|
|
4117
|
+
this.host = host;
|
|
4118
|
+
this.config = config;
|
|
4119
|
+
this.hooks = hooks;
|
|
4120
|
+
this.identity = identity;
|
|
4121
|
+
}
|
|
4122
|
+
projectRoot;
|
|
4123
|
+
host;
|
|
4124
|
+
config;
|
|
4125
|
+
hooks;
|
|
4126
|
+
identity;
|
|
4127
|
+
lease = null;
|
|
4128
|
+
watcher = null;
|
|
4129
|
+
leaderReady = Promise.resolve();
|
|
4130
|
+
heartbeatTimer = null;
|
|
4131
|
+
retryTimer = null;
|
|
4132
|
+
teardownRetryTimer = null;
|
|
4133
|
+
transition = Promise.resolve();
|
|
4134
|
+
stopPromise = null;
|
|
4135
|
+
stopped = false;
|
|
4136
|
+
stopping = false;
|
|
4137
|
+
losingLeadership = false;
|
|
4138
|
+
restartAfterStop = false;
|
|
4139
|
+
leaderWorkStopped = false;
|
|
4140
|
+
startingLeaderWork = false;
|
|
4141
|
+
stopAutoIndexOnTeardown = true;
|
|
4142
|
+
autoIndexStarted = false;
|
|
4143
|
+
reportedError = null;
|
|
4144
|
+
update(config, hooks, options) {
|
|
4145
|
+
const autoIndexWasEnabled = this.config.indexing.autoIndex;
|
|
4146
|
+
const shouldReplaceWatcher = this.watcher !== null && hooks.watcherFactory !== void 0 && (hooks.watcherFactory === null || hooks.replaceWatcher === true);
|
|
4147
|
+
this.config = config;
|
|
4148
|
+
this.hooks = {
|
|
4149
|
+
...this.hooks,
|
|
4150
|
+
...hooks,
|
|
4151
|
+
watcherFactory: hooks.watcherFactory === void 0 ? this.hooks.watcherFactory : hooks.watcherFactory,
|
|
4152
|
+
watcherFactoryForConfig: hooks.watcherFactoryForConfig === void 0 ? this.hooks.watcherFactoryForConfig : hooks.watcherFactoryForConfig
|
|
4153
|
+
};
|
|
4154
|
+
if (autoIndexWasEnabled && !config.indexing.autoIndex || options.restartAutoIndex === true && config.indexing.autoIndex && !this.startingLeaderWork) {
|
|
4155
|
+
this.autoIndexStarted = false;
|
|
4156
|
+
}
|
|
4157
|
+
if (!this.canRun()) {
|
|
4158
|
+
void this.stop().catch((error) => {
|
|
4159
|
+
console.error("[codebase-index] Failed to stop background worker after disabling automatic work:", error);
|
|
4160
|
+
});
|
|
4161
|
+
return;
|
|
4162
|
+
}
|
|
4163
|
+
if (shouldReplaceWatcher) {
|
|
4164
|
+
void this.enqueue(async () => {
|
|
4165
|
+
const watcher = this.watcher;
|
|
4166
|
+
if (watcher) {
|
|
4167
|
+
await watcher.stop();
|
|
4168
|
+
if (this.watcher === watcher) this.watcher = null;
|
|
4169
|
+
}
|
|
4170
|
+
if (this.lease && !this.stopped) this.startLeaderWork();
|
|
4171
|
+
}).catch((error) => {
|
|
4172
|
+
console.error("[codebase-index] Failed to replace background file watcher:", error);
|
|
4173
|
+
});
|
|
4174
|
+
}
|
|
4175
|
+
this.start();
|
|
4176
|
+
}
|
|
4177
|
+
startAfter(activation) {
|
|
4178
|
+
this.transition = activation.catch(() => void 0);
|
|
4179
|
+
this.start();
|
|
4180
|
+
}
|
|
4181
|
+
start() {
|
|
4182
|
+
if (!this.canRun() || this.losingLeadership) return;
|
|
4183
|
+
if (this.stopping) {
|
|
4184
|
+
this.restartAfterStop = true;
|
|
4185
|
+
return;
|
|
4186
|
+
}
|
|
4187
|
+
this.stopped = false;
|
|
4188
|
+
void this.enqueue(async () => {
|
|
4189
|
+
if (this.stopped || this.stopping || this.losingLeadership || !this.canRun()) return;
|
|
4190
|
+
if (!this.lease) {
|
|
4191
|
+
try {
|
|
4192
|
+
this.lease = acquireLease(this.identity);
|
|
4193
|
+
this.reportedError = null;
|
|
4194
|
+
} catch (error) {
|
|
4195
|
+
this.reportAcquireError(error);
|
|
4196
|
+
this.scheduleRetry();
|
|
4197
|
+
return;
|
|
4198
|
+
}
|
|
4199
|
+
}
|
|
4200
|
+
if (!this.lease) {
|
|
4201
|
+
this.scheduleRetry();
|
|
4202
|
+
return;
|
|
4203
|
+
}
|
|
4204
|
+
this.startHeartbeat();
|
|
4205
|
+
this.startLeaderWork();
|
|
4206
|
+
});
|
|
4207
|
+
}
|
|
4208
|
+
waitForStart() {
|
|
4209
|
+
return this.transition.catch(() => void 0).then(() => this.leaderReady);
|
|
4210
|
+
}
|
|
4211
|
+
requestRefresh(allowDisabledAutoIndex = false) {
|
|
4212
|
+
this.start();
|
|
4213
|
+
if (!this.isLeader()) {
|
|
4214
|
+
requestRefreshFromLeader(leasePathFor(this.identity), allowDisabledAutoIndex);
|
|
4215
|
+
return;
|
|
4216
|
+
}
|
|
4217
|
+
void this.enqueue(async () => {
|
|
4218
|
+
if (this.stopped || !this.lease) return;
|
|
4219
|
+
this.hooks.startAutoIndex("retrieval", allowDisabledAutoIndex);
|
|
4220
|
+
});
|
|
4221
|
+
}
|
|
4222
|
+
isLeader() {
|
|
4223
|
+
return this.lease !== null && !this.stopping && !this.losingLeadership;
|
|
4224
|
+
}
|
|
4225
|
+
isStopping() {
|
|
4226
|
+
return this.stopping;
|
|
4227
|
+
}
|
|
4228
|
+
getHooksForConfig(config) {
|
|
4229
|
+
const watcherFactoryForConfig = this.hooks.watcherFactoryForConfig;
|
|
4230
|
+
if (!watcherFactoryForConfig) return this.hooks;
|
|
4231
|
+
return {
|
|
4232
|
+
...this.hooks,
|
|
4233
|
+
watcherFactory: watcherFactoryForConfig(config),
|
|
4234
|
+
replaceWatcher: true
|
|
4235
|
+
};
|
|
4236
|
+
}
|
|
4237
|
+
attachWatcher(watcherFactory, watcherFactoryForConfig) {
|
|
4238
|
+
if (this.hooks.watcherFactory !== void 0) return;
|
|
4239
|
+
this.hooks = {
|
|
4240
|
+
...this.hooks,
|
|
4241
|
+
watcherFactory,
|
|
4242
|
+
watcherFactoryForConfig: watcherFactoryForConfig ?? this.hooks.watcherFactoryForConfig
|
|
4243
|
+
};
|
|
4244
|
+
this.start();
|
|
4245
|
+
}
|
|
4246
|
+
async stop(stopAutoIndex = true) {
|
|
4247
|
+
if (this.stopPromise) return this.stopPromise;
|
|
4248
|
+
this.stopped = true;
|
|
4249
|
+
this.stopping = true;
|
|
4250
|
+
this.stopAutoIndexOnTeardown &&= stopAutoIndex;
|
|
4251
|
+
this.clearRetryTimer();
|
|
4252
|
+
const attempt = this.enqueue(async () => {
|
|
4253
|
+
try {
|
|
4254
|
+
const lease = this.lease;
|
|
4255
|
+
if (this.leaderWorkStopped) {
|
|
4256
|
+
if (lease) {
|
|
4257
|
+
this.releaseStoppedLease(lease);
|
|
4258
|
+
} else {
|
|
4259
|
+
this.finishStoppedLease();
|
|
4260
|
+
}
|
|
4261
|
+
return;
|
|
4262
|
+
}
|
|
4263
|
+
const hadLeaderWork = lease !== null || this.watcher !== null || this.autoIndexStarted;
|
|
4264
|
+
const stopped = await this.stopLeaderWork(hadLeaderWork && this.stopAutoIndexOnTeardown);
|
|
4265
|
+
if (!lease) {
|
|
4266
|
+
this.finishStoppedLease();
|
|
4267
|
+
return;
|
|
4268
|
+
}
|
|
4269
|
+
if (!stopped.completed) {
|
|
4270
|
+
this.releaseLeaseWhenAutoIndexStops(lease, stopped.completion);
|
|
4271
|
+
return;
|
|
4272
|
+
}
|
|
4273
|
+
this.leaderWorkStopped = true;
|
|
4274
|
+
this.releaseStoppedLease(lease);
|
|
4275
|
+
} catch (error) {
|
|
4276
|
+
this.scheduleTeardownRetry();
|
|
4277
|
+
throw error;
|
|
4278
|
+
}
|
|
4279
|
+
});
|
|
4280
|
+
const completion = attempt.finally(() => {
|
|
4281
|
+
if (this.stopPromise === completion) this.stopPromise = null;
|
|
4282
|
+
});
|
|
4283
|
+
this.stopPromise = completion;
|
|
4284
|
+
return completion;
|
|
4285
|
+
}
|
|
4286
|
+
canRun() {
|
|
4287
|
+
return this.config.indexing.autoIndex || this.hooks.watcherFactory != null;
|
|
4288
|
+
}
|
|
4289
|
+
enqueue(operation) {
|
|
4290
|
+
const next = this.transition.catch(() => void 0).then(operation);
|
|
4291
|
+
this.transition = next;
|
|
4292
|
+
return next;
|
|
4293
|
+
}
|
|
4294
|
+
startLeaderWork() {
|
|
4295
|
+
if (this.stopped || this.stopping || this.losingLeadership) return;
|
|
4296
|
+
this.startingLeaderWork = true;
|
|
4297
|
+
try {
|
|
4298
|
+
if (this.config.indexing.autoIndex && !this.autoIndexStarted) {
|
|
4299
|
+
this.autoIndexStarted = true;
|
|
4300
|
+
this.hooks.startAutoIndex("startup");
|
|
4301
|
+
}
|
|
4302
|
+
if (!this.watcher && this.hooks.watcherFactory) {
|
|
4303
|
+
try {
|
|
4304
|
+
const watcher = this.hooks.watcherFactory();
|
|
4305
|
+
this.watcher = watcher;
|
|
4306
|
+
this.leaderReady = watcher.whenReady?.().catch((error) => {
|
|
4307
|
+
console.error("[codebase-index] Failed while waiting for background file watcher startup:", error);
|
|
4308
|
+
}) ?? Promise.resolve();
|
|
4309
|
+
} catch (error) {
|
|
4310
|
+
console.error("[codebase-index] Failed to start background file watcher:", error);
|
|
4311
|
+
this.leaderReady = Promise.resolve();
|
|
4312
|
+
}
|
|
4313
|
+
}
|
|
4314
|
+
} finally {
|
|
4315
|
+
this.startingLeaderWork = false;
|
|
4316
|
+
}
|
|
4317
|
+
}
|
|
4318
|
+
async stopLeaderWork(stopAutoIndex) {
|
|
4319
|
+
const watcher = this.watcher;
|
|
4320
|
+
let watcherError;
|
|
4321
|
+
if (watcher) {
|
|
4322
|
+
try {
|
|
4323
|
+
await watcher.stop();
|
|
4324
|
+
if (this.watcher === watcher) this.watcher = null;
|
|
4325
|
+
} catch (error) {
|
|
4326
|
+
watcherError = error;
|
|
4327
|
+
}
|
|
4328
|
+
}
|
|
4329
|
+
let autoIndexError;
|
|
4330
|
+
let autoIndexStop = {
|
|
4331
|
+
completed: true,
|
|
4332
|
+
completion: Promise.resolve()
|
|
4333
|
+
};
|
|
4334
|
+
if (stopAutoIndex) {
|
|
4335
|
+
try {
|
|
4336
|
+
autoIndexStop = await this.hooks.stopAutoIndex();
|
|
4337
|
+
this.autoIndexStarted = false;
|
|
4338
|
+
} catch (error) {
|
|
4339
|
+
autoIndexError = error;
|
|
4340
|
+
}
|
|
4341
|
+
}
|
|
4342
|
+
if (watcherError !== void 0 || autoIndexError !== void 0) {
|
|
4343
|
+
throw new BackgroundWorkerStopError(watcherError, autoIndexError);
|
|
4344
|
+
}
|
|
4345
|
+
return autoIndexStop;
|
|
4346
|
+
}
|
|
4347
|
+
releaseLeaseWhenAutoIndexStops(lease, completion) {
|
|
4348
|
+
void completion.then(
|
|
4349
|
+
() => {
|
|
4350
|
+
void this.enqueue(async () => {
|
|
4351
|
+
if (this.lease !== lease || !this.stopping) return;
|
|
4352
|
+
this.leaderWorkStopped = true;
|
|
4353
|
+
this.releaseStoppedLease(lease);
|
|
4354
|
+
}).catch((error) => {
|
|
4355
|
+
console.error("[codebase-index] Failed to release background worker lease after automatic indexing stopped:", error);
|
|
4356
|
+
this.scheduleTeardownRetry();
|
|
4357
|
+
});
|
|
4358
|
+
},
|
|
4359
|
+
(error) => {
|
|
4360
|
+
console.error("[codebase-index] Failed while waiting for automatic indexing to stop:", error);
|
|
4361
|
+
this.scheduleTeardownRetry();
|
|
4362
|
+
}
|
|
4363
|
+
);
|
|
4364
|
+
}
|
|
4365
|
+
releaseStoppedLease(lease) {
|
|
4366
|
+
if (this.lease !== lease) {
|
|
4367
|
+
this.finishStoppedLease();
|
|
4368
|
+
return;
|
|
4369
|
+
}
|
|
4370
|
+
releaseLease(lease);
|
|
4371
|
+
this.lease = null;
|
|
4372
|
+
this.finishStoppedLease();
|
|
4373
|
+
}
|
|
4374
|
+
finishStoppedLease() {
|
|
4375
|
+
this.leaderWorkStopped = false;
|
|
4376
|
+
this.stopAutoIndexOnTeardown = true;
|
|
4377
|
+
this.stopping = false;
|
|
4378
|
+
this.clearTimers();
|
|
4379
|
+
this.restartAfterTeardown();
|
|
4380
|
+
if (!this.stopped || this.stopping) return;
|
|
4381
|
+
const projectKey = projectLookupKey(this.projectRoot, this.host);
|
|
4382
|
+
const key = controllerKey(this.identity, this.host);
|
|
4383
|
+
if (workers.get(key) === this) workers.delete(key);
|
|
4384
|
+
if (workerKeysByProject.get(projectKey) === key) workerKeysByProject.delete(projectKey);
|
|
4385
|
+
}
|
|
4386
|
+
startHeartbeat() {
|
|
4387
|
+
if (this.heartbeatTimer) return;
|
|
4388
|
+
const heartbeat = () => {
|
|
4389
|
+
void this.heartbeat();
|
|
4390
|
+
};
|
|
4391
|
+
this.heartbeatTimer = setInterval(heartbeat, HEARTBEAT_INTERVAL_MS);
|
|
4392
|
+
this.heartbeatTimer.unref?.();
|
|
4393
|
+
}
|
|
4394
|
+
async heartbeat() {
|
|
4395
|
+
const lease = this.lease;
|
|
4396
|
+
if (!lease || this.losingLeadership || this.stopped && !this.stopping) return;
|
|
4397
|
+
if (hasActiveReclaimMarker(lease.leasePath, lease.owner)) {
|
|
4398
|
+
await this.loseLeadership();
|
|
4399
|
+
return;
|
|
4400
|
+
}
|
|
4401
|
+
const currentOwner = readOwner(lease.leasePath);
|
|
4402
|
+
if (!currentOwner || !sameOwner2(currentOwner, lease.owner)) {
|
|
4403
|
+
await this.loseLeadership();
|
|
4404
|
+
return;
|
|
4405
|
+
}
|
|
4406
|
+
try {
|
|
4407
|
+
const nextOwner = { ...lease.owner, heartbeatAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
4408
|
+
if (!writeHeartbeat(lease.leasePath, nextOwner)) {
|
|
4409
|
+
await this.loseLeadership();
|
|
4410
|
+
return;
|
|
4411
|
+
}
|
|
4412
|
+
lease.owner = nextOwner;
|
|
4413
|
+
const refreshRequest = !this.stopping ? consumeRefreshRequest(lease.leasePath) : null;
|
|
4414
|
+
if (refreshRequest) {
|
|
4415
|
+
this.hooks.startAutoIndex("retrieval", refreshRequest.allowDisabledAutoIndex);
|
|
4416
|
+
}
|
|
4417
|
+
} catch (error) {
|
|
4418
|
+
const ownerAfterError = readOwner(lease.leasePath);
|
|
4419
|
+
if (hasActiveReclaimMarker(lease.leasePath, lease.owner) || !ownerAfterError || !sameOwner2(ownerAfterError, lease.owner)) {
|
|
4420
|
+
await this.loseLeadership();
|
|
4421
|
+
return;
|
|
4422
|
+
}
|
|
4423
|
+
console.error("[codebase-index] Failed to renew background worker lease:", error);
|
|
4424
|
+
}
|
|
4425
|
+
}
|
|
4426
|
+
async loseLeadership() {
|
|
4427
|
+
if (this.losingLeadership) return;
|
|
4428
|
+
this.losingLeadership = true;
|
|
4429
|
+
this.clearHeartbeat();
|
|
4430
|
+
await this.enqueue(async () => this.stopAfterLeadershipLoss());
|
|
4431
|
+
}
|
|
4432
|
+
async stopAfterLeadershipLoss() {
|
|
4433
|
+
const lease = this.lease;
|
|
4434
|
+
if (!lease) {
|
|
4435
|
+
this.losingLeadership = false;
|
|
4436
|
+
return;
|
|
4437
|
+
}
|
|
4438
|
+
try {
|
|
4439
|
+
const stopped = await this.stopLeaderWork(true);
|
|
4440
|
+
this.lease = null;
|
|
4441
|
+
this.losingLeadership = false;
|
|
4442
|
+
if (stopped.completed) {
|
|
4443
|
+
this.scheduleRetry();
|
|
4444
|
+
} else {
|
|
4445
|
+
void stopped.completion.then(() => this.scheduleRetry());
|
|
4446
|
+
}
|
|
4447
|
+
} catch (error) {
|
|
4448
|
+
console.error("[codebase-index] Failed to stop background work after losing its lease:", error);
|
|
4449
|
+
this.scheduleLostLeadershipTeardownRetry();
|
|
4450
|
+
}
|
|
4451
|
+
}
|
|
4452
|
+
scheduleRetry() {
|
|
4453
|
+
if (this.stopped || !this.canRun() || this.retryTimer) return;
|
|
4454
|
+
this.retryTimer = setTimeout(() => {
|
|
4455
|
+
this.retryTimer = null;
|
|
4456
|
+
this.start();
|
|
4457
|
+
}, RETRY_DELAY_MS);
|
|
4458
|
+
this.retryTimer.unref?.();
|
|
4459
|
+
}
|
|
4460
|
+
scheduleTeardownRetry() {
|
|
4461
|
+
if (!this.stopping || this.teardownRetryTimer) return;
|
|
4462
|
+
this.teardownRetryTimer = setTimeout(() => {
|
|
4463
|
+
this.teardownRetryTimer = null;
|
|
4464
|
+
void this.stop(this.stopAutoIndexOnTeardown).catch((error) => {
|
|
4465
|
+
console.error("[codebase-index] Failed to retry background worker teardown:", error);
|
|
4466
|
+
});
|
|
4467
|
+
}, RETRY_DELAY_MS);
|
|
4468
|
+
this.teardownRetryTimer.unref?.();
|
|
4469
|
+
}
|
|
4470
|
+
restartAfterTeardown() {
|
|
4471
|
+
if (!this.restartAfterStop || !this.canRun() || this.losingLeadership) return;
|
|
4472
|
+
this.restartAfterStop = false;
|
|
4473
|
+
this.stopped = false;
|
|
4474
|
+
this.start();
|
|
4475
|
+
}
|
|
4476
|
+
scheduleLostLeadershipTeardownRetry() {
|
|
4477
|
+
if (this.stopped || !this.losingLeadership || this.retryTimer) return;
|
|
4478
|
+
this.retryTimer = setTimeout(() => {
|
|
4479
|
+
this.retryTimer = null;
|
|
4480
|
+
void this.enqueue(async () => this.stopAfterLeadershipLoss());
|
|
4481
|
+
}, RETRY_DELAY_MS);
|
|
4482
|
+
this.retryTimer.unref?.();
|
|
4483
|
+
}
|
|
4484
|
+
clearHeartbeat() {
|
|
4485
|
+
if (!this.heartbeatTimer) return;
|
|
4486
|
+
clearInterval(this.heartbeatTimer);
|
|
4487
|
+
this.heartbeatTimer = null;
|
|
4488
|
+
}
|
|
4489
|
+
clearTimers() {
|
|
4490
|
+
this.clearHeartbeat();
|
|
4491
|
+
this.clearRetryTimer();
|
|
4492
|
+
if (this.teardownRetryTimer) {
|
|
4493
|
+
clearTimeout(this.teardownRetryTimer);
|
|
4494
|
+
this.teardownRetryTimer = null;
|
|
4495
|
+
}
|
|
4496
|
+
}
|
|
4497
|
+
clearRetryTimer() {
|
|
4498
|
+
if (!this.retryTimer) return;
|
|
4499
|
+
clearTimeout(this.retryTimer);
|
|
4500
|
+
this.retryTimer = null;
|
|
4501
|
+
}
|
|
4502
|
+
reportAcquireError(error) {
|
|
4503
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
4504
|
+
if (this.reportedError === message) return;
|
|
4505
|
+
this.reportedError = message;
|
|
4506
|
+
console.error("[codebase-index] Failed to acquire background worker lease:", error);
|
|
4507
|
+
}
|
|
4508
|
+
};
|
|
4509
|
+
function configureBackgroundWorker(projectRoot, host, config, hooks, options = {}) {
|
|
4510
|
+
const projectKey = projectLookupKey(projectRoot, host);
|
|
4511
|
+
const identity = resolveIdentity(projectRoot, config, host);
|
|
4512
|
+
const key = controllerKey(identity, host);
|
|
4513
|
+
const previousKey = workerKeysByProject.get(projectKey);
|
|
4514
|
+
if (previousKey && previousKey !== key) {
|
|
4515
|
+
const previous = workers.get(previousKey);
|
|
4516
|
+
const previousBarrier = workerReplacementBarriers.get(projectKey) ?? Promise.resolve();
|
|
4517
|
+
const stopPrevious = previous?.stop(options.stopPreviousAutoIndex ?? true) ?? Promise.resolve();
|
|
4518
|
+
const activation = Promise.all([previousBarrier, stopPrevious]).then(() => void 0);
|
|
4519
|
+
workerReplacementBarriers.set(projectKey, activation);
|
|
4520
|
+
workers.delete(previousKey);
|
|
4521
|
+
const worker2 = new BackgroundWorkerController(projectRoot, host, config, hooks, identity);
|
|
4522
|
+
worker2.startAfter(activation);
|
|
4523
|
+
workers.set(key, worker2);
|
|
4524
|
+
workerKeysByProject.set(projectKey, key);
|
|
4525
|
+
return;
|
|
4526
|
+
}
|
|
4527
|
+
let worker = workers.get(key);
|
|
4528
|
+
if (!worker) {
|
|
4529
|
+
worker = new BackgroundWorkerController(projectRoot, host, config, hooks, identity);
|
|
4530
|
+
workers.set(key, worker);
|
|
4531
|
+
} else {
|
|
4532
|
+
worker.update(config, hooks, options);
|
|
4533
|
+
}
|
|
4534
|
+
workerKeysByProject.set(projectKey, key);
|
|
4535
|
+
worker.start();
|
|
4536
|
+
}
|
|
4537
|
+
function updateBackgroundWorkerConfig(projectRoot, host, config) {
|
|
4538
|
+
const projectKey = projectLookupKey(projectRoot, host);
|
|
4539
|
+
const key = workerKeysByProject.get(projectKey);
|
|
4540
|
+
const worker = key ? workers.get(key) : void 0;
|
|
4541
|
+
if (!worker) return;
|
|
4542
|
+
configureBackgroundWorker(projectRoot, host, config, worker.getHooksForConfig(config), {
|
|
4543
|
+
stopPreviousAutoIndex: false,
|
|
4544
|
+
restartAutoIndex: true
|
|
4545
|
+
});
|
|
4546
|
+
}
|
|
4547
|
+
function waitForBackgroundWorkerStart(projectRoot, host) {
|
|
4548
|
+
const key = workerKeysByProject.get(projectLookupKey(projectRoot, host));
|
|
4549
|
+
return workers.get(key ?? "")?.waitForStart() ?? Promise.resolve();
|
|
4550
|
+
}
|
|
4551
|
+
function requestBackgroundWorkerRefresh(projectRoot, host, allowDisabledAutoIndex = false) {
|
|
4552
|
+
const key = workerKeysByProject.get(projectLookupKey(projectRoot, host));
|
|
4553
|
+
workers.get(key ?? "")?.requestRefresh(allowDisabledAutoIndex);
|
|
4554
|
+
}
|
|
4555
|
+
function isBackgroundWorkerManaged(projectRoot, host) {
|
|
4556
|
+
const key = workerKeysByProject.get(projectLookupKey(projectRoot, host));
|
|
4557
|
+
return key !== void 0 && workers.has(key);
|
|
4558
|
+
}
|
|
4559
|
+
function isBackgroundWorkerLeader(projectRoot, host) {
|
|
4560
|
+
const key = workerKeysByProject.get(projectLookupKey(projectRoot, host));
|
|
4561
|
+
return key !== void 0 && workers.get(key)?.isLeader() === true;
|
|
4562
|
+
}
|
|
4563
|
+
async function stopBackgroundWorker(projectRoot, host) {
|
|
4564
|
+
const projectKey = projectLookupKey(projectRoot, host);
|
|
4565
|
+
const key = workerKeysByProject.get(projectKey);
|
|
4566
|
+
const worker = key ? workers.get(key) : void 0;
|
|
4567
|
+
if (!worker) return;
|
|
4568
|
+
await worker.stop();
|
|
4569
|
+
}
|
|
4570
|
+
|
|
3697
4571
|
// src/utils/files.ts
|
|
3698
4572
|
var import_ignore = __toESM(require_ignore(), 1);
|
|
3699
4573
|
var import_fs6 = require("fs");
|
|
3700
|
-
var
|
|
4574
|
+
var path11 = __toESM(require("path"), 1);
|
|
3701
4575
|
var PROJECT_MARKERS = [
|
|
3702
4576
|
".git",
|
|
3703
4577
|
"package.json",
|
|
@@ -3715,7 +4589,7 @@ var PROJECT_MARKERS = [
|
|
|
3715
4589
|
];
|
|
3716
4590
|
function hasProjectMarker(projectRoot) {
|
|
3717
4591
|
for (const marker of PROJECT_MARKERS) {
|
|
3718
|
-
if ((0, import_fs6.existsSync)(
|
|
4592
|
+
if ((0, import_fs6.existsSync)(path11.join(projectRoot, marker))) {
|
|
3719
4593
|
return true;
|
|
3720
4594
|
}
|
|
3721
4595
|
}
|
|
@@ -3742,33 +4616,53 @@ function createIgnoreFilter(projectRoot) {
|
|
|
3742
4616
|
"**/*build*/**"
|
|
3743
4617
|
];
|
|
3744
4618
|
ig.add(defaultIgnores);
|
|
3745
|
-
const gitignorePath =
|
|
4619
|
+
const gitignorePath = path11.join(projectRoot, ".gitignore");
|
|
3746
4620
|
if ((0, import_fs6.existsSync)(gitignorePath)) {
|
|
3747
4621
|
const gitignoreContent = (0, import_fs6.readFileSync)(gitignorePath, "utf-8");
|
|
3748
4622
|
ig.add(gitignoreContent);
|
|
3749
4623
|
}
|
|
3750
4624
|
return ig;
|
|
3751
4625
|
}
|
|
3752
|
-
function
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
|
|
4626
|
+
function toPosixRelativePath(relativePath) {
|
|
4627
|
+
return relativePath.split(path11.sep).join("/");
|
|
4628
|
+
}
|
|
4629
|
+
function matchesAnyGlob(filePath, patterns) {
|
|
4630
|
+
const normalized = toPosixRelativePath(filePath);
|
|
4631
|
+
return patterns.some((pattern) => matchGlob(normalized, pattern));
|
|
4632
|
+
}
|
|
4633
|
+
function isExcludedByPatterns(relativePath, excludePatterns) {
|
|
4634
|
+
return matchesAnyGlob(relativePath, excludePatterns);
|
|
4635
|
+
}
|
|
4636
|
+
function isExcludedDirectory(relativePath, excludePatterns) {
|
|
4637
|
+
const normalized = toPosixRelativePath(relativePath);
|
|
4638
|
+
if (matchesAnyGlob(normalized, excludePatterns)) {
|
|
4639
|
+
return true;
|
|
3759
4640
|
}
|
|
3760
4641
|
for (const pattern of excludePatterns) {
|
|
3761
|
-
|
|
3762
|
-
|
|
4642
|
+
const posixPattern = toPosixRelativePath(pattern).replace(/\/+$/, "");
|
|
4643
|
+
if (!posixPattern.endsWith("/**")) {
|
|
4644
|
+
continue;
|
|
3763
4645
|
}
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
if (matchGlob(relativePath, pattern)) {
|
|
4646
|
+
const directoryPattern = posixPattern.slice(0, -3);
|
|
4647
|
+
if (directoryPattern && matchesAnyGlob(normalized, [directoryPattern])) {
|
|
3767
4648
|
return true;
|
|
3768
4649
|
}
|
|
3769
4650
|
}
|
|
3770
4651
|
return false;
|
|
3771
4652
|
}
|
|
4653
|
+
function shouldIncludeFile(filePath, projectRoot, includePatterns, excludePatterns, ignoreFilter) {
|
|
4654
|
+
const relativePath = toPosixRelativePath(path11.relative(projectRoot, filePath));
|
|
4655
|
+
if (hasFilteredPathSegment(relativePath, "/")) {
|
|
4656
|
+
return false;
|
|
4657
|
+
}
|
|
4658
|
+
if (ignoreFilter.ignores(relativePath)) {
|
|
4659
|
+
return false;
|
|
4660
|
+
}
|
|
4661
|
+
if (isExcludedByPatterns(relativePath, excludePatterns)) {
|
|
4662
|
+
return false;
|
|
4663
|
+
}
|
|
4664
|
+
return matchesAnyGlob(relativePath, includePatterns);
|
|
4665
|
+
}
|
|
3772
4666
|
function matchGlob(filePath, pattern) {
|
|
3773
4667
|
if (pattern.startsWith("**/")) {
|
|
3774
4668
|
const withoutPrefix = pattern.slice(3);
|
|
@@ -3789,8 +4683,8 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
|
|
|
3789
4683
|
const filesInDir = [];
|
|
3790
4684
|
const subdirs = [];
|
|
3791
4685
|
for (const entry of entries) {
|
|
3792
|
-
const fullPath =
|
|
3793
|
-
const relativePath =
|
|
4686
|
+
const fullPath = path11.join(dir, entry.name);
|
|
4687
|
+
const relativePath = toPosixRelativePath(path11.relative(projectRoot, fullPath));
|
|
3794
4688
|
if (isHiddenPathSegment(entry.name)) {
|
|
3795
4689
|
if (entry.isDirectory()) {
|
|
3796
4690
|
skipped.push({ path: relativePath, reason: "excluded" });
|
|
@@ -3808,6 +4702,10 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
|
|
|
3808
4702
|
continue;
|
|
3809
4703
|
}
|
|
3810
4704
|
if (entry.isDirectory()) {
|
|
4705
|
+
if (isExcludedDirectory(relativePath, excludePatterns)) {
|
|
4706
|
+
skipped.push({ path: relativePath, reason: "excluded" });
|
|
4707
|
+
continue;
|
|
4708
|
+
}
|
|
3811
4709
|
subdirs.push({ fullPath, relativePath });
|
|
3812
4710
|
} else if (entry.isFile()) {
|
|
3813
4711
|
const stat5 = await import_fs6.promises.stat(fullPath);
|
|
@@ -3815,20 +4713,11 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
|
|
|
3815
4713
|
skipped.push({ path: relativePath, reason: "too_large" });
|
|
3816
4714
|
continue;
|
|
3817
4715
|
}
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
|
|
3821
|
-
continue;
|
|
3822
|
-
}
|
|
3823
|
-
}
|
|
3824
|
-
let matched = false;
|
|
3825
|
-
for (const pattern of includePatterns) {
|
|
3826
|
-
if (matchGlob(relativePath, pattern)) {
|
|
3827
|
-
matched = true;
|
|
3828
|
-
break;
|
|
3829
|
-
}
|
|
4716
|
+
if (isExcludedByPatterns(relativePath, excludePatterns)) {
|
|
4717
|
+
skipped.push({ path: relativePath, reason: "excluded" });
|
|
4718
|
+
continue;
|
|
3830
4719
|
}
|
|
3831
|
-
if (
|
|
4720
|
+
if (matchesAnyGlob(relativePath, includePatterns)) {
|
|
3832
4721
|
filesInDir.push({ path: fullPath, size: stat5.size });
|
|
3833
4722
|
}
|
|
3834
4723
|
}
|
|
@@ -3839,7 +4728,7 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
|
|
|
3839
4728
|
yield f;
|
|
3840
4729
|
}
|
|
3841
4730
|
for (let i = options.maxFilesPerDirectory; i < filesInDir.length; i++) {
|
|
3842
|
-
skipped.push({ path:
|
|
4731
|
+
skipped.push({ path: toPosixRelativePath(path11.relative(projectRoot, filesInDir[i].path)), reason: "excluded" });
|
|
3843
4732
|
}
|
|
3844
4733
|
const canRecurse = options.maxDepth === -1 || currentDepth < options.maxDepth;
|
|
3845
4734
|
if (canRecurse) {
|
|
@@ -3879,8 +4768,8 @@ async function collectFiles(projectRoot, includePatterns, excludePatterns, maxFi
|
|
|
3879
4768
|
if (additionalRoots && additionalRoots.length > 0) {
|
|
3880
4769
|
const normalizedRoots = /* @__PURE__ */ new Set();
|
|
3881
4770
|
for (const kbRoot of additionalRoots) {
|
|
3882
|
-
const resolved =
|
|
3883
|
-
|
|
4771
|
+
const resolved = path11.normalize(
|
|
4772
|
+
path11.isAbsolute(kbRoot) ? kbRoot : path11.resolve(projectRoot, kbRoot)
|
|
3884
4773
|
);
|
|
3885
4774
|
normalizedRoots.add(resolved);
|
|
3886
4775
|
}
|
|
@@ -3921,7 +4810,7 @@ function getErrorMessage(error) {
|
|
|
3921
4810
|
return error instanceof Error ? error.message : String(error);
|
|
3922
4811
|
}
|
|
3923
4812
|
function runCommand(file, args, options) {
|
|
3924
|
-
return new Promise((
|
|
4813
|
+
return new Promise((resolve18, reject) => {
|
|
3925
4814
|
childProcess.execFile(
|
|
3926
4815
|
file,
|
|
3927
4816
|
args,
|
|
@@ -3931,7 +4820,7 @@ function runCommand(file, args, options) {
|
|
|
3931
4820
|
reject(error);
|
|
3932
4821
|
return;
|
|
3933
4822
|
}
|
|
3934
|
-
|
|
4823
|
+
resolve18(stdout);
|
|
3935
4824
|
}
|
|
3936
4825
|
);
|
|
3937
4826
|
});
|
|
@@ -4023,8 +4912,8 @@ var AutoIndexCancelledError = class extends Error {
|
|
|
4023
4912
|
function now() {
|
|
4024
4913
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
4025
4914
|
}
|
|
4026
|
-
function
|
|
4027
|
-
const resolved =
|
|
4915
|
+
function canonicalizePath2(targetPath) {
|
|
4916
|
+
const resolved = path12.resolve(targetPath);
|
|
4028
4917
|
if ((0, import_fs7.existsSync)(resolved)) {
|
|
4029
4918
|
try {
|
|
4030
4919
|
return import_fs7.realpathSync.native(resolved);
|
|
@@ -4032,20 +4921,20 @@ function canonicalizePath(targetPath) {
|
|
|
4032
4921
|
return resolved;
|
|
4033
4922
|
}
|
|
4034
4923
|
}
|
|
4035
|
-
const parent =
|
|
4924
|
+
const parent = path12.dirname(resolved);
|
|
4036
4925
|
if (parent === resolved) return resolved;
|
|
4037
|
-
return
|
|
4926
|
+
return path12.join(canonicalizePath2(parent), path12.basename(resolved));
|
|
4038
4927
|
}
|
|
4039
4928
|
function isHomeDirectory(projectRoot) {
|
|
4040
|
-
return
|
|
4929
|
+
return canonicalizePath2(projectRoot) === canonicalizePath2(os4.homedir());
|
|
4041
4930
|
}
|
|
4042
|
-
function
|
|
4043
|
-
return `${host}::${
|
|
4931
|
+
function projectLookupKey2(projectRoot, host) {
|
|
4932
|
+
return `${host}::${canonicalizePath2(projectRoot)}`;
|
|
4044
4933
|
}
|
|
4045
4934
|
function coordinatorKey(projectRoot, config, host) {
|
|
4046
|
-
const canonicalProjectRoot =
|
|
4935
|
+
const canonicalProjectRoot = canonicalizePath2(projectRoot);
|
|
4047
4936
|
const indexPath = resolveProjectIndexPath(projectRoot, config.scope, host);
|
|
4048
|
-
return `${
|
|
4937
|
+
return `${canonicalizePath2(indexPath)}::${canonicalProjectRoot}`;
|
|
4049
4938
|
}
|
|
4050
4939
|
function getProjectSafety(projectRoot, config) {
|
|
4051
4940
|
if (isHomeDirectory(projectRoot)) {
|
|
@@ -4076,10 +4965,10 @@ function safeFailureMessage(error) {
|
|
|
4076
4965
|
}
|
|
4077
4966
|
function cancellableDelay(delayMs, signal) {
|
|
4078
4967
|
if (signal.aborted) return Promise.reject(new AutoIndexCancelledError());
|
|
4079
|
-
return new Promise((
|
|
4968
|
+
return new Promise((resolve18, reject) => {
|
|
4080
4969
|
const timer = setTimeout(() => {
|
|
4081
4970
|
signal.removeEventListener("abort", onAbort);
|
|
4082
|
-
|
|
4971
|
+
resolve18();
|
|
4083
4972
|
}, delayMs);
|
|
4084
4973
|
timer.unref?.();
|
|
4085
4974
|
const onAbort = () => {
|
|
@@ -4091,18 +4980,44 @@ function cancellableDelay(delayMs, signal) {
|
|
|
4091
4980
|
}
|
|
4092
4981
|
function withTimeout(promise, timeoutMs) {
|
|
4093
4982
|
if (timeoutMs <= 0) return Promise.resolve(void 0);
|
|
4094
|
-
return new Promise((
|
|
4095
|
-
const timer = setTimeout(() =>
|
|
4983
|
+
return new Promise((resolve18) => {
|
|
4984
|
+
const timer = setTimeout(() => resolve18(void 0), timeoutMs);
|
|
4096
4985
|
timer.unref?.();
|
|
4097
4986
|
void promise.then((value) => {
|
|
4098
4987
|
clearTimeout(timer);
|
|
4099
|
-
|
|
4988
|
+
resolve18(value);
|
|
4100
4989
|
}, () => {
|
|
4101
4990
|
clearTimeout(timer);
|
|
4102
|
-
|
|
4991
|
+
resolve18(void 0);
|
|
4103
4992
|
});
|
|
4104
4993
|
});
|
|
4105
4994
|
}
|
|
4995
|
+
function settlesWithin(promise, timeoutMs) {
|
|
4996
|
+
if (timeoutMs <= 0) return Promise.resolve(false);
|
|
4997
|
+
return new Promise((resolve18) => {
|
|
4998
|
+
let settled = false;
|
|
4999
|
+
const timer = setTimeout(() => {
|
|
5000
|
+
if (settled) return;
|
|
5001
|
+
settled = true;
|
|
5002
|
+
resolve18(false);
|
|
5003
|
+
}, timeoutMs);
|
|
5004
|
+
timer.unref?.();
|
|
5005
|
+
void promise.then(
|
|
5006
|
+
() => {
|
|
5007
|
+
if (settled) return;
|
|
5008
|
+
settled = true;
|
|
5009
|
+
clearTimeout(timer);
|
|
5010
|
+
resolve18(true);
|
|
5011
|
+
},
|
|
5012
|
+
() => {
|
|
5013
|
+
if (settled) return;
|
|
5014
|
+
settled = true;
|
|
5015
|
+
clearTimeout(timer);
|
|
5016
|
+
resolve18(true);
|
|
5017
|
+
}
|
|
5018
|
+
);
|
|
5019
|
+
});
|
|
5020
|
+
}
|
|
4106
5021
|
function requestPriority(request) {
|
|
4107
5022
|
if (request.force) return 4;
|
|
4108
5023
|
if (request.source === "manual") return 3;
|
|
@@ -4113,6 +5028,7 @@ function mergeRequests(current, next) {
|
|
|
4113
5028
|
if (!current) return next;
|
|
4114
5029
|
const preferred = requestPriority(next) > requestPriority(current) ? next : current;
|
|
4115
5030
|
return {
|
|
5031
|
+
allowDisabledAutoIndex: current.allowDisabledAutoIndex || next.allowDisabledAutoIndex,
|
|
4116
5032
|
checkFreshness: current.checkFreshness && next.checkFreshness,
|
|
4117
5033
|
force: current.force || next.force,
|
|
4118
5034
|
onProgress: next.onProgress ?? current.onProgress,
|
|
@@ -4174,11 +5090,11 @@ var AutoIndexCoordinator = class {
|
|
|
4174
5090
|
progress: this.status.progress ? { ...this.status.progress } : void 0
|
|
4175
5091
|
};
|
|
4176
5092
|
}
|
|
4177
|
-
start(source) {
|
|
5093
|
+
start(source, allowDisabledAutoIndex = false) {
|
|
4178
5094
|
this.refreshSafety();
|
|
4179
|
-
if (!this.registration.config.indexing.autoIndex || !this.registration.safeToRun) return null;
|
|
5095
|
+
if (!this.registration.config.indexing.autoIndex && !allowDisabledAutoIndex || !this.registration.safeToRun) return null;
|
|
4180
5096
|
if (this.status.state === "failed") return this.inFlight;
|
|
4181
|
-
return this.request({ checkFreshness: true, force: false, source });
|
|
5097
|
+
return this.request({ allowDisabledAutoIndex, checkFreshness: true, force: false, source });
|
|
4182
5098
|
}
|
|
4183
5099
|
request(request) {
|
|
4184
5100
|
if (this.stopped) {
|
|
@@ -4253,13 +5169,15 @@ var AutoIndexCoordinator = class {
|
|
|
4253
5169
|
retryAttempt: void 0
|
|
4254
5170
|
});
|
|
4255
5171
|
const inFlight = this.inFlight;
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
} else {
|
|
4260
|
-
await withTimeout(inFlight, SHUTDOWN_WAIT_MS);
|
|
4261
|
-
}
|
|
5172
|
+
const completion = inFlight ? inFlight.then(() => void 0, () => void 0) : Promise.resolve();
|
|
5173
|
+
if (!inFlight) {
|
|
5174
|
+
return { completed: true, completion };
|
|
4262
5175
|
}
|
|
5176
|
+
if (waitForCompletion) {
|
|
5177
|
+
await completion;
|
|
5178
|
+
return { completed: true, completion };
|
|
5179
|
+
}
|
|
5180
|
+
return { completed: await settlesWithin(completion, SHUTDOWN_WAIT_MS), completion };
|
|
4263
5181
|
}
|
|
4264
5182
|
startRequest(request) {
|
|
4265
5183
|
if (this.stopped || !this.canRun(request)) {
|
|
@@ -4448,7 +5366,7 @@ var AutoIndexCoordinator = class {
|
|
|
4448
5366
|
if (request.source === "manual" || request.source === "watcher") {
|
|
4449
5367
|
return true;
|
|
4450
5368
|
}
|
|
4451
|
-
return this.registration.safeToRun && this.registration.config.indexing.autoIndex;
|
|
5369
|
+
return this.registration.safeToRun && (this.registration.config.indexing.autoIndex || request.allowDisabledAutoIndex === true);
|
|
4452
5370
|
}
|
|
4453
5371
|
shouldDeferForBattery(request) {
|
|
4454
5372
|
return this.registration.backgroundIndexingPolicy !== null && (request.source === "startup" || request.source === "watcher");
|
|
@@ -4481,17 +5399,17 @@ var AutoIndexCoordinator = class {
|
|
|
4481
5399
|
}
|
|
4482
5400
|
}
|
|
4483
5401
|
waitForBatteryRetry(delayMs) {
|
|
4484
|
-
return new Promise((
|
|
5402
|
+
return new Promise((resolve18) => {
|
|
4485
5403
|
const timer = setTimeout(() => {
|
|
4486
5404
|
if (this.batteryRetryTimer === timer) {
|
|
4487
5405
|
this.batteryRetryTimer = null;
|
|
4488
5406
|
this.resolveBatteryRetry = null;
|
|
4489
5407
|
}
|
|
4490
|
-
|
|
5408
|
+
resolve18();
|
|
4491
5409
|
}, delayMs);
|
|
4492
5410
|
timer.unref?.();
|
|
4493
5411
|
this.batteryRetryTimer = timer;
|
|
4494
|
-
this.resolveBatteryRetry =
|
|
5412
|
+
this.resolveBatteryRetry = resolve18;
|
|
4495
5413
|
});
|
|
4496
5414
|
}
|
|
4497
5415
|
cancelBatteryRetry() {
|
|
@@ -4499,9 +5417,9 @@ var AutoIndexCoordinator = class {
|
|
|
4499
5417
|
clearTimeout(this.batteryRetryTimer);
|
|
4500
5418
|
this.batteryRetryTimer = null;
|
|
4501
5419
|
}
|
|
4502
|
-
const
|
|
5420
|
+
const resolve18 = this.resolveBatteryRetry;
|
|
4503
5421
|
this.resolveBatteryRetry = null;
|
|
4504
|
-
|
|
5422
|
+
resolve18?.();
|
|
4505
5423
|
}
|
|
4506
5424
|
finishBatteryCheck(batteryCheck) {
|
|
4507
5425
|
if (this.batteryCheck !== batteryCheck) return;
|
|
@@ -4514,12 +5432,25 @@ var AutoIndexCoordinator = class {
|
|
|
4514
5432
|
}
|
|
4515
5433
|
};
|
|
4516
5434
|
function getCoordinator(projectRoot, host) {
|
|
4517
|
-
const key = coordinatorKeysByProject.get(
|
|
5435
|
+
const key = coordinatorKeysByProject.get(projectLookupKey2(projectRoot, host));
|
|
4518
5436
|
return key ? coordinators.get(key) ?? null : null;
|
|
4519
5437
|
}
|
|
4520
|
-
function
|
|
4521
|
-
|
|
5438
|
+
function synchronizeBackgroundWorker(projectRoot, host, config, safeToRun) {
|
|
5439
|
+
if (safeToRun) {
|
|
5440
|
+
updateBackgroundWorkerConfig(projectRoot, host, config);
|
|
5441
|
+
return;
|
|
5442
|
+
}
|
|
5443
|
+
void stopBackgroundWorker(projectRoot, host).catch((error) => {
|
|
5444
|
+
console.error("[codebase-index] Failed to stop background worker after project safety changed:", error);
|
|
5445
|
+
});
|
|
5446
|
+
}
|
|
5447
|
+
function configureAutoIndex(projectRoot, host, config, getIndexer, options = {}) {
|
|
5448
|
+
const projectKey = projectLookupKey2(projectRoot, host);
|
|
4522
5449
|
const safety = getProjectSafety(projectRoot, config);
|
|
5450
|
+
const synchronizeWorker = options.synchronizeBackgroundWorker ?? true;
|
|
5451
|
+
if (options.preserveManagedWorker === true && isBackgroundWorkerManaged(projectRoot, host)) {
|
|
5452
|
+
return;
|
|
5453
|
+
}
|
|
4523
5454
|
const registration = {
|
|
4524
5455
|
backgroundIndexingPolicy: createBackgroundIndexingPolicy(
|
|
4525
5456
|
config.indexing.pauseBackgroundIndexingOnBattery
|
|
@@ -4537,6 +5468,9 @@ function configureAutoIndex(projectRoot, host, config, getIndexer) {
|
|
|
4537
5468
|
const stopPrevious = previousCoordinator?.stop(true) ?? Promise.resolve();
|
|
4538
5469
|
const activation = Promise.all([previousBarrier, stopPrevious]).then(() => void 0);
|
|
4539
5470
|
coordinatorReplacementBarriers.set(projectKey, activation);
|
|
5471
|
+
if (synchronizeWorker) {
|
|
5472
|
+
synchronizeBackgroundWorker(projectRoot, host, config, safety.safeToRun);
|
|
5473
|
+
}
|
|
4540
5474
|
coordinators.delete(previousKey);
|
|
4541
5475
|
const coordinator2 = new AutoIndexCoordinator(registration);
|
|
4542
5476
|
coordinator2.activateAfter(activation);
|
|
@@ -4552,11 +5486,17 @@ function configureAutoIndex(projectRoot, host, config, getIndexer) {
|
|
|
4552
5486
|
coordinator.update(registration);
|
|
4553
5487
|
}
|
|
4554
5488
|
coordinatorKeysByProject.set(projectKey, key);
|
|
5489
|
+
if (synchronizeWorker) {
|
|
5490
|
+
synchronizeBackgroundWorker(projectRoot, host, config, safety.safeToRun);
|
|
5491
|
+
}
|
|
4555
5492
|
}
|
|
4556
|
-
function
|
|
4557
|
-
return getCoordinator(projectRoot, host)?.start(source) ?? null;
|
|
5493
|
+
function startAutoIndexForBackgroundWorker(projectRoot, host, source = "startup", allowDisabledAutoIndex = false) {
|
|
5494
|
+
return getCoordinator(projectRoot, host)?.start(source, allowDisabledAutoIndex) ?? null;
|
|
4558
5495
|
}
|
|
4559
5496
|
function requestBackgroundIndex(projectRoot, host) {
|
|
5497
|
+
if (isBackgroundWorkerManaged(projectRoot, host) && !isBackgroundWorkerLeader(projectRoot, host)) {
|
|
5498
|
+
return null;
|
|
5499
|
+
}
|
|
4560
5500
|
return getCoordinator(projectRoot, host)?.request({
|
|
4561
5501
|
checkFreshness: false,
|
|
4562
5502
|
force: false,
|
|
@@ -4596,15 +5536,23 @@ async function waitForAutoIndexForRetrieval(projectRoot, host) {
|
|
|
4596
5536
|
};
|
|
4597
5537
|
}
|
|
4598
5538
|
try {
|
|
4599
|
-
|
|
5539
|
+
const readiness = await getSearchReadiness(coordinator);
|
|
5540
|
+
if (readiness.searchable) {
|
|
5541
|
+
return { ready: true };
|
|
5542
|
+
}
|
|
5543
|
+
if (readiness.blocked) return unavailableSnapshotResult(readiness.reason);
|
|
4600
5544
|
} catch {
|
|
4601
5545
|
}
|
|
4602
|
-
const job =
|
|
5546
|
+
const job = startRetrievalRefresh(projectRoot, host, coordinator);
|
|
4603
5547
|
if (job) {
|
|
4604
5548
|
await withTimeout(job, coordinator.getWaitMs());
|
|
5549
|
+
} else if (isBackgroundWorkerManaged(projectRoot, host)) {
|
|
5550
|
+
await waitForPublishedSnapshot(coordinator, coordinator.getWaitMs());
|
|
4605
5551
|
}
|
|
4606
5552
|
try {
|
|
4607
|
-
|
|
5553
|
+
const readiness = await getSearchReadiness(coordinator);
|
|
5554
|
+
if (readiness.searchable) return { ready: true };
|
|
5555
|
+
if (readiness.blocked) return unavailableSnapshotResult(readiness.reason);
|
|
4608
5556
|
} catch {
|
|
4609
5557
|
}
|
|
4610
5558
|
const status = coordinator.snapshot();
|
|
@@ -4625,18 +5573,52 @@ async function waitForAutoIndexForRetrieval(projectRoot, host) {
|
|
|
4625
5573
|
text: `Automatic indexing is ${status.state}. Retry shortly or call index_status for progress. You can also run index_codebase explicitly.`
|
|
4626
5574
|
};
|
|
4627
5575
|
}
|
|
4628
|
-
async function
|
|
5576
|
+
async function stopAutoIndexForBackgroundWorker(projectRoot, host, waitForCompletion = false) {
|
|
5577
|
+
const coordinator = getCoordinator(projectRoot, host);
|
|
5578
|
+
if (!coordinator) {
|
|
5579
|
+
return { completed: true, completion: Promise.resolve() };
|
|
5580
|
+
}
|
|
5581
|
+
return coordinator.stop(waitForCompletion);
|
|
5582
|
+
}
|
|
5583
|
+
async function getSearchReadiness(coordinator) {
|
|
4629
5584
|
const indexer = coordinator.getIndexer();
|
|
4630
5585
|
if (indexer.getIndexFreshness) {
|
|
4631
5586
|
const freshness = await indexer.getIndexFreshness();
|
|
4632
|
-
|
|
5587
|
+
const searchable = freshness.readable && freshness.current && freshness.reason === "current";
|
|
5588
|
+
return {
|
|
5589
|
+
blocked: freshness.reason === "unreadable" || freshness.reason === "incompatible" || freshness.reason === "failed-batches" || freshness.reason === "migration-required",
|
|
5590
|
+
reason: freshness.reason,
|
|
5591
|
+
searchable
|
|
5592
|
+
};
|
|
5593
|
+
}
|
|
5594
|
+
const indexed = (await indexer.getStatus()).indexed;
|
|
5595
|
+
return { blocked: false, searchable: indexed };
|
|
5596
|
+
}
|
|
5597
|
+
function unavailableSnapshotResult(reason) {
|
|
5598
|
+
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.";
|
|
5599
|
+
return {
|
|
5600
|
+
ready: false,
|
|
5601
|
+
text: `${detail} Run index_codebase before retrying retrieval.`
|
|
5602
|
+
};
|
|
5603
|
+
}
|
|
5604
|
+
function startRetrievalRefresh(projectRoot, host, coordinator) {
|
|
5605
|
+
if (isBackgroundWorkerManaged(projectRoot, host)) {
|
|
5606
|
+
requestBackgroundWorkerRefresh(projectRoot, host, true);
|
|
5607
|
+
return isBackgroundWorkerLeader(projectRoot, host) ? coordinator.currentJob() : null;
|
|
5608
|
+
}
|
|
5609
|
+
return coordinator.start("retrieval") ?? coordinator.currentJob();
|
|
5610
|
+
}
|
|
5611
|
+
async function waitForPublishedSnapshot(coordinator, waitMs) {
|
|
5612
|
+
const deadline = Date.now() + waitMs;
|
|
5613
|
+
while (Date.now() < deadline) {
|
|
5614
|
+
if ((await getSearchReadiness(coordinator)).searchable) return;
|
|
5615
|
+
await new Promise((resolve18) => setTimeout(resolve18, Math.min(250, deadline - Date.now())));
|
|
4633
5616
|
}
|
|
4634
|
-
return (await indexer.getStatus()).indexed;
|
|
4635
5617
|
}
|
|
4636
5618
|
|
|
4637
5619
|
// src/tools/config-state.ts
|
|
4638
5620
|
var import_fs8 = require("fs");
|
|
4639
|
-
var
|
|
5621
|
+
var path13 = __toESM(require("path"), 1);
|
|
4640
5622
|
function normalizeKnowledgeBasePaths(config, projectRoot) {
|
|
4641
5623
|
const normalized = { ...config };
|
|
4642
5624
|
if (Array.isArray(normalized.knowledgeBases)) {
|
|
@@ -4663,8 +5645,8 @@ function loadEditableConfig(projectRoot, host) {
|
|
|
4663
5645
|
}
|
|
4664
5646
|
function saveConfig(projectRoot, config, host) {
|
|
4665
5647
|
const configPath = getConfigPath(projectRoot, host);
|
|
4666
|
-
const configDir =
|
|
4667
|
-
const configBaseDir =
|
|
5648
|
+
const configDir = path13.dirname(configPath);
|
|
5649
|
+
const configBaseDir = path13.dirname(configDir);
|
|
4668
5650
|
if (!(0, import_fs8.existsSync)(configDir)) {
|
|
4669
5651
|
(0, import_fs8.mkdirSync)(configDir, { recursive: true });
|
|
4670
5652
|
}
|
|
@@ -4679,7 +5661,7 @@ function saveConfig(projectRoot, config, host) {
|
|
|
4679
5661
|
|
|
4680
5662
|
// src/indexer/index.ts
|
|
4681
5663
|
var import_fs12 = require("fs");
|
|
4682
|
-
var
|
|
5664
|
+
var path20 = __toESM(require("path"), 1);
|
|
4683
5665
|
var import_perf_hooks = require("perf_hooks");
|
|
4684
5666
|
var import_child_process4 = require("child_process");
|
|
4685
5667
|
var import_util4 = require("util");
|
|
@@ -4706,7 +5688,7 @@ function pTimeout(promise, options) {
|
|
|
4706
5688
|
} = options;
|
|
4707
5689
|
let timer;
|
|
4708
5690
|
let abortHandler;
|
|
4709
|
-
const wrappedPromise = new Promise((
|
|
5691
|
+
const wrappedPromise = new Promise((resolve18, reject) => {
|
|
4710
5692
|
if (typeof milliseconds !== "number" || Math.sign(milliseconds) !== 1) {
|
|
4711
5693
|
throw new TypeError(`Expected \`milliseconds\` to be a positive number, got \`${milliseconds}\``);
|
|
4712
5694
|
}
|
|
@@ -4720,7 +5702,7 @@ function pTimeout(promise, options) {
|
|
|
4720
5702
|
};
|
|
4721
5703
|
signal.addEventListener("abort", abortHandler, { once: true });
|
|
4722
5704
|
}
|
|
4723
|
-
promise.then(
|
|
5705
|
+
promise.then(resolve18, reject);
|
|
4724
5706
|
if (milliseconds === Number.POSITIVE_INFINITY) {
|
|
4725
5707
|
return;
|
|
4726
5708
|
}
|
|
@@ -4728,7 +5710,7 @@ function pTimeout(promise, options) {
|
|
|
4728
5710
|
timer = customTimers.setTimeout.call(void 0, () => {
|
|
4729
5711
|
if (fallback) {
|
|
4730
5712
|
try {
|
|
4731
|
-
|
|
5713
|
+
resolve18(fallback());
|
|
4732
5714
|
} catch (error) {
|
|
4733
5715
|
reject(error);
|
|
4734
5716
|
}
|
|
@@ -4738,7 +5720,7 @@ function pTimeout(promise, options) {
|
|
|
4738
5720
|
promise.cancel();
|
|
4739
5721
|
}
|
|
4740
5722
|
if (message === false) {
|
|
4741
|
-
|
|
5723
|
+
resolve18();
|
|
4742
5724
|
} else if (message instanceof Error) {
|
|
4743
5725
|
reject(message);
|
|
4744
5726
|
} else {
|
|
@@ -5140,7 +6122,7 @@ var PQueue = class extends import_index.default {
|
|
|
5140
6122
|
// Assign unique ID if not provided
|
|
5141
6123
|
id: options.id ?? (this.#idAssigner++).toString()
|
|
5142
6124
|
};
|
|
5143
|
-
return new Promise((
|
|
6125
|
+
return new Promise((resolve18, reject) => {
|
|
5144
6126
|
const taskSymbol = /* @__PURE__ */ Symbol(`task-${options.id}`);
|
|
5145
6127
|
let cleanupQueueAbortHandler = () => void 0;
|
|
5146
6128
|
const run = async () => {
|
|
@@ -5180,7 +6162,7 @@ var PQueue = class extends import_index.default {
|
|
|
5180
6162
|
})]);
|
|
5181
6163
|
}
|
|
5182
6164
|
const result = await operation;
|
|
5183
|
-
|
|
6165
|
+
resolve18(result);
|
|
5184
6166
|
this.emit("completed", result);
|
|
5185
6167
|
} catch (error) {
|
|
5186
6168
|
reject(error);
|
|
@@ -5368,13 +6350,13 @@ var PQueue = class extends import_index.default {
|
|
|
5368
6350
|
});
|
|
5369
6351
|
}
|
|
5370
6352
|
async #onEvent(event, filter) {
|
|
5371
|
-
return new Promise((
|
|
6353
|
+
return new Promise((resolve18) => {
|
|
5372
6354
|
const listener = () => {
|
|
5373
6355
|
if (filter && !filter()) {
|
|
5374
6356
|
return;
|
|
5375
6357
|
}
|
|
5376
6358
|
this.off(event, listener);
|
|
5377
|
-
|
|
6359
|
+
resolve18();
|
|
5378
6360
|
};
|
|
5379
6361
|
this.on(event, listener);
|
|
5380
6362
|
});
|
|
@@ -5660,7 +6642,7 @@ async function onAttemptFailure({ error, attemptNumber, retriesConsumed, startTi
|
|
|
5660
6642
|
const finalDelay = Math.min(delayTime, remainingTime);
|
|
5661
6643
|
options.signal?.throwIfAborted();
|
|
5662
6644
|
if (finalDelay > 0) {
|
|
5663
|
-
await new Promise((
|
|
6645
|
+
await new Promise((resolve18, reject) => {
|
|
5664
6646
|
const onAbort = () => {
|
|
5665
6647
|
clearTimeout(timeoutToken);
|
|
5666
6648
|
options.signal?.removeEventListener("abort", onAbort);
|
|
@@ -5668,7 +6650,7 @@ async function onAttemptFailure({ error, attemptNumber, retriesConsumed, startTi
|
|
|
5668
6650
|
};
|
|
5669
6651
|
const timeoutToken = setTimeout(() => {
|
|
5670
6652
|
options.signal?.removeEventListener("abort", onAbort);
|
|
5671
|
-
|
|
6653
|
+
resolve18();
|
|
5672
6654
|
}, finalDelay);
|
|
5673
6655
|
if (options.unref) {
|
|
5674
6656
|
timeoutToken.unref?.();
|
|
@@ -5730,10 +6712,10 @@ async function pRetry(input, options = {}) {
|
|
|
5730
6712
|
|
|
5731
6713
|
// src/embeddings/detector.ts
|
|
5732
6714
|
var import_fs9 = require("fs");
|
|
5733
|
-
var
|
|
5734
|
-
var
|
|
6715
|
+
var path14 = __toESM(require("path"), 1);
|
|
6716
|
+
var os5 = __toESM(require("os"), 1);
|
|
5735
6717
|
function getOpenCodeAuthPath() {
|
|
5736
|
-
return
|
|
6718
|
+
return path14.join(os5.homedir(), ".local", "share", "opencode", "auth.json");
|
|
5737
6719
|
}
|
|
5738
6720
|
function loadOpenCodeAuth() {
|
|
5739
6721
|
const authPath = getOpenCodeAuthPath();
|
|
@@ -6030,17 +7012,17 @@ function validateExternalUrl(urlString) {
|
|
|
6030
7012
|
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
6031
7013
|
return { valid: false, reason: `Blocked protocol: ${parsed.protocol}` };
|
|
6032
7014
|
}
|
|
6033
|
-
const
|
|
6034
|
-
if (BLOCKED_HOSTNAMES.has(
|
|
6035
|
-
return { valid: false, reason: `Blocked: cloud metadata service (${
|
|
7015
|
+
const hostname3 = parsed.hostname.toLowerCase();
|
|
7016
|
+
if (BLOCKED_HOSTNAMES.has(hostname3)) {
|
|
7017
|
+
return { valid: false, reason: `Blocked: cloud metadata service (${hostname3})` };
|
|
6036
7018
|
}
|
|
6037
7019
|
for (const pattern of BLOCKED_METADATA_IPS) {
|
|
6038
|
-
if (pattern.test(
|
|
6039
|
-
return { valid: false, reason: `Blocked: cloud metadata IP (${
|
|
7020
|
+
if (pattern.test(hostname3)) {
|
|
7021
|
+
return { valid: false, reason: `Blocked: cloud metadata IP (${hostname3})` };
|
|
6040
7022
|
}
|
|
6041
7023
|
}
|
|
6042
|
-
if (/^169\.254\./.test(
|
|
6043
|
-
return { valid: false, reason: `Blocked: link-local address (${
|
|
7024
|
+
if (/^169\.254\./.test(hostname3)) {
|
|
7025
|
+
return { valid: false, reason: `Blocked: link-local address (${hostname3})` };
|
|
6044
7026
|
}
|
|
6045
7027
|
return { valid: true };
|
|
6046
7028
|
}
|
|
@@ -7132,8 +8114,8 @@ function extractParamNames(params) {
|
|
|
7132
8114
|
}
|
|
7133
8115
|
|
|
7134
8116
|
// src/native/binding.ts
|
|
7135
|
-
var
|
|
7136
|
-
var
|
|
8117
|
+
var os6 = __toESM(require("os"), 1);
|
|
8118
|
+
var path15 = __toESM(require("path"), 1);
|
|
7137
8119
|
var module2 = __toESM(require("module"), 1);
|
|
7138
8120
|
var import_node_url = require("url");
|
|
7139
8121
|
|
|
@@ -7170,7 +8152,7 @@ var STABLE_NATIVE_BINARY_NAME = IDENTITY_CATALOG.native.binaryName;
|
|
|
7170
8152
|
|
|
7171
8153
|
// src/native/binding.ts
|
|
7172
8154
|
var import_meta = {};
|
|
7173
|
-
function getNativeBindingFilename(platform2 =
|
|
8155
|
+
function getNativeBindingFilename(platform2 = os6.platform(), arch2 = os6.arch()) {
|
|
7174
8156
|
if (platform2 === "darwin" && arch2 === "arm64") {
|
|
7175
8157
|
return `${STABLE_NATIVE_BINARY_NAME}.darwin-arm64.node`;
|
|
7176
8158
|
}
|
|
@@ -7188,25 +8170,25 @@ function getNativeBindingFilename(platform2 = os5.platform(), arch2 = os5.arch()
|
|
|
7188
8170
|
}
|
|
7189
8171
|
throw new Error(`Unsupported platform: ${platform2}-${arch2}`);
|
|
7190
8172
|
}
|
|
7191
|
-
function resolveNativeBindingPath(packageRoot, platform2 =
|
|
7192
|
-
return
|
|
8173
|
+
function resolveNativeBindingPath(packageRoot, platform2 = os6.platform(), arch2 = os6.arch()) {
|
|
8174
|
+
return path15.join(packageRoot, "native", getNativeBindingFilename(platform2, arch2));
|
|
7193
8175
|
}
|
|
7194
8176
|
function getNativeBinding() {
|
|
7195
8177
|
let currentDir;
|
|
7196
8178
|
let requireTarget;
|
|
7197
8179
|
if (typeof import_meta !== "undefined" && import_meta.url) {
|
|
7198
|
-
currentDir =
|
|
8180
|
+
currentDir = path15.dirname((0, import_node_url.fileURLToPath)(import_meta.url));
|
|
7199
8181
|
requireTarget = import_meta.url;
|
|
7200
8182
|
} else if (typeof __dirname !== "undefined") {
|
|
7201
8183
|
currentDir = __dirname;
|
|
7202
8184
|
requireTarget = __filename;
|
|
7203
8185
|
} else {
|
|
7204
8186
|
currentDir = process.cwd();
|
|
7205
|
-
requireTarget =
|
|
8187
|
+
requireTarget = path15.join(currentDir, "index.js");
|
|
7206
8188
|
}
|
|
7207
8189
|
const normalizedDir = currentDir.replace(/\\/g, "/");
|
|
7208
|
-
const isDevMode = normalizedDir.includes("/src/native") || currentDir.includes(
|
|
7209
|
-
const packageRoot = isDevMode ?
|
|
8190
|
+
const isDevMode = normalizedDir.includes("/src/native") || currentDir.includes(path15.join("src", "native"));
|
|
8191
|
+
const packageRoot = isDevMode ? path15.resolve(currentDir, "../..") : path15.resolve(currentDir, "..");
|
|
7210
8192
|
const nativePath = resolveNativeBindingPath(packageRoot);
|
|
7211
8193
|
const require2 = module2.createRequire(requireTarget);
|
|
7212
8194
|
return require2(nativePath);
|
|
@@ -7790,8 +8772,8 @@ var Database = class _Database {
|
|
|
7790
8772
|
|
|
7791
8773
|
// src/git/branch-materialization.ts
|
|
7792
8774
|
var import_fs10 = require("fs");
|
|
7793
|
-
var
|
|
7794
|
-
var
|
|
8775
|
+
var os7 = __toESM(require("os"), 1);
|
|
8776
|
+
var path16 = __toESM(require("path"), 1);
|
|
7795
8777
|
|
|
7796
8778
|
// src/git/branch-resolution.ts
|
|
7797
8779
|
var import_child_process = require("child_process");
|
|
@@ -8110,13 +9092,13 @@ async function isWorktreeRegistered(projectRoot, worktreePath) {
|
|
|
8110
9092
|
return false;
|
|
8111
9093
|
}
|
|
8112
9094
|
function isPathWithinRoot(filePath, rootPath) {
|
|
8113
|
-
const relative14 =
|
|
8114
|
-
return relative14 === "" || !relative14.startsWith(`..${
|
|
9095
|
+
const relative14 = path16.relative(path16.resolve(rootPath), path16.resolve(filePath));
|
|
9096
|
+
return relative14 === "" || !relative14.startsWith(`..${path16.sep}`) && relative14 !== ".." && !path16.isAbsolute(relative14);
|
|
8115
9097
|
}
|
|
8116
9098
|
async function pruneExactMissingWorktreeRegistration(projectRoot, worktreePath) {
|
|
8117
9099
|
if (await pathExists(worktreePath)) return false;
|
|
8118
9100
|
const commonDir = await runGit(projectRoot, ["rev-parse", "--path-format=absolute", "--git-common-dir"]);
|
|
8119
|
-
const registrationsRoot =
|
|
9101
|
+
const registrationsRoot = path16.join(commonDir, "worktrees");
|
|
8120
9102
|
let entries;
|
|
8121
9103
|
try {
|
|
8122
9104
|
entries = await import_fs10.promises.readdir(registrationsRoot, { withFileTypes: true });
|
|
@@ -8127,16 +9109,16 @@ async function pruneExactMissingWorktreeRegistration(projectRoot, worktreePath)
|
|
|
8127
9109
|
const target = canonicalizePathForComparison(worktreePath);
|
|
8128
9110
|
for (const entry of entries) {
|
|
8129
9111
|
if (!entry.isDirectory()) continue;
|
|
8130
|
-
const registrationPath =
|
|
9112
|
+
const registrationPath = path16.join(registrationsRoot, entry.name);
|
|
8131
9113
|
if (!isPathWithinRoot(registrationPath, registrationsRoot)) continue;
|
|
8132
9114
|
let gitdirPath;
|
|
8133
9115
|
try {
|
|
8134
|
-
gitdirPath = (await import_fs10.promises.readFile(
|
|
9116
|
+
gitdirPath = (await import_fs10.promises.readFile(path16.join(registrationPath, "gitdir"), "utf8")).trim();
|
|
8135
9117
|
} catch {
|
|
8136
9118
|
continue;
|
|
8137
9119
|
}
|
|
8138
|
-
const resolvedGitdirPath =
|
|
8139
|
-
if (canonicalizePathForComparison(
|
|
9120
|
+
const resolvedGitdirPath = path16.isAbsolute(gitdirPath) ? gitdirPath : path16.resolve(registrationPath, gitdirPath);
|
|
9121
|
+
if (canonicalizePathForComparison(path16.dirname(resolvedGitdirPath)) !== target) continue;
|
|
8140
9122
|
await import_fs10.promises.rm(registrationPath, { recursive: true, force: true });
|
|
8141
9123
|
return true;
|
|
8142
9124
|
}
|
|
@@ -8154,7 +9136,7 @@ async function removeWorktree(projectRoot, worktreePath) {
|
|
|
8154
9136
|
registered = await isWorktreeRegistered(projectRoot, worktreePath);
|
|
8155
9137
|
} catch (error) {
|
|
8156
9138
|
errors.push(asError(error));
|
|
8157
|
-
throw new AggregateError(errors, `Could not verify temporary worktree deregistration; preserved ${
|
|
9139
|
+
throw new AggregateError(errors, `Could not verify temporary worktree deregistration; preserved ${path16.dirname(worktreePath)}`);
|
|
8158
9140
|
}
|
|
8159
9141
|
if (registered) {
|
|
8160
9142
|
try {
|
|
@@ -8170,7 +9152,7 @@ async function removeWorktree(projectRoot, worktreePath) {
|
|
|
8170
9152
|
registered = await isWorktreeRegistered(projectRoot, worktreePath);
|
|
8171
9153
|
} catch (error) {
|
|
8172
9154
|
errors.push(asError(error));
|
|
8173
|
-
throw new AggregateError(errors, `Could not verify temporary worktree deregistration; preserved ${
|
|
9155
|
+
throw new AggregateError(errors, `Could not verify temporary worktree deregistration; preserved ${path16.dirname(worktreePath)}`);
|
|
8174
9156
|
}
|
|
8175
9157
|
}
|
|
8176
9158
|
if (registered && !await pathExists(worktreePath)) {
|
|
@@ -8183,13 +9165,13 @@ async function removeWorktree(projectRoot, worktreePath) {
|
|
|
8183
9165
|
}
|
|
8184
9166
|
if (registered) {
|
|
8185
9167
|
errors.push(new Error(`Temporary worktree remains registered: ${worktreePath}`));
|
|
8186
|
-
throw new AggregateError(errors, `Failed to deregister temporary worktree; preserved ${
|
|
9168
|
+
throw new AggregateError(errors, `Failed to deregister temporary worktree; preserved ${path16.dirname(worktreePath)}`);
|
|
8187
9169
|
}
|
|
8188
9170
|
try {
|
|
8189
|
-
await import_fs10.promises.rm(
|
|
9171
|
+
await import_fs10.promises.rm(path16.dirname(worktreePath), { recursive: true, force: true });
|
|
8190
9172
|
} catch (error) {
|
|
8191
9173
|
errors.push(asError(error));
|
|
8192
|
-
throw new AggregateError(errors, `Deregistered the temporary worktree but could not remove ${
|
|
9174
|
+
throw new AggregateError(errors, `Deregistered the temporary worktree but could not remove ${path16.dirname(worktreePath)}`);
|
|
8193
9175
|
}
|
|
8194
9176
|
}
|
|
8195
9177
|
async function cleanupTemporaryWorktree(projectRoot, worktreePath, temporaryRoot) {
|
|
@@ -8225,9 +9207,9 @@ async function withMaterializedBranch(request, callback) {
|
|
|
8225
9207
|
`Git ref ${JSON.stringify(request.ref ?? request.branch)} is not available locally. For an unfetched branch, pass a remote-qualified name such as origin/feature.`
|
|
8226
9208
|
);
|
|
8227
9209
|
}
|
|
8228
|
-
const temporaryRoot = await import_fs10.promises.mkdtemp(
|
|
8229
|
-
const worktreePath =
|
|
8230
|
-
const hooksPath =
|
|
9210
|
+
const temporaryRoot = await import_fs10.promises.mkdtemp(path16.join(os7.tmpdir(), "codebase-index-branch-"));
|
|
9211
|
+
const worktreePath = path16.join(temporaryRoot, "worktree");
|
|
9212
|
+
const hooksPath = path16.join(temporaryRoot, "hooks");
|
|
8231
9213
|
await import_fs10.promises.mkdir(hooksPath);
|
|
8232
9214
|
const info = {
|
|
8233
9215
|
branch: request.branch,
|
|
@@ -8279,7 +9261,7 @@ async function withMaterializedBranch(request, callback) {
|
|
|
8279
9261
|
// src/tools/changed-files.ts
|
|
8280
9262
|
var import_child_process2 = require("child_process");
|
|
8281
9263
|
var import_fs11 = require("fs");
|
|
8282
|
-
var
|
|
9264
|
+
var path17 = __toESM(require("path"), 1);
|
|
8283
9265
|
var import_util2 = require("util");
|
|
8284
9266
|
var execFileAsync2 = (0, import_util2.promisify)(import_child_process2.execFile);
|
|
8285
9267
|
var GH_PR_VIEW_FIELDS = [
|
|
@@ -8421,7 +9403,7 @@ function getHeadRepositoryIdentity(data, host) {
|
|
|
8421
9403
|
return `${host}/${owner.toLowerCase()}/${repository.replace(/\.git$/i, "").toLowerCase()}`;
|
|
8422
9404
|
}
|
|
8423
9405
|
function getLocalRepositoryIdentity(projectRoot) {
|
|
8424
|
-
let canonicalRoot =
|
|
9406
|
+
let canonicalRoot = path17.resolve(projectRoot);
|
|
8425
9407
|
try {
|
|
8426
9408
|
canonicalRoot = import_fs11.realpathSync.native(canonicalRoot);
|
|
8427
9409
|
} catch {
|
|
@@ -8482,17 +9464,17 @@ async function getMergeBase(projectRoot, baseCommit, headCommit) {
|
|
|
8482
9464
|
return commit;
|
|
8483
9465
|
}
|
|
8484
9466
|
function normalizeFiles(rawFiles, projectRoot) {
|
|
8485
|
-
const root =
|
|
9467
|
+
const root = path17.resolve(projectRoot);
|
|
8486
9468
|
const seen = /* @__PURE__ */ new Set();
|
|
8487
9469
|
const result = [];
|
|
8488
9470
|
for (const raw of rawFiles) {
|
|
8489
9471
|
if (raw.length === 0) continue;
|
|
8490
|
-
const absolute =
|
|
8491
|
-
const relative14 =
|
|
8492
|
-
if (
|
|
9472
|
+
const absolute = path17.resolve(root, raw);
|
|
9473
|
+
const relative14 = path17.relative(root, absolute);
|
|
9474
|
+
if (path17.isAbsolute(raw) || relative14 === ".." || relative14.startsWith(`..${path17.sep}`) || path17.isAbsolute(relative14)) {
|
|
8493
9475
|
throw new Error(`Changed file escapes the project root: ${JSON.stringify(raw)}`);
|
|
8494
9476
|
}
|
|
8495
|
-
const cleaned = relative14.startsWith(`.${
|
|
9477
|
+
const cleaned = relative14.startsWith(`.${path17.sep}`) ? relative14.slice(2) : relative14;
|
|
8496
9478
|
if (!seen.has(cleaned)) {
|
|
8497
9479
|
seen.add(cleaned);
|
|
8498
9480
|
result.push(cleaned);
|
|
@@ -8503,7 +9485,7 @@ function normalizeFiles(rawFiles, projectRoot) {
|
|
|
8503
9485
|
|
|
8504
9486
|
// src/indexer/git-blame.ts
|
|
8505
9487
|
var import_child_process3 = require("child_process");
|
|
8506
|
-
var
|
|
9488
|
+
var path18 = __toESM(require("path"), 1);
|
|
8507
9489
|
var import_util3 = require("util");
|
|
8508
9490
|
var execFileAsync3 = (0, import_util3.promisify)(import_child_process3.execFile);
|
|
8509
9491
|
function parseGitBlamePorcelain(output) {
|
|
@@ -8541,7 +9523,7 @@ function parseGitBlamePorcelain(output) {
|
|
|
8541
9523
|
return Array.from(commits.values()).filter((commit) => commit.lines > 0).sort((a, b) => b.lines - a.lines || b.committedAt - a.committedAt)[0];
|
|
8542
9524
|
}
|
|
8543
9525
|
async function getChunkGitBlame(projectRoot, filePath, startLine, endLine) {
|
|
8544
|
-
const relativePath =
|
|
9526
|
+
const relativePath = path18.relative(projectRoot, filePath);
|
|
8545
9527
|
try {
|
|
8546
9528
|
const { stdout } = await execFileAsync3(
|
|
8547
9529
|
"git",
|
|
@@ -9120,8 +10102,8 @@ function pathSegmentsForAffinityMatch(filePath) {
|
|
|
9120
10102
|
if (segments.length === 0) {
|
|
9121
10103
|
return [];
|
|
9122
10104
|
}
|
|
9123
|
-
const
|
|
9124
|
-
const basenameWithoutExt =
|
|
10105
|
+
const basename10 = segments[segments.length - 1] ?? "";
|
|
10106
|
+
const basenameWithoutExt = basename10.replace(/\.[^/.]+$/u, "");
|
|
9125
10107
|
const normalizedSegments = segments.map((segment) => segment.toLowerCase());
|
|
9126
10108
|
return Array.from(/* @__PURE__ */ new Set([
|
|
9127
10109
|
...normalizedSegments,
|
|
@@ -9430,8 +10412,8 @@ function hasAllEmbeddingParts(parts, expectedPartCount) {
|
|
|
9430
10412
|
|
|
9431
10413
|
// src/indexer/failed-state-persistence.ts
|
|
9432
10414
|
var fs2 = __toESM(require("fs"), 1);
|
|
9433
|
-
var
|
|
9434
|
-
var
|
|
10415
|
+
var import_node_crypto2 = require("crypto");
|
|
10416
|
+
var path19 = __toESM(require("path"), 1);
|
|
9435
10417
|
var import_node_string_decoder = require("string_decoder");
|
|
9436
10418
|
var CURRENT_FAILED_BATCH_VERSION = 1;
|
|
9437
10419
|
var DEFAULT_MALFORMED_LINE_ACTION = "skip";
|
|
@@ -9449,7 +10431,7 @@ function* readFailedBatchRecords(filePath, options = {}) {
|
|
|
9449
10431
|
function createFailedBatchWriter(targetPath) {
|
|
9450
10432
|
const temporaryPath = createTemporaryPath(targetPath);
|
|
9451
10433
|
let finalized = false;
|
|
9452
|
-
fs2.mkdirSync(
|
|
10434
|
+
fs2.mkdirSync(path19.dirname(targetPath), { recursive: true });
|
|
9453
10435
|
fs2.closeSync(fs2.openSync(temporaryPath, "w"));
|
|
9454
10436
|
const write = (record) => {
|
|
9455
10437
|
if (finalized) {
|
|
@@ -9468,7 +10450,7 @@ function createFailedBatchWriter(targetPath) {
|
|
|
9468
10450
|
if (lines.length === 0) {
|
|
9469
10451
|
return;
|
|
9470
10452
|
}
|
|
9471
|
-
fs2.mkdirSync(
|
|
10453
|
+
fs2.mkdirSync(path19.dirname(targetPath), { recursive: true });
|
|
9472
10454
|
fs2.appendFileSync(temporaryPath, `${lines.join("\n")}
|
|
9473
10455
|
`, "utf-8");
|
|
9474
10456
|
};
|
|
@@ -9476,7 +10458,7 @@ function createFailedBatchWriter(targetPath) {
|
|
|
9476
10458
|
if (finalized) {
|
|
9477
10459
|
return;
|
|
9478
10460
|
}
|
|
9479
|
-
fs2.mkdirSync(
|
|
10461
|
+
fs2.mkdirSync(path19.dirname(targetPath), { recursive: true });
|
|
9480
10462
|
fs2.renameSync(temporaryPath, targetPath);
|
|
9481
10463
|
finalized = true;
|
|
9482
10464
|
};
|
|
@@ -9622,10 +10604,10 @@ function stripLeadingBomAndWhitespace(value) {
|
|
|
9622
10604
|
return result;
|
|
9623
10605
|
}
|
|
9624
10606
|
function createTemporaryPath(targetPath) {
|
|
9625
|
-
const randomId = (0,
|
|
9626
|
-
const targetDir =
|
|
9627
|
-
const baseName =
|
|
9628
|
-
return
|
|
10607
|
+
const randomId = (0, import_node_crypto2.createHash)("sha1").update(`${Date.now()}:${(0, import_node_crypto2.randomBytes)(8).toString("hex")}`).digest("hex");
|
|
10608
|
+
const targetDir = path19.dirname(targetPath);
|
|
10609
|
+
const baseName = path19.basename(targetPath);
|
|
10610
|
+
return path19.join(targetDir, `.${baseName}.${randomId}.tmp`);
|
|
9629
10611
|
}
|
|
9630
10612
|
function handleMalformedLine(filePath, lineNumber, line, error, options) {
|
|
9631
10613
|
const action = options.malformedLineAction ?? DEFAULT_MALFORMED_LINE_ACTION;
|
|
@@ -9871,9 +10853,9 @@ var SWIFT_PARSER_VERSION = "1";
|
|
|
9871
10853
|
var METAL_PARSER_VERSION = "1";
|
|
9872
10854
|
var SYMBOL_EXTRACTOR_VERSION = "1";
|
|
9873
10855
|
function isPathWithinRoot2(filePath, rootPath) {
|
|
9874
|
-
const normalizedFilePath =
|
|
9875
|
-
const normalizedRoot =
|
|
9876
|
-
return normalizedFilePath === normalizedRoot || normalizedFilePath.startsWith(`${normalizedRoot}${
|
|
10856
|
+
const normalizedFilePath = path20.resolve(filePath);
|
|
10857
|
+
const normalizedRoot = path20.resolve(rootPath);
|
|
10858
|
+
return normalizedFilePath === normalizedRoot || normalizedFilePath.startsWith(`${normalizedRoot}${path20.sep}`);
|
|
9877
10859
|
}
|
|
9878
10860
|
function promoteIdentifierMatches(query, combined, semanticCandidates, keywordCandidates, database, branchChunkIds, prioritizeSourcePaths = classifyQueryIntentRaw(query) === "source") {
|
|
9879
10861
|
if (combined.length === 0) {
|
|
@@ -10204,10 +11186,10 @@ function matchesHardSearchFilters(candidate, options, projectRoot) {
|
|
|
10204
11186
|
}
|
|
10205
11187
|
if (options?.directory) {
|
|
10206
11188
|
const candidatePath = canonicalizePathForComparison(
|
|
10207
|
-
|
|
11189
|
+
path20.resolve(projectRoot, candidate.metadata.filePath.replace(/\\/g, path20.sep))
|
|
10208
11190
|
);
|
|
10209
11191
|
const directoryPath = canonicalizePathForComparison(
|
|
10210
|
-
|
|
11192
|
+
path20.resolve(projectRoot, options.directory.trim().replace(/\\/g, path20.sep))
|
|
10211
11193
|
);
|
|
10212
11194
|
if (!isPathWithinRoot2(candidatePath, directoryPath)) return false;
|
|
10213
11195
|
}
|
|
@@ -10320,26 +11302,37 @@ var Indexer = class _Indexer {
|
|
|
10320
11302
|
return this.indexPathOverride ?? resolveProjectIndexPath(this.projectRoot, this.config.scope, this.host);
|
|
10321
11303
|
}
|
|
10322
11304
|
toCanonicalFilePath(filePath) {
|
|
10323
|
-
if (!
|
|
11305
|
+
if (!path20.isAbsolute(filePath)) {
|
|
10324
11306
|
return this.resolveStoredFilePath(filePath, this.projectRoot);
|
|
10325
11307
|
}
|
|
10326
|
-
if (
|
|
11308
|
+
if (path20.resolve(this.materializedProjectRoot) === path20.resolve(this.projectRoot) || !isPathWithinRoot2(filePath, this.materializedProjectRoot)) {
|
|
10327
11309
|
return filePath;
|
|
10328
11310
|
}
|
|
10329
|
-
return
|
|
11311
|
+
return path20.resolve(this.projectRoot, path20.relative(this.materializedProjectRoot, filePath));
|
|
10330
11312
|
}
|
|
10331
11313
|
toStoredFilePath(filePath) {
|
|
10332
11314
|
const canonicalFilePath = this.toCanonicalFilePath(filePath);
|
|
10333
11315
|
if (this.config.scope !== "project" || !isPathWithinRoot2(canonicalFilePath, this.projectRoot)) {
|
|
10334
11316
|
return canonicalFilePath;
|
|
10335
11317
|
}
|
|
10336
|
-
return
|
|
11318
|
+
return path20.relative(this.projectRoot, canonicalFilePath).split(path20.sep).join("/");
|
|
11319
|
+
}
|
|
11320
|
+
isStoredPathExcluded(storedPath) {
|
|
11321
|
+
let matchPath = storedPath.split(path20.sep).join("/");
|
|
11322
|
+
if (path20.isAbsolute(storedPath)) {
|
|
11323
|
+
const relativePath = path20.relative(this.projectRoot, storedPath).split(path20.sep).join("/");
|
|
11324
|
+
if (relativePath.startsWith("..") || path20.isAbsolute(relativePath)) {
|
|
11325
|
+
return false;
|
|
11326
|
+
}
|
|
11327
|
+
matchPath = relativePath;
|
|
11328
|
+
}
|
|
11329
|
+
return isExcludedByPatterns(matchPath, this.config.exclude);
|
|
10337
11330
|
}
|
|
10338
11331
|
resolveStoredFilePath(filePath, rootPath = this.projectRoot) {
|
|
10339
|
-
if (
|
|
11332
|
+
if (path20.isAbsolute(filePath)) {
|
|
10340
11333
|
return filePath;
|
|
10341
11334
|
}
|
|
10342
|
-
const resolvedPath =
|
|
11335
|
+
const resolvedPath = path20.resolve(rootPath, ...filePath.split("/"));
|
|
10343
11336
|
if (!isPathWithinRoot2(resolvedPath, rootPath)) {
|
|
10344
11337
|
throw new Error(`Stored project path escapes project root: ${JSON.stringify(filePath)}`);
|
|
10345
11338
|
}
|
|
@@ -10363,7 +11356,7 @@ var Indexer = class _Indexer {
|
|
|
10363
11356
|
}
|
|
10364
11357
|
toMaterializedFilePath(filePath) {
|
|
10365
11358
|
const storedFilePath = this.toStoredFilePath(filePath);
|
|
10366
|
-
if (
|
|
11359
|
+
if (path20.isAbsolute(storedFilePath)) {
|
|
10367
11360
|
return storedFilePath;
|
|
10368
11361
|
}
|
|
10369
11362
|
return this.resolveStoredFilePath(storedFilePath, this.materializedProjectRoot);
|
|
@@ -10380,10 +11373,10 @@ var Indexer = class _Indexer {
|
|
|
10380
11373
|
}
|
|
10381
11374
|
getRuntimeArtifactPath(fileName) {
|
|
10382
11375
|
const namespace = this.getRuntimeArtifactNamespace();
|
|
10383
|
-
if (!namespace) return
|
|
10384
|
-
const extension =
|
|
11376
|
+
if (!namespace) return path20.join(this.indexPath, fileName);
|
|
11377
|
+
const extension = path20.extname(fileName);
|
|
10385
11378
|
const baseName = fileName.slice(0, fileName.length - extension.length);
|
|
10386
|
-
return
|
|
11379
|
+
return path20.join(this.indexPath, `${baseName}.${namespace}${extension}`);
|
|
10387
11380
|
}
|
|
10388
11381
|
refreshRuntimeArtifactPaths() {
|
|
10389
11382
|
this.fileHashCachePath = this.getRuntimeArtifactPath("file-hashes.json");
|
|
@@ -10396,14 +11389,14 @@ var Indexer = class _Indexer {
|
|
|
10396
11389
|
getMaterializedKnowledgeBases() {
|
|
10397
11390
|
const canonicalProjectRoot = this.getCanonicalPath(this.projectRoot);
|
|
10398
11391
|
return this.config.knowledgeBases.map((knowledgeBase) => {
|
|
10399
|
-
const configuredPath =
|
|
11392
|
+
const configuredPath = path20.isAbsolute(knowledgeBase) ? knowledgeBase : path20.resolve(this.projectRoot, knowledgeBase);
|
|
10400
11393
|
const canonicalPath = this.getCanonicalPath(configuredPath);
|
|
10401
11394
|
if (!isPathWithinRoot2(canonicalPath, canonicalProjectRoot)) {
|
|
10402
11395
|
return canonicalPath;
|
|
10403
11396
|
}
|
|
10404
|
-
return
|
|
11397
|
+
return path20.resolve(
|
|
10405
11398
|
this.materializedProjectRoot,
|
|
10406
|
-
|
|
11399
|
+
path20.relative(canonicalProjectRoot, canonicalPath)
|
|
10407
11400
|
);
|
|
10408
11401
|
});
|
|
10409
11402
|
}
|
|
@@ -10411,7 +11404,7 @@ var Indexer = class _Indexer {
|
|
|
10411
11404
|
try {
|
|
10412
11405
|
return canonicalizePathForComparison(targetPath);
|
|
10413
11406
|
} catch {
|
|
10414
|
-
return
|
|
11407
|
+
return path20.resolve(targetPath);
|
|
10415
11408
|
}
|
|
10416
11409
|
}
|
|
10417
11410
|
getProjectIdentityHash(projectRoot) {
|
|
@@ -10537,7 +11530,7 @@ var Indexer = class _Indexer {
|
|
|
10537
11530
|
atomicWriteSync(targetPath, data) {
|
|
10538
11531
|
const lease = this.requireActiveLease();
|
|
10539
11532
|
const tempPath = createLeaseTemporaryPath(targetPath, lease.owner, "tmp");
|
|
10540
|
-
(0, import_fs12.mkdirSync)(
|
|
11533
|
+
(0, import_fs12.mkdirSync)(path20.dirname(targetPath), { recursive: true });
|
|
10541
11534
|
try {
|
|
10542
11535
|
(0, import_fs12.writeFileSync)(tempPath, data);
|
|
10543
11536
|
(0, import_fs12.renameSync)(tempPath, targetPath);
|
|
@@ -10547,14 +11540,14 @@ var Indexer = class _Indexer {
|
|
|
10547
11540
|
}
|
|
10548
11541
|
saveInvertedIndex(invertedIndex) {
|
|
10549
11542
|
this.atomicWriteSync(
|
|
10550
|
-
|
|
11543
|
+
path20.join(this.indexPath, "inverted-index.json"),
|
|
10551
11544
|
invertedIndex.serialize()
|
|
10552
11545
|
);
|
|
10553
11546
|
}
|
|
10554
11547
|
getScopedRoots(projectRoot = this.projectRoot) {
|
|
10555
11548
|
const roots = /* @__PURE__ */ new Set([this.getCanonicalPath(projectRoot)]);
|
|
10556
11549
|
for (const kbRoot of this.config.knowledgeBases) {
|
|
10557
|
-
roots.add(this.getCanonicalPath(
|
|
11550
|
+
roots.add(this.getCanonicalPath(path20.resolve(projectRoot, kbRoot)));
|
|
10558
11551
|
}
|
|
10559
11552
|
return Array.from(roots);
|
|
10560
11553
|
}
|
|
@@ -10971,7 +11964,7 @@ var Indexer = class _Indexer {
|
|
|
10971
11964
|
return configuredProviderInfo !== null && recovery.embeddingProvider === configuredProviderInfo.provider && recovery.embeddingModel === configuredProviderInfo.modelInfo.model && recovery.embeddingDimensions === configuredProviderInfo.modelInfo.dimensions && recovery.embeddingStrategyVersion === EMBEDDING_STRATEGY_VERSION;
|
|
10972
11965
|
}
|
|
10973
11966
|
hasUnknownLegacyForceIndexClear(owner) {
|
|
10974
|
-
return owner.operation === "force-index" && owner.clearRecovery === void 0 && owner.recoveryProtocolVersion !== 1 && (0, import_fs12.existsSync)(
|
|
11967
|
+
return owner.operation === "force-index" && owner.clearRecovery === void 0 && owner.recoveryProtocolVersion !== 1 && (0, import_fs12.existsSync)(path20.join(this.indexPath, "force-index-phase"));
|
|
10975
11968
|
}
|
|
10976
11969
|
async recoverFromInterruptedIndexingUnlocked(owners) {
|
|
10977
11970
|
for (const owner of owners) {
|
|
@@ -11359,7 +12352,7 @@ var Indexer = class _Indexer {
|
|
|
11359
12352
|
await options.queue.onSizeLessThan(Math.max(1, options.providerRateLimits.concurrency));
|
|
11360
12353
|
const task = options.queue.add(async () => {
|
|
11361
12354
|
if (options.rateLimitState.backoffMs > 0) {
|
|
11362
|
-
await new Promise((
|
|
12355
|
+
await new Promise((resolve18) => setTimeout(resolve18, options.rateLimitState.backoffMs));
|
|
11363
12356
|
}
|
|
11364
12357
|
try {
|
|
11365
12358
|
const embeddingResult = await pRetry(
|
|
@@ -11778,12 +12771,12 @@ var Indexer = class _Indexer {
|
|
|
11778
12771
|
}
|
|
11779
12772
|
}
|
|
11780
12773
|
captureReaderArtifactFingerprint() {
|
|
11781
|
-
const storePath =
|
|
12774
|
+
const storePath = path20.join(this.indexPath, "vectors");
|
|
11782
12775
|
return {
|
|
11783
12776
|
vectors: `${this.getReaderFileFingerprint(storePath)}|${this.getReaderFileFingerprint(`${storePath}.meta.json`)}`,
|
|
11784
|
-
keyword: this.getReaderFileFingerprint(
|
|
11785
|
-
database: this.getReaderFileFingerprint(
|
|
11786
|
-
databaseIdentity: this.getReaderFileFingerprint(
|
|
12777
|
+
keyword: this.getReaderFileFingerprint(path20.join(this.indexPath, "inverted-index.json")),
|
|
12778
|
+
database: this.getReaderFileFingerprint(path20.join(this.indexPath, "codebase.db")),
|
|
12779
|
+
databaseIdentity: this.getReaderFileFingerprint(path20.join(this.indexPath, "codebase.db"), true)
|
|
11787
12780
|
};
|
|
11788
12781
|
}
|
|
11789
12782
|
refreshReaderArtifacts() {
|
|
@@ -11808,10 +12801,10 @@ var Indexer = class _Indexer {
|
|
|
11808
12801
|
issues.set(component, this.createReadIssue(component, message));
|
|
11809
12802
|
this.readerArtifactRetryAfter.set(component, Date.now() + READER_ARTIFACT_RETRY_INTERVAL_MS);
|
|
11810
12803
|
};
|
|
11811
|
-
const storePath =
|
|
12804
|
+
const storePath = path20.join(this.indexPath, "vectors");
|
|
11812
12805
|
const vectorMetadataPath = `${storePath}.meta.json`;
|
|
11813
|
-
const invertedIndexPath =
|
|
11814
|
-
const dbPath =
|
|
12806
|
+
const invertedIndexPath = path20.join(this.indexPath, "inverted-index.json");
|
|
12807
|
+
const dbPath = path20.join(this.indexPath, "codebase.db");
|
|
11815
12808
|
if (vectorsChanged || retryDue("vectors")) {
|
|
11816
12809
|
const vectorStoreExists = (0, import_fs12.existsSync)(storePath);
|
|
11817
12810
|
const vectorMetadataExists = (0, import_fs12.existsSync)(vectorMetadataPath);
|
|
@@ -11927,10 +12920,10 @@ var Indexer = class _Indexer {
|
|
|
11927
12920
|
});
|
|
11928
12921
|
this.provider = createEmbeddingProvider(this.configuredProviderInfo);
|
|
11929
12922
|
const dimensions = this.configuredProviderInfo.modelInfo.dimensions;
|
|
11930
|
-
const storePath =
|
|
12923
|
+
const storePath = path20.join(this.indexPath, "vectors");
|
|
11931
12924
|
const vectorMetadataPath = `${storePath}.meta.json`;
|
|
11932
|
-
const invertedIndexPath =
|
|
11933
|
-
const dbPath =
|
|
12925
|
+
const invertedIndexPath = path20.join(this.indexPath, "inverted-index.json");
|
|
12926
|
+
const dbPath = path20.join(this.indexPath, "codebase.db");
|
|
11934
12927
|
let dbIsNew = !(0, import_fs12.existsSync)(dbPath);
|
|
11935
12928
|
const readerArtifactFingerprint = mode === "reader" ? this.captureReaderArtifactFingerprint() : null;
|
|
11936
12929
|
if (mode === "writer") {
|
|
@@ -12108,7 +13101,7 @@ var Indexer = class _Indexer {
|
|
|
12108
13101
|
if (await this.tryResetCorruptedIndex("running automatic orphan garbage collection", error)) {
|
|
12109
13102
|
return {
|
|
12110
13103
|
resetCorruptedIndex: true,
|
|
12111
|
-
warning: this.getCorruptedIndexWarning(
|
|
13104
|
+
warning: this.getCorruptedIndexWarning(path20.join(this.indexPath, "codebase.db"))
|
|
12112
13105
|
};
|
|
12113
13106
|
}
|
|
12114
13107
|
throw error;
|
|
@@ -12123,7 +13116,7 @@ var Indexer = class _Indexer {
|
|
|
12123
13116
|
return;
|
|
12124
13117
|
}
|
|
12125
13118
|
const retainedEntries = store.getAllMetadata().filter(({ key }) => !excludedSet.has(key));
|
|
12126
|
-
const storeBasePath =
|
|
13119
|
+
const storeBasePath = path20.join(this.indexPath, "vectors");
|
|
12127
13120
|
const storeIndexPath = storeBasePath;
|
|
12128
13121
|
const storeMetadataPath = `${storeBasePath}.meta.json`;
|
|
12129
13122
|
const lease = this.requireActiveLease();
|
|
@@ -12210,7 +13203,7 @@ var Indexer = class _Indexer {
|
|
|
12210
13203
|
const names = await import_fs12.promises.readdir(this.indexPath);
|
|
12211
13204
|
const runtimeStatePattern = /^(?:file-hashes|failed-batches)(?:\.[a-f0-9]{16})?\.json$/;
|
|
12212
13205
|
await Promise.all(
|
|
12213
|
-
names.filter((name) => runtimeStatePattern.test(name)).map((name) => import_fs12.promises.rm(
|
|
13206
|
+
names.filter((name) => runtimeStatePattern.test(name)).map((name) => import_fs12.promises.rm(path20.join(this.indexPath, name), { force: true }))
|
|
12214
13207
|
);
|
|
12215
13208
|
}
|
|
12216
13209
|
async resetLocalIndexArtifacts() {
|
|
@@ -12226,13 +13219,13 @@ var Indexer = class _Indexer {
|
|
|
12226
13219
|
this.readerArtifactRetryAfter.clear();
|
|
12227
13220
|
this.fileHashCache.clear();
|
|
12228
13221
|
const resetPaths = [
|
|
12229
|
-
|
|
12230
|
-
|
|
12231
|
-
|
|
12232
|
-
|
|
12233
|
-
|
|
12234
|
-
|
|
12235
|
-
|
|
13222
|
+
path20.join(this.indexPath, "codebase.db"),
|
|
13223
|
+
path20.join(this.indexPath, "codebase.db-shm"),
|
|
13224
|
+
path20.join(this.indexPath, "codebase.db-wal"),
|
|
13225
|
+
path20.join(this.indexPath, "vectors"),
|
|
13226
|
+
path20.join(this.indexPath, "vectors.usearch"),
|
|
13227
|
+
path20.join(this.indexPath, "vectors.meta.json"),
|
|
13228
|
+
path20.join(this.indexPath, "inverted-index.json")
|
|
12236
13229
|
];
|
|
12237
13230
|
await Promise.all(resetPaths.map((targetPath) => import_fs12.promises.rm(targetPath, { recursive: true, force: true })));
|
|
12238
13231
|
await this.removeProjectRuntimeStateArtifacts();
|
|
@@ -12242,7 +13235,7 @@ var Indexer = class _Indexer {
|
|
|
12242
13235
|
if (!isSqliteCorruptionError(error)) {
|
|
12243
13236
|
return false;
|
|
12244
13237
|
}
|
|
12245
|
-
const dbPath =
|
|
13238
|
+
const dbPath = path20.join(this.indexPath, "codebase.db");
|
|
12246
13239
|
const warning = this.getCorruptedIndexWarning(dbPath);
|
|
12247
13240
|
const errorMessage = getErrorMessage4(error);
|
|
12248
13241
|
if (this.config.scope === "global") {
|
|
@@ -12629,10 +13622,10 @@ var Indexer = class _Indexer {
|
|
|
12629
13622
|
const reparseCachedMetalFiles = database.getMetadata(metalParserMetadataKey) !== METAL_PARSER_VERSION;
|
|
12630
13623
|
const symbolExtractorMetadataKey = this.getSymbolExtractorVersionMetadataKey();
|
|
12631
13624
|
const refreshCachedSymbols = database.getMetadata(symbolExtractorMetadataKey) !== SYMBOL_EXTRACTOR_VERSION;
|
|
12632
|
-
if (reparseCachedSwiftFiles && Array.from(this.fileHashCache.keys()).some((filePath) =>
|
|
13625
|
+
if (reparseCachedSwiftFiles && Array.from(this.fileHashCache.keys()).some((filePath) => path20.extname(filePath).toLowerCase() === ".swift")) {
|
|
12633
13626
|
this.logger.info("Reindexing cached Swift files for parser support");
|
|
12634
13627
|
}
|
|
12635
|
-
if (reparseCachedMetalFiles && Array.from(this.fileHashCache.keys()).some((filePath) =>
|
|
13628
|
+
if (reparseCachedMetalFiles && Array.from(this.fileHashCache.keys()).some((filePath) => path20.extname(filePath).toLowerCase() === ".metal")) {
|
|
12636
13629
|
this.logger.info("Reindexing cached Metal files for parser support");
|
|
12637
13630
|
}
|
|
12638
13631
|
const includePatterns = [...this.config.include, ...this.config.additionalInclude];
|
|
@@ -12676,8 +13669,8 @@ var Indexer = class _Indexer {
|
|
|
12676
13669
|
const needsCallGraphRefresh = cachedHashMatches && needsCallGraphResolutionMigration && database.getChunksByFile(storedPath).some(
|
|
12677
13670
|
(chunk) => chunk.language === "php" || chunk.language === "c" || chunk.language === "cpp"
|
|
12678
13671
|
);
|
|
12679
|
-
const requiresSwiftParserUpgrade = reparseCachedSwiftFiles &&
|
|
12680
|
-
const requiresMetalParserUpgrade = reparseCachedMetalFiles &&
|
|
13672
|
+
const requiresSwiftParserUpgrade = reparseCachedSwiftFiles && path20.extname(storedPath).toLowerCase() === ".swift";
|
|
13673
|
+
const requiresMetalParserUpgrade = reparseCachedMetalFiles && path20.extname(storedPath).toLowerCase() === ".metal";
|
|
12681
13674
|
const inMigrationScope = forceScopedReembed && scopedRoots !== null && this.isFileInCurrentScope(storedPath, scopedRoots);
|
|
12682
13675
|
if (cachedHashMatches && !inMigrationScope && !needsCallGraphRefresh && !requiresSwiftParserUpgrade && !requiresMetalParserUpgrade && !refreshCachedSymbols) {
|
|
12683
13676
|
unchangedFilePaths.add(storedPath);
|
|
@@ -12736,7 +13729,7 @@ var Indexer = class _Indexer {
|
|
|
12736
13729
|
}
|
|
12737
13730
|
}
|
|
12738
13731
|
}
|
|
12739
|
-
const shouldRetryFailedPath = (filePath) => filePath !== null && currentFileHashes.has(filePath) && unchangedFilePaths.has(filePath);
|
|
13732
|
+
const shouldRetryFailedPath = (filePath) => filePath !== null && !this.isStoredPathExcluded(filePath) && currentFileHashes.has(filePath) && unchangedFilePaths.has(filePath);
|
|
12740
13733
|
const failedProcessing = this.prepareFailedBatchProcessing(scopedRoots, shouldRetryFailedPath);
|
|
12741
13734
|
const maxChunkTokens = getSafeEmbeddingChunkTokenLimit(configuredProviderInfo);
|
|
12742
13735
|
const providerRateLimits = this.getProviderRateLimits(configuredProviderInfo.provider);
|
|
@@ -12840,7 +13833,7 @@ var Indexer = class _Indexer {
|
|
|
12840
13833
|
throw new Error(`Parsed file was not present in its source batch: ${parsed.path}`);
|
|
12841
13834
|
}
|
|
12842
13835
|
if (parsed.chunks.length === 0) {
|
|
12843
|
-
stats.parseFailures.push(
|
|
13836
|
+
stats.parseFailures.push(path20.isAbsolute(parsed.path) ? path20.relative(this.projectRoot, parsed.path) : parsed.path);
|
|
12844
13837
|
}
|
|
12845
13838
|
let chunksToProcess = parsed.chunks;
|
|
12846
13839
|
if (this.config.indexing.fallbackToTextOnMaxChunks && chunksToProcess.length > this.config.indexing.maxChunksPerFile) {
|
|
@@ -13175,7 +14168,7 @@ var Indexer = class _Indexer {
|
|
|
13175
14168
|
previousBranchSymbolIds,
|
|
13176
14169
|
Array.from(allSymbolIds)
|
|
13177
14170
|
);
|
|
13178
|
-
const vectorPath =
|
|
14171
|
+
const vectorPath = path20.join(this.indexPath, "vectors");
|
|
13179
14172
|
const shouldFingerprintLegacyPair = !store.hasFingerprint() && (0, import_fs12.existsSync)(vectorPath) && (0, import_fs12.existsSync)(`${vectorPath}.meta.json`);
|
|
13180
14173
|
if (backfilledBlameMetadata || shouldFingerprintLegacyPair || removedStoredChunks) {
|
|
13181
14174
|
store.save();
|
|
@@ -14034,7 +15027,7 @@ var Indexer = class _Indexer {
|
|
|
14034
15027
|
gcOrphanSymbols: 0,
|
|
14035
15028
|
gcOrphanCallEdges: 0,
|
|
14036
15029
|
resetCorruptedIndex: true,
|
|
14037
|
-
warning: this.getCorruptedIndexWarning(
|
|
15030
|
+
warning: this.getCorruptedIndexWarning(path20.join(this.indexPath, "codebase.db"))
|
|
14038
15031
|
};
|
|
14039
15032
|
}
|
|
14040
15033
|
this.logger.recordGc(removedCount, gcOrphanChunks, gcOrphanEmbeddings);
|
|
@@ -14064,7 +15057,8 @@ var Indexer = class _Indexer {
|
|
|
14064
15057
|
const maxChunkTokens = getSafeEmbeddingChunkTokenLimit(configuredProviderInfo);
|
|
14065
15058
|
const providerRateLimits = this.getProviderRateLimits(configuredProviderInfo.provider);
|
|
14066
15059
|
const roots = this.config.scope === "global" ? this.getScopedRoots() : null;
|
|
14067
|
-
const
|
|
15060
|
+
const shouldProcessFailedPath = (filePath) => filePath === null || !this.isStoredPathExcluded(filePath);
|
|
15061
|
+
const failedProcessing = this.prepareFailedBatchProcessing(roots, shouldProcessFailedPath);
|
|
14068
15062
|
if (failedProcessing.latestById.size === 0) {
|
|
14069
15063
|
this.finalizeFailedBatchWriteState(failedProcessing.state);
|
|
14070
15064
|
return { succeeded: 0, failed: 0, remaining: 0 };
|
|
@@ -14077,7 +15071,7 @@ var Indexer = class _Indexer {
|
|
|
14077
15071
|
const retryableChunks = this.iterateLatestFailedChunks(
|
|
14078
15072
|
failedProcessing.latestById,
|
|
14079
15073
|
roots,
|
|
14080
|
-
|
|
15074
|
+
shouldProcessFailedPath,
|
|
14081
15075
|
maxChunkTokens
|
|
14082
15076
|
);
|
|
14083
15077
|
for (const retryBatch of iterateOrderedFileBatches(
|
|
@@ -14347,9 +15341,9 @@ var Indexer = class _Indexer {
|
|
|
14347
15341
|
this.requireReadableComponents(readIssues, "database");
|
|
14348
15342
|
let shortest = [];
|
|
14349
15343
|
for (const branchKey of this.getBranchCatalogKeys()) {
|
|
14350
|
-
const
|
|
14351
|
-
if (
|
|
14352
|
-
shortest =
|
|
15344
|
+
const path31 = database.findShortestPath(fromName, toName, branchKey, maxDepth);
|
|
15345
|
+
if (path31.length > 0 && (shortest.length === 0 || path31.length < shortest.length)) {
|
|
15346
|
+
shortest = path31;
|
|
14353
15347
|
}
|
|
14354
15348
|
}
|
|
14355
15349
|
return shortest.map((hop) => this.resolveFilePathRecord(hop));
|
|
@@ -14397,13 +15391,13 @@ var Indexer = class _Indexer {
|
|
|
14397
15391
|
}
|
|
14398
15392
|
}
|
|
14399
15393
|
if (!found) continue;
|
|
14400
|
-
const
|
|
15394
|
+
const path31 = [];
|
|
14401
15395
|
let currentSymbolId = toSymbolId;
|
|
14402
15396
|
while (true) {
|
|
14403
15397
|
const symbol = symbolsById.get(currentSymbolId);
|
|
14404
15398
|
if (!symbol) break;
|
|
14405
15399
|
const parent = parentBySymbolId.get(currentSymbolId);
|
|
14406
|
-
|
|
15400
|
+
path31.push({
|
|
14407
15401
|
symbolId: symbol.id,
|
|
14408
15402
|
symbolName: symbol.name,
|
|
14409
15403
|
filePath: symbol.filePath,
|
|
@@ -14413,9 +15407,9 @@ var Indexer = class _Indexer {
|
|
|
14413
15407
|
if (!parent) break;
|
|
14414
15408
|
currentSymbolId = parent.parentId;
|
|
14415
15409
|
}
|
|
14416
|
-
|
|
14417
|
-
if (
|
|
14418
|
-
shortest =
|
|
15410
|
+
path31.reverse();
|
|
15411
|
+
if (path31.length > 0 && (shortest.length === 0 || path31.length < shortest.length)) {
|
|
15412
|
+
shortest = path31;
|
|
14419
15413
|
}
|
|
14420
15414
|
}
|
|
14421
15415
|
return shortest.map((hop) => this.resolveFilePathRecord(hop));
|
|
@@ -14566,7 +15560,7 @@ var Indexer = class _Indexer {
|
|
|
14566
15560
|
);
|
|
14567
15561
|
}
|
|
14568
15562
|
}
|
|
14569
|
-
const toStoredChangedFiles = (filePaths) => filePaths.map((filePath) => this.toStoredFilePath(
|
|
15563
|
+
const toStoredChangedFiles = (filePaths) => filePaths.map((filePath) => this.toStoredFilePath(path20.resolve(this.projectRoot, filePath)));
|
|
14570
15564
|
const storedChangedFiles = toStoredChangedFiles(changedFiles);
|
|
14571
15565
|
const directSymbols = database.getSymbolsForFiles(storedChangedFiles, branchKey);
|
|
14572
15566
|
const directIds = directSymbols.map((s) => s.id);
|
|
@@ -14715,12 +15709,12 @@ var Indexer = class _Indexer {
|
|
|
14715
15709
|
if (meta.filePath) filePaths.add(meta.filePath);
|
|
14716
15710
|
}
|
|
14717
15711
|
const directory = options?.directory?.replace(/\/$/, "");
|
|
14718
|
-
const absoluteDirectoryFilter = directory ?
|
|
15712
|
+
const absoluteDirectoryFilter = directory ? path20.resolve(this.projectRoot, directory) : void 0;
|
|
14719
15713
|
for (const filePath of filePaths) {
|
|
14720
15714
|
if (directory) {
|
|
14721
15715
|
const absoluteFilePath = this.resolveStoredFilePath(filePath);
|
|
14722
15716
|
const matchesRelative = filePath === directory || filePath.startsWith(directory + "/");
|
|
14723
|
-
const matchesProjectRelative = absoluteDirectoryFilter !== void 0 && (absoluteFilePath === absoluteDirectoryFilter || absoluteFilePath.startsWith(absoluteDirectoryFilter +
|
|
15717
|
+
const matchesProjectRelative = absoluteDirectoryFilter !== void 0 && (absoluteFilePath === absoluteDirectoryFilter || absoluteFilePath.startsWith(absoluteDirectoryFilter + path20.sep));
|
|
14724
15718
|
if (!matchesRelative && !matchesProjectRelative) {
|
|
14725
15719
|
continue;
|
|
14726
15720
|
}
|
|
@@ -14837,15 +15831,24 @@ function getOrCreateIndexer(projectRoot, host) {
|
|
|
14837
15831
|
}
|
|
14838
15832
|
const indexer = new Indexer(projectRoot, config, host);
|
|
14839
15833
|
indexerCache.set(key, indexer);
|
|
14840
|
-
configureAutoIndex(projectRoot, host, config, () => getOrCreateIndexer(projectRoot, host)
|
|
15834
|
+
configureAutoIndex(projectRoot, host, config, () => getOrCreateIndexer(projectRoot, host), {
|
|
15835
|
+
preserveManagedWorker: true,
|
|
15836
|
+
synchronizeBackgroundWorker: false
|
|
15837
|
+
});
|
|
14841
15838
|
return indexer;
|
|
14842
15839
|
}
|
|
14843
|
-
function initializeTools(projectRoot, config, host) {
|
|
15840
|
+
function initializeTools(projectRoot, config, host, options = {}) {
|
|
14844
15841
|
defaultProjectRoots.set(host, projectRoot);
|
|
14845
15842
|
const key = getIndexerCacheKey(projectRoot, host);
|
|
15843
|
+
if (options.preserveManagedWorker === true && isBackgroundWorkerManaged(projectRoot, host) && indexerCache.has(key)) {
|
|
15844
|
+
return;
|
|
15845
|
+
}
|
|
14846
15846
|
configCache.set(key, config);
|
|
14847
15847
|
indexerCache.set(key, new Indexer(projectRoot, config, host));
|
|
14848
|
-
configureAutoIndex(projectRoot, host, config, () => getOrCreateIndexer(projectRoot, host)
|
|
15848
|
+
configureAutoIndex(projectRoot, host, config, () => getOrCreateIndexer(projectRoot, host), {
|
|
15849
|
+
preserveManagedWorker: options.preserveManagedWorker,
|
|
15850
|
+
synchronizeBackgroundWorker: false
|
|
15851
|
+
});
|
|
14849
15852
|
}
|
|
14850
15853
|
function getIndexerForProject(projectRoot, host) {
|
|
14851
15854
|
const root = getProjectRoot(projectRoot, host);
|
|
@@ -14859,7 +15862,9 @@ function refreshIndexerForDirectory(projectRoot, host, config = parseConfig(load
|
|
|
14859
15862
|
const key = getIndexerCacheKey(projectRoot, host);
|
|
14860
15863
|
configCache.set(key, config);
|
|
14861
15864
|
indexerCache.set(key, new Indexer(projectRoot, config, host));
|
|
14862
|
-
configureAutoIndex(projectRoot, host, config, () => getOrCreateIndexer(projectRoot, host)
|
|
15865
|
+
configureAutoIndex(projectRoot, host, config, () => getOrCreateIndexer(projectRoot, host), {
|
|
15866
|
+
synchronizeBackgroundWorker: true
|
|
15867
|
+
});
|
|
14863
15868
|
return config;
|
|
14864
15869
|
}
|
|
14865
15870
|
var AutoIndexRetrievalUnavailableError = class extends Error {
|
|
@@ -14886,7 +15891,7 @@ function trimOrUndefined(value) {
|
|
|
14886
15891
|
return normalized || void 0;
|
|
14887
15892
|
}
|
|
14888
15893
|
function normalizeCallGraphPath(value) {
|
|
14889
|
-
let normalized =
|
|
15894
|
+
let normalized = path21.posix.normalize(value.trim().replaceAll("\\", "/"));
|
|
14890
15895
|
if (normalized.startsWith("./")) {
|
|
14891
15896
|
normalized = normalized.slice(2);
|
|
14892
15897
|
}
|
|
@@ -15079,12 +16084,12 @@ async function getCallGraphPath(projectRoot, host, from, to, maxDepth, fromFileP
|
|
|
15079
16084
|
if (fromResolution.status !== "resolved" || toResolution.status !== "resolved") {
|
|
15080
16085
|
return { from: fromResolution, to: toResolution, path: [] };
|
|
15081
16086
|
}
|
|
15082
|
-
const
|
|
16087
|
+
const path31 = await indexer.findCallPathBySymbolIds(
|
|
15083
16088
|
fromResolution.symbolId,
|
|
15084
16089
|
toResolution.symbolId,
|
|
15085
16090
|
maxDepth
|
|
15086
16091
|
);
|
|
15087
|
-
return { from: fromResolution, to: toResolution, path:
|
|
16092
|
+
return { from: fromResolution, to: toResolution, path: path31 };
|
|
15088
16093
|
}
|
|
15089
16094
|
async function runIndexCodebase(projectRoot, host, args, onProgress) {
|
|
15090
16095
|
const root = getProjectRoot(projectRoot, host);
|
|
@@ -15270,8 +16275,8 @@ async function getIndexLogs(projectRoot, host, args) {
|
|
|
15270
16275
|
function addKnowledgeBase(projectRoot, host, knowledgeBasePath) {
|
|
15271
16276
|
const root = getProjectRoot(projectRoot, host);
|
|
15272
16277
|
const inputPath = knowledgeBasePath.trim();
|
|
15273
|
-
const normalizedPath2 =
|
|
15274
|
-
|
|
16278
|
+
const normalizedPath2 = path21.resolve(
|
|
16279
|
+
path21.isAbsolute(inputPath) ? inputPath : resolveKnowledgeBasePath(inputPath, root)
|
|
15275
16280
|
);
|
|
15276
16281
|
if (!(0, import_fs13.existsSync)(normalizedPath2)) {
|
|
15277
16282
|
return `Error: Directory does not exist: ${normalizedPath2}`;
|
|
@@ -15307,7 +16312,7 @@ function addKnowledgeBase(projectRoot, host, knowledgeBasePath) {
|
|
|
15307
16312
|
}
|
|
15308
16313
|
}
|
|
15309
16314
|
for (const dotDir of sensitiveDotDirs) {
|
|
15310
|
-
const sensitiveDir =
|
|
16315
|
+
const sensitiveDir = path21.join(homeDir, dotDir);
|
|
15311
16316
|
if (sensitiveDir && (realPath === sensitiveDir || realPath.startsWith(`${sensitiveDir}/`))) {
|
|
15312
16317
|
return `Error: Adding sensitive directory as knowledge base is not allowed: ${normalizedPath2}`;
|
|
15313
16318
|
}
|
|
@@ -15370,7 +16375,7 @@ function listKnowledgeBases(projectRoot, host) {
|
|
|
15370
16375
|
}
|
|
15371
16376
|
result += "\n";
|
|
15372
16377
|
}
|
|
15373
|
-
const hasHostConfig = (0, import_fs13.existsSync)(
|
|
16378
|
+
const hasHostConfig = (0, import_fs13.existsSync)(path21.join(root, getHostProjectConfigRelativePath(host)));
|
|
15374
16379
|
if (hasHostConfig) {
|
|
15375
16380
|
result += `
|
|
15376
16381
|
Config sources: 1 file(s).`;
|
|
@@ -15408,7 +16413,7 @@ var import_fs14 = require("fs");
|
|
|
15408
16413
|
|
|
15409
16414
|
// node_modules/chokidar/index.js
|
|
15410
16415
|
var import_node_events = require("events");
|
|
15411
|
-
var
|
|
16416
|
+
var import_node_fs3 = require("fs");
|
|
15412
16417
|
var import_promises3 = require("fs/promises");
|
|
15413
16418
|
var sp2 = __toESM(require("path"), 1);
|
|
15414
16419
|
|
|
@@ -15496,7 +16501,7 @@ var ReaddirpStream = class extends import_node_stream.Readable {
|
|
|
15496
16501
|
this._directoryFilter = normalizeFilter(opts.directoryFilter);
|
|
15497
16502
|
const statMethod = opts.lstat ? import_promises.lstat : import_promises.stat;
|
|
15498
16503
|
if (wantBigintFsStats) {
|
|
15499
|
-
this._stat = (
|
|
16504
|
+
this._stat = (path31) => statMethod(path31, { bigint: true });
|
|
15500
16505
|
} else {
|
|
15501
16506
|
this._stat = statMethod;
|
|
15502
16507
|
}
|
|
@@ -15521,8 +16526,8 @@ var ReaddirpStream = class extends import_node_stream.Readable {
|
|
|
15521
16526
|
const par = this.parent;
|
|
15522
16527
|
const fil = par && par.files;
|
|
15523
16528
|
if (fil && fil.length > 0) {
|
|
15524
|
-
const { path:
|
|
15525
|
-
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent,
|
|
16529
|
+
const { path: path31, depth } = par;
|
|
16530
|
+
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path31));
|
|
15526
16531
|
const awaited = await Promise.all(slice);
|
|
15527
16532
|
for (const entry of awaited) {
|
|
15528
16533
|
if (!entry)
|
|
@@ -15562,21 +16567,21 @@ var ReaddirpStream = class extends import_node_stream.Readable {
|
|
|
15562
16567
|
this.reading = false;
|
|
15563
16568
|
}
|
|
15564
16569
|
}
|
|
15565
|
-
async _exploreDir(
|
|
16570
|
+
async _exploreDir(path31, depth) {
|
|
15566
16571
|
let files;
|
|
15567
16572
|
try {
|
|
15568
|
-
files = await (0, import_promises.readdir)(
|
|
16573
|
+
files = await (0, import_promises.readdir)(path31, this._rdOptions);
|
|
15569
16574
|
} catch (error) {
|
|
15570
16575
|
this._onError(error);
|
|
15571
16576
|
}
|
|
15572
|
-
return { files, depth, path:
|
|
16577
|
+
return { files, depth, path: path31 };
|
|
15573
16578
|
}
|
|
15574
|
-
async _formatEntry(dirent,
|
|
16579
|
+
async _formatEntry(dirent, path31) {
|
|
15575
16580
|
let entry;
|
|
15576
|
-
const
|
|
16581
|
+
const basename10 = this._isDirent ? dirent.name : dirent;
|
|
15577
16582
|
try {
|
|
15578
|
-
const fullPath = (0, import_node_path.resolve)((0, import_node_path.join)(
|
|
15579
|
-
entry = { path: (0, import_node_path.relative)(this._root, fullPath), fullPath, basename:
|
|
16583
|
+
const fullPath = (0, import_node_path.resolve)((0, import_node_path.join)(path31, basename10));
|
|
16584
|
+
entry = { path: (0, import_node_path.relative)(this._root, fullPath), fullPath, basename: basename10 };
|
|
15580
16585
|
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
15581
16586
|
} catch (err) {
|
|
15582
16587
|
this._onError(err);
|
|
@@ -15646,7 +16651,7 @@ function readdirp(root, options = {}) {
|
|
|
15646
16651
|
}
|
|
15647
16652
|
|
|
15648
16653
|
// node_modules/chokidar/handler.js
|
|
15649
|
-
var
|
|
16654
|
+
var import_node_fs2 = require("fs");
|
|
15650
16655
|
var import_promises2 = require("fs/promises");
|
|
15651
16656
|
var import_node_os = require("os");
|
|
15652
16657
|
var sp = __toESM(require("path"), 1);
|
|
@@ -15975,16 +16980,16 @@ var delFromSet = (main, prop, item) => {
|
|
|
15975
16980
|
};
|
|
15976
16981
|
var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
|
|
15977
16982
|
var FsWatchInstances = /* @__PURE__ */ new Map();
|
|
15978
|
-
function createFsWatchInstance(
|
|
16983
|
+
function createFsWatchInstance(path31, options, listener, errHandler, emitRaw) {
|
|
15979
16984
|
const handleEvent = (rawEvent, evPath) => {
|
|
15980
|
-
listener(
|
|
15981
|
-
emitRaw(rawEvent, evPath, { watchedPath:
|
|
15982
|
-
if (evPath &&
|
|
15983
|
-
fsWatchBroadcast(sp.resolve(
|
|
16985
|
+
listener(path31);
|
|
16986
|
+
emitRaw(rawEvent, evPath, { watchedPath: path31 });
|
|
16987
|
+
if (evPath && path31 !== evPath) {
|
|
16988
|
+
fsWatchBroadcast(sp.resolve(path31, evPath), KEY_LISTENERS, sp.join(path31, evPath));
|
|
15984
16989
|
}
|
|
15985
16990
|
};
|
|
15986
16991
|
try {
|
|
15987
|
-
return (0,
|
|
16992
|
+
return (0, import_node_fs2.watch)(path31, {
|
|
15988
16993
|
persistent: options.persistent
|
|
15989
16994
|
}, handleEvent);
|
|
15990
16995
|
} catch (error) {
|
|
@@ -16000,12 +17005,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
|
|
|
16000
17005
|
listener(val1, val2, val3);
|
|
16001
17006
|
});
|
|
16002
17007
|
};
|
|
16003
|
-
var setFsWatchListener = (
|
|
17008
|
+
var setFsWatchListener = (path31, fullPath, options, handlers) => {
|
|
16004
17009
|
const { listener, errHandler, rawEmitter } = handlers;
|
|
16005
17010
|
let cont = FsWatchInstances.get(fullPath);
|
|
16006
17011
|
let watcher;
|
|
16007
17012
|
if (!options.persistent) {
|
|
16008
|
-
watcher = createFsWatchInstance(
|
|
17013
|
+
watcher = createFsWatchInstance(path31, options, listener, errHandler, rawEmitter);
|
|
16009
17014
|
if (!watcher)
|
|
16010
17015
|
return;
|
|
16011
17016
|
return watcher.close.bind(watcher);
|
|
@@ -16016,7 +17021,7 @@ var setFsWatchListener = (path30, fullPath, options, handlers) => {
|
|
|
16016
17021
|
addAndConvert(cont, KEY_RAW, rawEmitter);
|
|
16017
17022
|
} else {
|
|
16018
17023
|
watcher = createFsWatchInstance(
|
|
16019
|
-
|
|
17024
|
+
path31,
|
|
16020
17025
|
options,
|
|
16021
17026
|
fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
|
|
16022
17027
|
errHandler,
|
|
@@ -16031,7 +17036,7 @@ var setFsWatchListener = (path30, fullPath, options, handlers) => {
|
|
|
16031
17036
|
cont.watcherUnusable = true;
|
|
16032
17037
|
if (isWindows && error.code === "EPERM") {
|
|
16033
17038
|
try {
|
|
16034
|
-
const fd = await (0, import_promises2.open)(
|
|
17039
|
+
const fd = await (0, import_promises2.open)(path31, "r");
|
|
16035
17040
|
await fd.close();
|
|
16036
17041
|
broadcastErr(error);
|
|
16037
17042
|
} catch (err) {
|
|
@@ -16062,12 +17067,12 @@ var setFsWatchListener = (path30, fullPath, options, handlers) => {
|
|
|
16062
17067
|
};
|
|
16063
17068
|
};
|
|
16064
17069
|
var FsWatchFileInstances = /* @__PURE__ */ new Map();
|
|
16065
|
-
var setFsWatchFileListener = (
|
|
17070
|
+
var setFsWatchFileListener = (path31, fullPath, options, handlers) => {
|
|
16066
17071
|
const { listener, rawEmitter } = handlers;
|
|
16067
17072
|
let cont = FsWatchFileInstances.get(fullPath);
|
|
16068
17073
|
const copts = cont && cont.options;
|
|
16069
17074
|
if (copts && (copts.persistent < options.persistent || copts.interval > options.interval)) {
|
|
16070
|
-
(0,
|
|
17075
|
+
(0, import_node_fs2.unwatchFile)(fullPath);
|
|
16071
17076
|
cont = void 0;
|
|
16072
17077
|
}
|
|
16073
17078
|
if (cont) {
|
|
@@ -16078,13 +17083,13 @@ var setFsWatchFileListener = (path30, fullPath, options, handlers) => {
|
|
|
16078
17083
|
listeners: listener,
|
|
16079
17084
|
rawEmitters: rawEmitter,
|
|
16080
17085
|
options,
|
|
16081
|
-
watcher: (0,
|
|
17086
|
+
watcher: (0, import_node_fs2.watchFile)(fullPath, options, (curr, prev) => {
|
|
16082
17087
|
foreach(cont.rawEmitters, (rawEmitter2) => {
|
|
16083
17088
|
rawEmitter2(EV.CHANGE, fullPath, { curr, prev });
|
|
16084
17089
|
});
|
|
16085
17090
|
const currmtime = curr.mtimeMs;
|
|
16086
17091
|
if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
|
|
16087
|
-
foreach(cont.listeners, (listener2) => listener2(
|
|
17092
|
+
foreach(cont.listeners, (listener2) => listener2(path31, curr));
|
|
16088
17093
|
}
|
|
16089
17094
|
})
|
|
16090
17095
|
};
|
|
@@ -16095,7 +17100,7 @@ var setFsWatchFileListener = (path30, fullPath, options, handlers) => {
|
|
|
16095
17100
|
delFromSet(cont, KEY_RAW, rawEmitter);
|
|
16096
17101
|
if (isEmptySet(cont.listeners)) {
|
|
16097
17102
|
FsWatchFileInstances.delete(fullPath);
|
|
16098
|
-
(0,
|
|
17103
|
+
(0, import_node_fs2.unwatchFile)(fullPath);
|
|
16099
17104
|
cont.options = cont.watcher = void 0;
|
|
16100
17105
|
Object.freeze(cont);
|
|
16101
17106
|
}
|
|
@@ -16114,13 +17119,13 @@ var NodeFsHandler = class {
|
|
|
16114
17119
|
* @param listener on fs change
|
|
16115
17120
|
* @returns closer for the watcher instance
|
|
16116
17121
|
*/
|
|
16117
|
-
_watchWithNodeFs(
|
|
17122
|
+
_watchWithNodeFs(path31, listener) {
|
|
16118
17123
|
const opts = this.fsw.options;
|
|
16119
|
-
const directory = sp.dirname(
|
|
16120
|
-
const
|
|
17124
|
+
const directory = sp.dirname(path31);
|
|
17125
|
+
const basename10 = sp.basename(path31);
|
|
16121
17126
|
const parent = this.fsw._getWatchedDir(directory);
|
|
16122
|
-
parent.add(
|
|
16123
|
-
const absolutePath = sp.resolve(
|
|
17127
|
+
parent.add(basename10);
|
|
17128
|
+
const absolutePath = sp.resolve(path31);
|
|
16124
17129
|
const options = {
|
|
16125
17130
|
persistent: opts.persistent
|
|
16126
17131
|
};
|
|
@@ -16129,13 +17134,13 @@ var NodeFsHandler = class {
|
|
|
16129
17134
|
let closer;
|
|
16130
17135
|
if (opts.usePolling) {
|
|
16131
17136
|
const enableBin = opts.interval !== opts.binaryInterval;
|
|
16132
|
-
options.interval = enableBin && isBinaryPath(
|
|
16133
|
-
closer = setFsWatchFileListener(
|
|
17137
|
+
options.interval = enableBin && isBinaryPath(basename10) ? opts.binaryInterval : opts.interval;
|
|
17138
|
+
closer = setFsWatchFileListener(path31, absolutePath, options, {
|
|
16134
17139
|
listener,
|
|
16135
17140
|
rawEmitter: this.fsw._emitRaw
|
|
16136
17141
|
});
|
|
16137
17142
|
} else {
|
|
16138
|
-
closer = setFsWatchListener(
|
|
17143
|
+
closer = setFsWatchListener(path31, absolutePath, options, {
|
|
16139
17144
|
listener,
|
|
16140
17145
|
errHandler: this._boundHandleError,
|
|
16141
17146
|
rawEmitter: this.fsw._emitRaw
|
|
@@ -16151,13 +17156,13 @@ var NodeFsHandler = class {
|
|
|
16151
17156
|
if (this.fsw.closed) {
|
|
16152
17157
|
return;
|
|
16153
17158
|
}
|
|
16154
|
-
const
|
|
16155
|
-
const
|
|
16156
|
-
const parent = this.fsw._getWatchedDir(
|
|
17159
|
+
const dirname16 = sp.dirname(file);
|
|
17160
|
+
const basename10 = sp.basename(file);
|
|
17161
|
+
const parent = this.fsw._getWatchedDir(dirname16);
|
|
16157
17162
|
let prevStats = stats;
|
|
16158
|
-
if (parent.has(
|
|
17163
|
+
if (parent.has(basename10))
|
|
16159
17164
|
return;
|
|
16160
|
-
const listener = async (
|
|
17165
|
+
const listener = async (path31, newStats) => {
|
|
16161
17166
|
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
|
|
16162
17167
|
return;
|
|
16163
17168
|
if (!newStats || newStats.mtimeMs === 0) {
|
|
@@ -16171,18 +17176,18 @@ var NodeFsHandler = class {
|
|
|
16171
17176
|
this.fsw._emit(EV.CHANGE, file, newStats2);
|
|
16172
17177
|
}
|
|
16173
17178
|
if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
|
|
16174
|
-
this.fsw._closeFile(
|
|
17179
|
+
this.fsw._closeFile(path31);
|
|
16175
17180
|
prevStats = newStats2;
|
|
16176
17181
|
const closer2 = this._watchWithNodeFs(file, listener);
|
|
16177
17182
|
if (closer2)
|
|
16178
|
-
this.fsw._addPathCloser(
|
|
17183
|
+
this.fsw._addPathCloser(path31, closer2);
|
|
16179
17184
|
} else {
|
|
16180
17185
|
prevStats = newStats2;
|
|
16181
17186
|
}
|
|
16182
17187
|
} catch (error) {
|
|
16183
|
-
this.fsw._remove(
|
|
17188
|
+
this.fsw._remove(dirname16, basename10);
|
|
16184
17189
|
}
|
|
16185
|
-
} else if (parent.has(
|
|
17190
|
+
} else if (parent.has(basename10)) {
|
|
16186
17191
|
const at = newStats.atimeMs;
|
|
16187
17192
|
const mt = newStats.mtimeMs;
|
|
16188
17193
|
if (!at || at <= mt || mt !== prevStats.mtimeMs) {
|
|
@@ -16207,7 +17212,7 @@ var NodeFsHandler = class {
|
|
|
16207
17212
|
* @param item basename of this item
|
|
16208
17213
|
* @returns true if no more processing is needed for this entry.
|
|
16209
17214
|
*/
|
|
16210
|
-
async _handleSymlink(entry, directory,
|
|
17215
|
+
async _handleSymlink(entry, directory, path31, item) {
|
|
16211
17216
|
if (this.fsw.closed) {
|
|
16212
17217
|
return;
|
|
16213
17218
|
}
|
|
@@ -16217,7 +17222,7 @@ var NodeFsHandler = class {
|
|
|
16217
17222
|
this.fsw._incrReadyCount();
|
|
16218
17223
|
let linkPath;
|
|
16219
17224
|
try {
|
|
16220
|
-
linkPath = await (0, import_promises2.realpath)(
|
|
17225
|
+
linkPath = await (0, import_promises2.realpath)(path31);
|
|
16221
17226
|
} catch (e) {
|
|
16222
17227
|
this.fsw._emitReady();
|
|
16223
17228
|
return true;
|
|
@@ -16227,12 +17232,12 @@ var NodeFsHandler = class {
|
|
|
16227
17232
|
if (dir.has(item)) {
|
|
16228
17233
|
if (this.fsw._symlinkPaths.get(full) !== linkPath) {
|
|
16229
17234
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
16230
|
-
this.fsw._emit(EV.CHANGE,
|
|
17235
|
+
this.fsw._emit(EV.CHANGE, path31, entry.stats);
|
|
16231
17236
|
}
|
|
16232
17237
|
} else {
|
|
16233
17238
|
dir.add(item);
|
|
16234
17239
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
16235
|
-
this.fsw._emit(EV.ADD,
|
|
17240
|
+
this.fsw._emit(EV.ADD, path31, entry.stats);
|
|
16236
17241
|
}
|
|
16237
17242
|
this.fsw._emitReady();
|
|
16238
17243
|
return true;
|
|
@@ -16262,9 +17267,9 @@ var NodeFsHandler = class {
|
|
|
16262
17267
|
return;
|
|
16263
17268
|
}
|
|
16264
17269
|
const item = entry.path;
|
|
16265
|
-
let
|
|
17270
|
+
let path31 = sp.join(directory, item);
|
|
16266
17271
|
current.add(item);
|
|
16267
|
-
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory,
|
|
17272
|
+
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path31, item)) {
|
|
16268
17273
|
return;
|
|
16269
17274
|
}
|
|
16270
17275
|
if (this.fsw.closed) {
|
|
@@ -16273,11 +17278,11 @@ var NodeFsHandler = class {
|
|
|
16273
17278
|
}
|
|
16274
17279
|
if (item === target || !target && !previous.has(item)) {
|
|
16275
17280
|
this.fsw._incrReadyCount();
|
|
16276
|
-
|
|
16277
|
-
this._addToNodeFs(
|
|
17281
|
+
path31 = sp.join(dir, sp.relative(dir, path31));
|
|
17282
|
+
this._addToNodeFs(path31, initialAdd, wh, depth + 1);
|
|
16278
17283
|
}
|
|
16279
17284
|
}).on(EV.ERROR, this._boundHandleError);
|
|
16280
|
-
return new Promise((
|
|
17285
|
+
return new Promise((resolve18, reject) => {
|
|
16281
17286
|
if (!stream)
|
|
16282
17287
|
return reject();
|
|
16283
17288
|
stream.once(STR_END, () => {
|
|
@@ -16286,7 +17291,7 @@ var NodeFsHandler = class {
|
|
|
16286
17291
|
return;
|
|
16287
17292
|
}
|
|
16288
17293
|
const wasThrottled = throttler ? throttler.clear() : false;
|
|
16289
|
-
|
|
17294
|
+
resolve18(void 0);
|
|
16290
17295
|
previous.getChildren().filter((item) => {
|
|
16291
17296
|
return item !== directory && !current.has(item);
|
|
16292
17297
|
}).forEach((item) => {
|
|
@@ -16343,13 +17348,13 @@ var NodeFsHandler = class {
|
|
|
16343
17348
|
* @param depth Child path actually targeted for watch
|
|
16344
17349
|
* @param target Child path actually targeted for watch
|
|
16345
17350
|
*/
|
|
16346
|
-
async _addToNodeFs(
|
|
17351
|
+
async _addToNodeFs(path31, initialAdd, priorWh, depth, target) {
|
|
16347
17352
|
const ready = this.fsw._emitReady;
|
|
16348
|
-
if (this.fsw._isIgnored(
|
|
17353
|
+
if (this.fsw._isIgnored(path31) || this.fsw.closed) {
|
|
16349
17354
|
ready();
|
|
16350
17355
|
return false;
|
|
16351
17356
|
}
|
|
16352
|
-
const wh = this.fsw._getWatchHelpers(
|
|
17357
|
+
const wh = this.fsw._getWatchHelpers(path31);
|
|
16353
17358
|
if (priorWh) {
|
|
16354
17359
|
wh.filterPath = (entry) => priorWh.filterPath(entry);
|
|
16355
17360
|
wh.filterDir = (entry) => priorWh.filterDir(entry);
|
|
@@ -16365,8 +17370,8 @@ var NodeFsHandler = class {
|
|
|
16365
17370
|
const follow = this.fsw.options.followSymlinks;
|
|
16366
17371
|
let closer;
|
|
16367
17372
|
if (stats.isDirectory()) {
|
|
16368
|
-
const absPath = sp.resolve(
|
|
16369
|
-
const targetPath = follow ? await (0, import_promises2.realpath)(
|
|
17373
|
+
const absPath = sp.resolve(path31);
|
|
17374
|
+
const targetPath = follow ? await (0, import_promises2.realpath)(path31) : path31;
|
|
16370
17375
|
if (this.fsw.closed)
|
|
16371
17376
|
return;
|
|
16372
17377
|
closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
|
|
@@ -16376,29 +17381,29 @@ var NodeFsHandler = class {
|
|
|
16376
17381
|
this.fsw._symlinkPaths.set(absPath, targetPath);
|
|
16377
17382
|
}
|
|
16378
17383
|
} else if (stats.isSymbolicLink()) {
|
|
16379
|
-
const targetPath = follow ? await (0, import_promises2.realpath)(
|
|
17384
|
+
const targetPath = follow ? await (0, import_promises2.realpath)(path31) : path31;
|
|
16380
17385
|
if (this.fsw.closed)
|
|
16381
17386
|
return;
|
|
16382
17387
|
const parent = sp.dirname(wh.watchPath);
|
|
16383
17388
|
this.fsw._getWatchedDir(parent).add(wh.watchPath);
|
|
16384
17389
|
this.fsw._emit(EV.ADD, wh.watchPath, stats);
|
|
16385
|
-
closer = await this._handleDir(parent, stats, initialAdd, depth,
|
|
17390
|
+
closer = await this._handleDir(parent, stats, initialAdd, depth, path31, wh, targetPath);
|
|
16386
17391
|
if (this.fsw.closed)
|
|
16387
17392
|
return;
|
|
16388
17393
|
if (targetPath !== void 0) {
|
|
16389
|
-
this.fsw._symlinkPaths.set(sp.resolve(
|
|
17394
|
+
this.fsw._symlinkPaths.set(sp.resolve(path31), targetPath);
|
|
16390
17395
|
}
|
|
16391
17396
|
} else {
|
|
16392
17397
|
closer = this._handleFile(wh.watchPath, stats, initialAdd);
|
|
16393
17398
|
}
|
|
16394
17399
|
ready();
|
|
16395
17400
|
if (closer)
|
|
16396
|
-
this.fsw._addPathCloser(
|
|
17401
|
+
this.fsw._addPathCloser(path31, closer);
|
|
16397
17402
|
return false;
|
|
16398
17403
|
} catch (error) {
|
|
16399
17404
|
if (this.fsw._handleError(error)) {
|
|
16400
17405
|
ready();
|
|
16401
|
-
return
|
|
17406
|
+
return path31;
|
|
16402
17407
|
}
|
|
16403
17408
|
}
|
|
16404
17409
|
}
|
|
@@ -16441,24 +17446,24 @@ function createPattern(matcher) {
|
|
|
16441
17446
|
}
|
|
16442
17447
|
return () => false;
|
|
16443
17448
|
}
|
|
16444
|
-
function normalizePath2(
|
|
16445
|
-
if (typeof
|
|
17449
|
+
function normalizePath2(path31) {
|
|
17450
|
+
if (typeof path31 !== "string")
|
|
16446
17451
|
throw new Error("string expected");
|
|
16447
|
-
|
|
16448
|
-
|
|
17452
|
+
path31 = sp2.normalize(path31);
|
|
17453
|
+
path31 = path31.replace(/\\/g, "/");
|
|
16449
17454
|
let prepend = false;
|
|
16450
|
-
if (
|
|
17455
|
+
if (path31.startsWith("//"))
|
|
16451
17456
|
prepend = true;
|
|
16452
|
-
|
|
17457
|
+
path31 = path31.replace(DOUBLE_SLASH_RE, "/");
|
|
16453
17458
|
if (prepend)
|
|
16454
|
-
|
|
16455
|
-
return
|
|
17459
|
+
path31 = "/" + path31;
|
|
17460
|
+
return path31;
|
|
16456
17461
|
}
|
|
16457
17462
|
function matchPatterns(patterns, testString, stats) {
|
|
16458
|
-
const
|
|
17463
|
+
const path31 = normalizePath2(testString);
|
|
16459
17464
|
for (let index = 0; index < patterns.length; index++) {
|
|
16460
17465
|
const pattern = patterns[index];
|
|
16461
|
-
if (pattern(
|
|
17466
|
+
if (pattern(path31, stats)) {
|
|
16462
17467
|
return true;
|
|
16463
17468
|
}
|
|
16464
17469
|
}
|
|
@@ -16496,19 +17501,19 @@ var toUnix = (string) => {
|
|
|
16496
17501
|
}
|
|
16497
17502
|
return str;
|
|
16498
17503
|
};
|
|
16499
|
-
var normalizePathToUnix = (
|
|
16500
|
-
var normalizeIgnored = (cwd = "") => (
|
|
16501
|
-
if (typeof
|
|
16502
|
-
return normalizePathToUnix(sp2.isAbsolute(
|
|
17504
|
+
var normalizePathToUnix = (path31) => toUnix(sp2.normalize(toUnix(path31)));
|
|
17505
|
+
var normalizeIgnored = (cwd = "") => (path31) => {
|
|
17506
|
+
if (typeof path31 === "string") {
|
|
17507
|
+
return normalizePathToUnix(sp2.isAbsolute(path31) ? path31 : sp2.join(cwd, path31));
|
|
16503
17508
|
} else {
|
|
16504
|
-
return
|
|
17509
|
+
return path31;
|
|
16505
17510
|
}
|
|
16506
17511
|
};
|
|
16507
|
-
var getAbsolutePath = (
|
|
16508
|
-
if (sp2.isAbsolute(
|
|
16509
|
-
return
|
|
17512
|
+
var getAbsolutePath = (path31, cwd) => {
|
|
17513
|
+
if (sp2.isAbsolute(path31)) {
|
|
17514
|
+
return path31;
|
|
16510
17515
|
}
|
|
16511
|
-
return sp2.join(cwd,
|
|
17516
|
+
return sp2.join(cwd, path31);
|
|
16512
17517
|
};
|
|
16513
17518
|
var EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
|
|
16514
17519
|
var DirEntry = class {
|
|
@@ -16573,10 +17578,10 @@ var WatchHelper = class {
|
|
|
16573
17578
|
dirParts;
|
|
16574
17579
|
followSymlinks;
|
|
16575
17580
|
statMethod;
|
|
16576
|
-
constructor(
|
|
17581
|
+
constructor(path31, follow, fsw) {
|
|
16577
17582
|
this.fsw = fsw;
|
|
16578
|
-
const watchPath =
|
|
16579
|
-
this.path =
|
|
17583
|
+
const watchPath = path31;
|
|
17584
|
+
this.path = path31 = path31.replace(REPLACER_RE, "");
|
|
16580
17585
|
this.watchPath = watchPath;
|
|
16581
17586
|
this.fullWatchPath = sp2.resolve(watchPath);
|
|
16582
17587
|
this.dirParts = [];
|
|
@@ -16716,20 +17721,20 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
16716
17721
|
this._closePromise = void 0;
|
|
16717
17722
|
let paths = unifyPaths(paths_);
|
|
16718
17723
|
if (cwd) {
|
|
16719
|
-
paths = paths.map((
|
|
16720
|
-
const absPath = getAbsolutePath(
|
|
17724
|
+
paths = paths.map((path31) => {
|
|
17725
|
+
const absPath = getAbsolutePath(path31, cwd);
|
|
16721
17726
|
return absPath;
|
|
16722
17727
|
});
|
|
16723
17728
|
}
|
|
16724
|
-
paths.forEach((
|
|
16725
|
-
this._removeIgnoredPath(
|
|
17729
|
+
paths.forEach((path31) => {
|
|
17730
|
+
this._removeIgnoredPath(path31);
|
|
16726
17731
|
});
|
|
16727
17732
|
this._userIgnored = void 0;
|
|
16728
17733
|
if (!this._readyCount)
|
|
16729
17734
|
this._readyCount = 0;
|
|
16730
17735
|
this._readyCount += paths.length;
|
|
16731
|
-
Promise.all(paths.map(async (
|
|
16732
|
-
const res = await this._nodeFsHandler._addToNodeFs(
|
|
17736
|
+
Promise.all(paths.map(async (path31) => {
|
|
17737
|
+
const res = await this._nodeFsHandler._addToNodeFs(path31, !_internal, void 0, 0, _origAdd);
|
|
16733
17738
|
if (res)
|
|
16734
17739
|
this._emitReady();
|
|
16735
17740
|
return res;
|
|
@@ -16751,17 +17756,17 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
16751
17756
|
return this;
|
|
16752
17757
|
const paths = unifyPaths(paths_);
|
|
16753
17758
|
const { cwd } = this.options;
|
|
16754
|
-
paths.forEach((
|
|
16755
|
-
if (!sp2.isAbsolute(
|
|
17759
|
+
paths.forEach((path31) => {
|
|
17760
|
+
if (!sp2.isAbsolute(path31) && !this._closers.has(path31)) {
|
|
16756
17761
|
if (cwd)
|
|
16757
|
-
|
|
16758
|
-
|
|
17762
|
+
path31 = sp2.join(cwd, path31);
|
|
17763
|
+
path31 = sp2.resolve(path31);
|
|
16759
17764
|
}
|
|
16760
|
-
this._closePath(
|
|
16761
|
-
this._addIgnoredPath(
|
|
16762
|
-
if (this._watched.has(
|
|
17765
|
+
this._closePath(path31);
|
|
17766
|
+
this._addIgnoredPath(path31);
|
|
17767
|
+
if (this._watched.has(path31)) {
|
|
16763
17768
|
this._addIgnoredPath({
|
|
16764
|
-
path:
|
|
17769
|
+
path: path31,
|
|
16765
17770
|
recursive: true
|
|
16766
17771
|
});
|
|
16767
17772
|
}
|
|
@@ -16825,38 +17830,38 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
16825
17830
|
* @param stats arguments to be passed with event
|
|
16826
17831
|
* @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
|
|
16827
17832
|
*/
|
|
16828
|
-
async _emit(event,
|
|
17833
|
+
async _emit(event, path31, stats) {
|
|
16829
17834
|
if (this.closed)
|
|
16830
17835
|
return;
|
|
16831
17836
|
const opts = this.options;
|
|
16832
17837
|
if (isWindows)
|
|
16833
|
-
|
|
17838
|
+
path31 = sp2.normalize(path31);
|
|
16834
17839
|
if (opts.cwd)
|
|
16835
|
-
|
|
16836
|
-
const args = [
|
|
17840
|
+
path31 = sp2.relative(opts.cwd, path31);
|
|
17841
|
+
const args = [path31];
|
|
16837
17842
|
if (stats != null)
|
|
16838
17843
|
args.push(stats);
|
|
16839
17844
|
const awf = opts.awaitWriteFinish;
|
|
16840
17845
|
let pw;
|
|
16841
|
-
if (awf && (pw = this._pendingWrites.get(
|
|
17846
|
+
if (awf && (pw = this._pendingWrites.get(path31))) {
|
|
16842
17847
|
pw.lastChange = /* @__PURE__ */ new Date();
|
|
16843
17848
|
return this;
|
|
16844
17849
|
}
|
|
16845
17850
|
if (opts.atomic) {
|
|
16846
17851
|
if (event === EVENTS.UNLINK) {
|
|
16847
|
-
this._pendingUnlinks.set(
|
|
17852
|
+
this._pendingUnlinks.set(path31, [event, ...args]);
|
|
16848
17853
|
setTimeout(() => {
|
|
16849
|
-
this._pendingUnlinks.forEach((entry,
|
|
17854
|
+
this._pendingUnlinks.forEach((entry, path32) => {
|
|
16850
17855
|
this.emit(...entry);
|
|
16851
17856
|
this.emit(EVENTS.ALL, ...entry);
|
|
16852
|
-
this._pendingUnlinks.delete(
|
|
17857
|
+
this._pendingUnlinks.delete(path32);
|
|
16853
17858
|
});
|
|
16854
17859
|
}, typeof opts.atomic === "number" ? opts.atomic : 100);
|
|
16855
17860
|
return this;
|
|
16856
17861
|
}
|
|
16857
|
-
if (event === EVENTS.ADD && this._pendingUnlinks.has(
|
|
17862
|
+
if (event === EVENTS.ADD && this._pendingUnlinks.has(path31)) {
|
|
16858
17863
|
event = EVENTS.CHANGE;
|
|
16859
|
-
this._pendingUnlinks.delete(
|
|
17864
|
+
this._pendingUnlinks.delete(path31);
|
|
16860
17865
|
}
|
|
16861
17866
|
}
|
|
16862
17867
|
if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
|
|
@@ -16874,16 +17879,16 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
16874
17879
|
this.emitWithAll(event, args);
|
|
16875
17880
|
}
|
|
16876
17881
|
};
|
|
16877
|
-
this._awaitWriteFinish(
|
|
17882
|
+
this._awaitWriteFinish(path31, awf.stabilityThreshold, event, awfEmit);
|
|
16878
17883
|
return this;
|
|
16879
17884
|
}
|
|
16880
17885
|
if (event === EVENTS.CHANGE) {
|
|
16881
|
-
const isThrottled = !this._throttle(EVENTS.CHANGE,
|
|
17886
|
+
const isThrottled = !this._throttle(EVENTS.CHANGE, path31, 50);
|
|
16882
17887
|
if (isThrottled)
|
|
16883
17888
|
return this;
|
|
16884
17889
|
}
|
|
16885
17890
|
if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
|
|
16886
|
-
const fullPath = opts.cwd ? sp2.join(opts.cwd,
|
|
17891
|
+
const fullPath = opts.cwd ? sp2.join(opts.cwd, path31) : path31;
|
|
16887
17892
|
let stats2;
|
|
16888
17893
|
try {
|
|
16889
17894
|
stats2 = await (0, import_promises3.stat)(fullPath);
|
|
@@ -16914,23 +17919,23 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
16914
17919
|
* @param timeout duration of time to suppress duplicate actions
|
|
16915
17920
|
* @returns tracking object or false if action should be suppressed
|
|
16916
17921
|
*/
|
|
16917
|
-
_throttle(actionType,
|
|
17922
|
+
_throttle(actionType, path31, timeout) {
|
|
16918
17923
|
if (!this._throttled.has(actionType)) {
|
|
16919
17924
|
this._throttled.set(actionType, /* @__PURE__ */ new Map());
|
|
16920
17925
|
}
|
|
16921
17926
|
const action = this._throttled.get(actionType);
|
|
16922
17927
|
if (!action)
|
|
16923
17928
|
throw new Error("invalid throttle");
|
|
16924
|
-
const actionPath = action.get(
|
|
17929
|
+
const actionPath = action.get(path31);
|
|
16925
17930
|
if (actionPath) {
|
|
16926
17931
|
actionPath.count++;
|
|
16927
17932
|
return false;
|
|
16928
17933
|
}
|
|
16929
17934
|
let timeoutObject;
|
|
16930
17935
|
const clear = () => {
|
|
16931
|
-
const item = action.get(
|
|
17936
|
+
const item = action.get(path31);
|
|
16932
17937
|
const count = item ? item.count : 0;
|
|
16933
|
-
action.delete(
|
|
17938
|
+
action.delete(path31);
|
|
16934
17939
|
clearTimeout(timeoutObject);
|
|
16935
17940
|
if (item)
|
|
16936
17941
|
clearTimeout(item.timeoutObject);
|
|
@@ -16938,7 +17943,7 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
16938
17943
|
};
|
|
16939
17944
|
timeoutObject = setTimeout(clear, timeout);
|
|
16940
17945
|
const thr = { timeoutObject, clear, count: 0 };
|
|
16941
|
-
action.set(
|
|
17946
|
+
action.set(path31, thr);
|
|
16942
17947
|
return thr;
|
|
16943
17948
|
}
|
|
16944
17949
|
_incrReadyCount() {
|
|
@@ -16952,44 +17957,44 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
16952
17957
|
* @param event
|
|
16953
17958
|
* @param awfEmit Callback to be called when ready for event to be emitted.
|
|
16954
17959
|
*/
|
|
16955
|
-
_awaitWriteFinish(
|
|
17960
|
+
_awaitWriteFinish(path31, threshold, event, awfEmit) {
|
|
16956
17961
|
const awf = this.options.awaitWriteFinish;
|
|
16957
17962
|
if (typeof awf !== "object")
|
|
16958
17963
|
return;
|
|
16959
17964
|
const pollInterval = awf.pollInterval;
|
|
16960
17965
|
let timeoutHandler;
|
|
16961
|
-
let fullPath =
|
|
16962
|
-
if (this.options.cwd && !sp2.isAbsolute(
|
|
16963
|
-
fullPath = sp2.join(this.options.cwd,
|
|
17966
|
+
let fullPath = path31;
|
|
17967
|
+
if (this.options.cwd && !sp2.isAbsolute(path31)) {
|
|
17968
|
+
fullPath = sp2.join(this.options.cwd, path31);
|
|
16964
17969
|
}
|
|
16965
17970
|
const now2 = /* @__PURE__ */ new Date();
|
|
16966
17971
|
const writes = this._pendingWrites;
|
|
16967
17972
|
function awaitWriteFinishFn(prevStat) {
|
|
16968
|
-
(0,
|
|
16969
|
-
if (err || !writes.has(
|
|
17973
|
+
(0, import_node_fs3.stat)(fullPath, (err, curStat) => {
|
|
17974
|
+
if (err || !writes.has(path31)) {
|
|
16970
17975
|
if (err && err.code !== "ENOENT")
|
|
16971
17976
|
awfEmit(err);
|
|
16972
17977
|
return;
|
|
16973
17978
|
}
|
|
16974
17979
|
const now3 = Number(/* @__PURE__ */ new Date());
|
|
16975
17980
|
if (prevStat && curStat.size !== prevStat.size) {
|
|
16976
|
-
writes.get(
|
|
17981
|
+
writes.get(path31).lastChange = now3;
|
|
16977
17982
|
}
|
|
16978
|
-
const pw = writes.get(
|
|
17983
|
+
const pw = writes.get(path31);
|
|
16979
17984
|
const df = now3 - pw.lastChange;
|
|
16980
17985
|
if (df >= threshold) {
|
|
16981
|
-
writes.delete(
|
|
17986
|
+
writes.delete(path31);
|
|
16982
17987
|
awfEmit(void 0, curStat);
|
|
16983
17988
|
} else {
|
|
16984
17989
|
timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
|
|
16985
17990
|
}
|
|
16986
17991
|
});
|
|
16987
17992
|
}
|
|
16988
|
-
if (!writes.has(
|
|
16989
|
-
writes.set(
|
|
17993
|
+
if (!writes.has(path31)) {
|
|
17994
|
+
writes.set(path31, {
|
|
16990
17995
|
lastChange: now2,
|
|
16991
17996
|
cancelWait: () => {
|
|
16992
|
-
writes.delete(
|
|
17997
|
+
writes.delete(path31);
|
|
16993
17998
|
clearTimeout(timeoutHandler);
|
|
16994
17999
|
return event;
|
|
16995
18000
|
}
|
|
@@ -17000,8 +18005,8 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
17000
18005
|
/**
|
|
17001
18006
|
* Determines whether user has asked to ignore this path.
|
|
17002
18007
|
*/
|
|
17003
|
-
_isIgnored(
|
|
17004
|
-
if (this.options.atomic && DOT_RE.test(
|
|
18008
|
+
_isIgnored(path31, stats) {
|
|
18009
|
+
if (this.options.atomic && DOT_RE.test(path31))
|
|
17005
18010
|
return true;
|
|
17006
18011
|
if (!this._userIgnored) {
|
|
17007
18012
|
const { cwd } = this.options;
|
|
@@ -17011,17 +18016,17 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
17011
18016
|
const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
|
|
17012
18017
|
this._userIgnored = anymatch(list, void 0);
|
|
17013
18018
|
}
|
|
17014
|
-
return this._userIgnored(
|
|
18019
|
+
return this._userIgnored(path31, stats);
|
|
17015
18020
|
}
|
|
17016
|
-
_isntIgnored(
|
|
17017
|
-
return !this._isIgnored(
|
|
18021
|
+
_isntIgnored(path31, stat5) {
|
|
18022
|
+
return !this._isIgnored(path31, stat5);
|
|
17018
18023
|
}
|
|
17019
18024
|
/**
|
|
17020
18025
|
* Provides a set of common helpers and properties relating to symlink handling.
|
|
17021
18026
|
* @param path file or directory pattern being watched
|
|
17022
18027
|
*/
|
|
17023
|
-
_getWatchHelpers(
|
|
17024
|
-
return new WatchHelper(
|
|
18028
|
+
_getWatchHelpers(path31) {
|
|
18029
|
+
return new WatchHelper(path31, this.options.followSymlinks, this);
|
|
17025
18030
|
}
|
|
17026
18031
|
// Directory helpers
|
|
17027
18032
|
// -----------------
|
|
@@ -17053,63 +18058,63 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
17053
18058
|
* @param item base path of item/directory
|
|
17054
18059
|
*/
|
|
17055
18060
|
_remove(directory, item, isDirectory) {
|
|
17056
|
-
const
|
|
17057
|
-
const fullPath = sp2.resolve(
|
|
17058
|
-
isDirectory = isDirectory != null ? isDirectory : this._watched.has(
|
|
17059
|
-
if (!this._throttle("remove",
|
|
18061
|
+
const path31 = sp2.join(directory, item);
|
|
18062
|
+
const fullPath = sp2.resolve(path31);
|
|
18063
|
+
isDirectory = isDirectory != null ? isDirectory : this._watched.has(path31) || this._watched.has(fullPath);
|
|
18064
|
+
if (!this._throttle("remove", path31, 100))
|
|
17060
18065
|
return;
|
|
17061
18066
|
if (!isDirectory && this._watched.size === 1) {
|
|
17062
18067
|
this.add(directory, item, true);
|
|
17063
18068
|
}
|
|
17064
|
-
const wp = this._getWatchedDir(
|
|
18069
|
+
const wp = this._getWatchedDir(path31);
|
|
17065
18070
|
const nestedDirectoryChildren = wp.getChildren();
|
|
17066
|
-
nestedDirectoryChildren.forEach((nested) => this._remove(
|
|
18071
|
+
nestedDirectoryChildren.forEach((nested) => this._remove(path31, nested));
|
|
17067
18072
|
const parent = this._getWatchedDir(directory);
|
|
17068
18073
|
const wasTracked = parent.has(item);
|
|
17069
18074
|
parent.remove(item);
|
|
17070
18075
|
if (this._symlinkPaths.has(fullPath)) {
|
|
17071
18076
|
this._symlinkPaths.delete(fullPath);
|
|
17072
18077
|
}
|
|
17073
|
-
let relPath =
|
|
18078
|
+
let relPath = path31;
|
|
17074
18079
|
if (this.options.cwd)
|
|
17075
|
-
relPath = sp2.relative(this.options.cwd,
|
|
18080
|
+
relPath = sp2.relative(this.options.cwd, path31);
|
|
17076
18081
|
if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
|
|
17077
18082
|
const event = this._pendingWrites.get(relPath).cancelWait();
|
|
17078
18083
|
if (event === EVENTS.ADD)
|
|
17079
18084
|
return;
|
|
17080
18085
|
}
|
|
17081
|
-
this._watched.delete(
|
|
18086
|
+
this._watched.delete(path31);
|
|
17082
18087
|
this._watched.delete(fullPath);
|
|
17083
18088
|
const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
|
|
17084
|
-
if (wasTracked && !this._isIgnored(
|
|
17085
|
-
this._emit(eventName,
|
|
17086
|
-
this._closePath(
|
|
18089
|
+
if (wasTracked && !this._isIgnored(path31))
|
|
18090
|
+
this._emit(eventName, path31);
|
|
18091
|
+
this._closePath(path31);
|
|
17087
18092
|
}
|
|
17088
18093
|
/**
|
|
17089
18094
|
* Closes all watchers for a path
|
|
17090
18095
|
*/
|
|
17091
|
-
_closePath(
|
|
17092
|
-
this._closeFile(
|
|
17093
|
-
const dir = sp2.dirname(
|
|
17094
|
-
this._getWatchedDir(dir).remove(sp2.basename(
|
|
18096
|
+
_closePath(path31) {
|
|
18097
|
+
this._closeFile(path31);
|
|
18098
|
+
const dir = sp2.dirname(path31);
|
|
18099
|
+
this._getWatchedDir(dir).remove(sp2.basename(path31));
|
|
17095
18100
|
}
|
|
17096
18101
|
/**
|
|
17097
18102
|
* Closes only file-specific watchers
|
|
17098
18103
|
*/
|
|
17099
|
-
_closeFile(
|
|
17100
|
-
const closers = this._closers.get(
|
|
18104
|
+
_closeFile(path31) {
|
|
18105
|
+
const closers = this._closers.get(path31);
|
|
17101
18106
|
if (!closers)
|
|
17102
18107
|
return;
|
|
17103
18108
|
closers.forEach((closer) => closer());
|
|
17104
|
-
this._closers.delete(
|
|
18109
|
+
this._closers.delete(path31);
|
|
17105
18110
|
}
|
|
17106
|
-
_addPathCloser(
|
|
18111
|
+
_addPathCloser(path31, closer) {
|
|
17107
18112
|
if (!closer)
|
|
17108
18113
|
return;
|
|
17109
|
-
let list = this._closers.get(
|
|
18114
|
+
let list = this._closers.get(path31);
|
|
17110
18115
|
if (!list) {
|
|
17111
18116
|
list = [];
|
|
17112
|
-
this._closers.set(
|
|
18117
|
+
this._closers.set(path31, list);
|
|
17113
18118
|
}
|
|
17114
18119
|
list.push(closer);
|
|
17115
18120
|
}
|
|
@@ -17139,11 +18144,11 @@ function watch(paths, options = {}) {
|
|
|
17139
18144
|
var chokidar_default = { watch, FSWatcher };
|
|
17140
18145
|
|
|
17141
18146
|
// src/watcher/file-watcher.ts
|
|
17142
|
-
var
|
|
18147
|
+
var path24 = __toESM(require("path"), 1);
|
|
17143
18148
|
|
|
17144
18149
|
// src/watcher/native-recursive-watcher.ts
|
|
17145
|
-
var
|
|
17146
|
-
var
|
|
18150
|
+
var import_node_fs4 = require("fs");
|
|
18151
|
+
var path22 = __toESM(require("path"), 1);
|
|
17147
18152
|
var NativeRecursiveWatcher = class {
|
|
17148
18153
|
constructor(root, onChange, options = {}) {
|
|
17149
18154
|
this.root = root;
|
|
@@ -17191,26 +18196,26 @@ var NativeRecursiveWatcher = class {
|
|
|
17191
18196
|
toAbsolutePath(filename) {
|
|
17192
18197
|
if (filename == null) return null;
|
|
17193
18198
|
const normalizedFilename = typeof filename === "string" ? filename : filename.toString();
|
|
17194
|
-
const absolutePath =
|
|
17195
|
-
const relativePath =
|
|
17196
|
-
const outsideRoot = relativePath === ".." || relativePath.startsWith(`..${
|
|
18199
|
+
const absolutePath = path22.resolve(this.root, normalizedFilename);
|
|
18200
|
+
const relativePath = path22.relative(this.root, absolutePath);
|
|
18201
|
+
const outsideRoot = relativePath === ".." || relativePath.startsWith(`..${path22.sep}`) || path22.isAbsolute(relativePath);
|
|
17197
18202
|
return outsideRoot ? null : absolutePath;
|
|
17198
18203
|
}
|
|
17199
|
-
defaultWatchFactory = (root, listener, options) => (0,
|
|
18204
|
+
defaultWatchFactory = (root, listener, options) => (0, import_node_fs4.watch)(root, options, listener);
|
|
17200
18205
|
};
|
|
17201
18206
|
|
|
17202
18207
|
// src/watcher/snapshot.ts
|
|
17203
18208
|
var fsPromises4 = __toESM(require("fs/promises"), 1);
|
|
17204
|
-
var
|
|
18209
|
+
var path23 = __toESM(require("path"), 1);
|
|
17205
18210
|
async function buildFileSnapshotScan(projectRoot, config, configPaths = []) {
|
|
17206
|
-
const normalizedProjectRoot =
|
|
18211
|
+
const normalizedProjectRoot = path23.resolve(projectRoot);
|
|
17207
18212
|
const ignoreFilter = createIgnoreFilter(normalizedProjectRoot);
|
|
17208
18213
|
const includePatterns = [...config.include, ...config.additionalInclude ?? []];
|
|
17209
18214
|
const maxDepth = config.indexing?.maxDepth ?? -1;
|
|
17210
18215
|
const snapshot = /* @__PURE__ */ new Map();
|
|
17211
18216
|
const unreadablePrefixes = /* @__PURE__ */ new Set();
|
|
17212
18217
|
const includeFile = async (filePath) => {
|
|
17213
|
-
const normalizedPath2 =
|
|
18218
|
+
const normalizedPath2 = path23.resolve(filePath);
|
|
17214
18219
|
if (!shouldIncludeFile(normalizedPath2, normalizedProjectRoot, includePatterns, config.exclude, ignoreFilter)) return;
|
|
17215
18220
|
const stat5 = await readStatIfFile(normalizedPath2, unreadablePrefixes);
|
|
17216
18221
|
if (stat5) snapshot.set(normalizedPath2, { size: stat5.size, mtimeMs: stat5.mtimeMs });
|
|
@@ -17222,16 +18227,16 @@ async function buildFileSnapshotScan(projectRoot, config, configPaths = []) {
|
|
|
17222
18227
|
} catch (error) {
|
|
17223
18228
|
if (isMissingFsError(error)) return;
|
|
17224
18229
|
if (isPermissionFsError(error)) {
|
|
17225
|
-
unreadablePrefixes.add(
|
|
18230
|
+
unreadablePrefixes.add(path23.resolve(directoryPath));
|
|
17226
18231
|
return;
|
|
17227
18232
|
}
|
|
17228
18233
|
throw error;
|
|
17229
18234
|
}
|
|
17230
18235
|
for (const entry of entries) {
|
|
17231
|
-
const fullPath =
|
|
17232
|
-
const relativePath =
|
|
18236
|
+
const fullPath = path23.join(directoryPath, entry.name);
|
|
18237
|
+
const relativePath = path23.relative(normalizedProjectRoot, fullPath);
|
|
17233
18238
|
if (entry.isDirectory()) {
|
|
17234
|
-
if (hasFilteredPathSegment(relativePath,
|
|
18239
|
+
if (hasFilteredPathSegment(relativePath, path23.sep) || isRestrictedDirectory(relativePath, path23.sep)) continue;
|
|
17235
18240
|
if (ignoreFilter.ignores(relativePath)) continue;
|
|
17236
18241
|
if (maxDepth === -1 || depth < maxDepth) await walk(fullPath, depth + 1);
|
|
17237
18242
|
} else if (entry.isFile()) {
|
|
@@ -17244,19 +18249,19 @@ async function buildFileSnapshotScan(projectRoot, config, configPaths = []) {
|
|
|
17244
18249
|
return { entries: snapshot, unreadablePrefixes };
|
|
17245
18250
|
}
|
|
17246
18251
|
async function buildFileSnapshotForPathScan(projectRoot, config, configPaths, targetPath) {
|
|
17247
|
-
const normalizedProjectRoot =
|
|
17248
|
-
const normalizedTargetPath =
|
|
18252
|
+
const normalizedProjectRoot = path23.resolve(projectRoot);
|
|
18253
|
+
const normalizedTargetPath = path23.resolve(targetPath);
|
|
17249
18254
|
if (!isWithinPath(normalizedProjectRoot, normalizedTargetPath)) {
|
|
17250
18255
|
return { entries: /* @__PURE__ */ new Map(), unreadablePrefixes: /* @__PURE__ */ new Set() };
|
|
17251
18256
|
}
|
|
17252
18257
|
const ignoreFilter = createIgnoreFilter(normalizedProjectRoot);
|
|
17253
18258
|
const includePatterns = [...config.include, ...config.additionalInclude ?? []];
|
|
17254
18259
|
const maxDepth = config.indexing?.maxDepth ?? -1;
|
|
17255
|
-
const explicitConfigPaths = new Set(configPaths.map((configPath) =>
|
|
18260
|
+
const explicitConfigPaths = new Set(configPaths.map((configPath) => path23.resolve(configPath)));
|
|
17256
18261
|
const snapshot = /* @__PURE__ */ new Map();
|
|
17257
18262
|
const unreadablePrefixes = /* @__PURE__ */ new Set();
|
|
17258
18263
|
const includeFile = async (filePath) => {
|
|
17259
|
-
const normalizedPath2 =
|
|
18264
|
+
const normalizedPath2 = path23.resolve(filePath);
|
|
17260
18265
|
if (!explicitConfigPaths.has(normalizedPath2) && !shouldIncludeFile(
|
|
17261
18266
|
normalizedPath2,
|
|
17262
18267
|
normalizedProjectRoot,
|
|
@@ -17274,16 +18279,16 @@ async function buildFileSnapshotForPathScan(projectRoot, config, configPaths, ta
|
|
|
17274
18279
|
} catch (error) {
|
|
17275
18280
|
if (isMissingFsError(error)) return;
|
|
17276
18281
|
if (isPermissionFsError(error)) {
|
|
17277
|
-
unreadablePrefixes.add(
|
|
18282
|
+
unreadablePrefixes.add(path23.resolve(directoryPath));
|
|
17278
18283
|
return;
|
|
17279
18284
|
}
|
|
17280
18285
|
throw error;
|
|
17281
18286
|
}
|
|
17282
18287
|
for (const entry of entries) {
|
|
17283
|
-
const fullPath =
|
|
17284
|
-
const relativePath =
|
|
18288
|
+
const fullPath = path23.join(directoryPath, entry.name);
|
|
18289
|
+
const relativePath = path23.relative(normalizedProjectRoot, fullPath);
|
|
17285
18290
|
if (entry.isDirectory()) {
|
|
17286
|
-
if (hasFilteredPathSegment(relativePath,
|
|
18291
|
+
if (hasFilteredPathSegment(relativePath, path23.sep) || isRestrictedDirectory(relativePath, path23.sep)) continue;
|
|
17287
18292
|
if (ignoreFilter.ignores(relativePath)) continue;
|
|
17288
18293
|
if (maxDepth === -1 || depth < maxDepth) await walk(fullPath, depth + 1);
|
|
17289
18294
|
} else if (entry.isFile()) {
|
|
@@ -17307,7 +18312,7 @@ function completeFileSnapshot(previous, scan) {
|
|
|
17307
18312
|
return completed;
|
|
17308
18313
|
}
|
|
17309
18314
|
async function includeExplicitConfigPaths(snapshot, unreadablePrefixes, configPaths) {
|
|
17310
|
-
for (const configPath of [...new Set(configPaths.map((value) =>
|
|
18315
|
+
for (const configPath of [...new Set(configPaths.map((value) => path23.resolve(value)))]) {
|
|
17311
18316
|
if (snapshot.has(configPath)) continue;
|
|
17312
18317
|
const stat5 = await readStatIfFile(configPath, unreadablePrefixes);
|
|
17313
18318
|
if (stat5) snapshot.set(configPath, { size: stat5.size, mtimeMs: stat5.mtimeMs });
|
|
@@ -17317,12 +18322,12 @@ async function includeExplicitConfigPathsInPath(snapshot, unreadablePrefixes, co
|
|
|
17317
18322
|
await includeExplicitConfigPaths(
|
|
17318
18323
|
snapshot,
|
|
17319
18324
|
unreadablePrefixes,
|
|
17320
|
-
configPaths.filter((configPath) => isWithinPath(targetPath,
|
|
18325
|
+
configPaths.filter((configPath) => isWithinPath(targetPath, path23.resolve(configPath)))
|
|
17321
18326
|
);
|
|
17322
18327
|
}
|
|
17323
18328
|
function isWithinPath(parentPath, childPath) {
|
|
17324
|
-
const relativePath =
|
|
17325
|
-
return relativePath === "" || !relativePath.startsWith(`..${
|
|
18329
|
+
const relativePath = path23.relative(parentPath, childPath);
|
|
18330
|
+
return relativePath === "" || !relativePath.startsWith(`..${path23.sep}`) && relativePath !== ".." && !path23.isAbsolute(relativePath);
|
|
17326
18331
|
}
|
|
17327
18332
|
async function readStatIfFile(filePath, unreadablePrefixes) {
|
|
17328
18333
|
try {
|
|
@@ -17331,7 +18336,7 @@ async function readStatIfFile(filePath, unreadablePrefixes) {
|
|
|
17331
18336
|
} catch (error) {
|
|
17332
18337
|
if (isMissingFsError(error)) return null;
|
|
17333
18338
|
if (isPermissionFsError(error)) {
|
|
17334
|
-
unreadablePrefixes.add(
|
|
18339
|
+
unreadablePrefixes.add(path23.resolve(filePath));
|
|
17335
18340
|
return null;
|
|
17336
18341
|
}
|
|
17337
18342
|
throw error;
|
|
@@ -17468,8 +18473,8 @@ var FileWatcher = class {
|
|
|
17468
18473
|
this.createWatcher();
|
|
17469
18474
|
}
|
|
17470
18475
|
resetReady() {
|
|
17471
|
-
this.readyPromise = new Promise((
|
|
17472
|
-
this.resolveReady =
|
|
18476
|
+
this.readyPromise = new Promise((resolve18) => {
|
|
18477
|
+
this.resolveReady = resolve18;
|
|
17473
18478
|
});
|
|
17474
18479
|
this.startupReadySignals = 1;
|
|
17475
18480
|
}
|
|
@@ -17500,7 +18505,7 @@ var FileWatcher = class {
|
|
|
17500
18505
|
const resolvedWatchTargets = watchTargets ?? this.getFullChokidarWatchTargets();
|
|
17501
18506
|
const watcherOptions = {
|
|
17502
18507
|
ignored: (filePath) => {
|
|
17503
|
-
const relativePath =
|
|
18508
|
+
const relativePath = path24.relative(this.projectRoot, filePath);
|
|
17504
18509
|
if (!relativePath) return false;
|
|
17505
18510
|
if (this.isProjectConfigPathOrAncestor(relativePath)) {
|
|
17506
18511
|
return false;
|
|
@@ -17508,10 +18513,10 @@ var FileWatcher = class {
|
|
|
17508
18513
|
if (this.isOutsideProjectPath(relativePath)) {
|
|
17509
18514
|
return true;
|
|
17510
18515
|
}
|
|
17511
|
-
if (hasFilteredPathSegment(relativePath,
|
|
18516
|
+
if (hasFilteredPathSegment(relativePath, path24.sep)) {
|
|
17512
18517
|
return true;
|
|
17513
18518
|
}
|
|
17514
|
-
if (isRestrictedDirectory(relativePath,
|
|
18519
|
+
if (isRestrictedDirectory(relativePath, path24.sep)) {
|
|
17515
18520
|
return true;
|
|
17516
18521
|
}
|
|
17517
18522
|
if (ignoreFilter.ignores(relativePath)) {
|
|
@@ -17602,13 +18607,13 @@ var FileWatcher = class {
|
|
|
17602
18607
|
getExternalConfigWatchTargets() {
|
|
17603
18608
|
return [...new Set(
|
|
17604
18609
|
this.projectConfigPaths.filter((projectConfigPath) => {
|
|
17605
|
-
const relativeConfigPath =
|
|
18610
|
+
const relativeConfigPath = path24.relative(this.projectRoot, projectConfigPath);
|
|
17606
18611
|
return this.isOutsideProjectPath(relativeConfigPath);
|
|
17607
18612
|
}).map((projectConfigPath) => {
|
|
17608
18613
|
if ((0, import_fs14.existsSync)(projectConfigPath)) {
|
|
17609
18614
|
return projectConfigPath;
|
|
17610
18615
|
}
|
|
17611
|
-
return this.getNearestExistingDirectory(
|
|
18616
|
+
return this.getNearestExistingDirectory(path24.dirname(projectConfigPath));
|
|
17612
18617
|
})
|
|
17613
18618
|
)];
|
|
17614
18619
|
}
|
|
@@ -17670,7 +18675,7 @@ var FileWatcher = class {
|
|
|
17670
18675
|
}
|
|
17671
18676
|
scheduleNativeReconciliation(generation, filePath) {
|
|
17672
18677
|
if (!this.isCurrentNativeSetup(generation)) return;
|
|
17673
|
-
const requiresFullReconciliation = filePath ===
|
|
18678
|
+
const requiresFullReconciliation = filePath === path24.join(this.projectRoot, ".gitignore");
|
|
17674
18679
|
const invalidatedPath = requiresFullReconciliation ? null : filePath;
|
|
17675
18680
|
this.nativeInvalidatedPaths.set(invalidatedPath, invalidatedPath !== null);
|
|
17676
18681
|
if (this.nativeReconcileTimer) {
|
|
@@ -17765,23 +18770,23 @@ var FileWatcher = class {
|
|
|
17765
18770
|
this.scheduleFlush();
|
|
17766
18771
|
}
|
|
17767
18772
|
isProjectConfigPath(filePath) {
|
|
17768
|
-
const relativePath =
|
|
17769
|
-
const normalizedRelativePath =
|
|
18773
|
+
const relativePath = path24.relative(this.projectRoot, filePath);
|
|
18774
|
+
const normalizedRelativePath = path24.normalize(relativePath);
|
|
17770
18775
|
return this.getProjectConfigRelativePaths().some((configPath) => configPath === normalizedRelativePath);
|
|
17771
18776
|
}
|
|
17772
18777
|
isProjectConfigPathOrAncestor(relativePath) {
|
|
17773
|
-
const normalizedRelativePath =
|
|
18778
|
+
const normalizedRelativePath = path24.normalize(relativePath);
|
|
17774
18779
|
return this.getProjectConfigRelativePaths().some(
|
|
17775
|
-
(configPath) => configPath === normalizedRelativePath || configPath.startsWith(`${normalizedRelativePath}${
|
|
18780
|
+
(configPath) => configPath === normalizedRelativePath || configPath.startsWith(`${normalizedRelativePath}${path24.sep}`)
|
|
17776
18781
|
);
|
|
17777
18782
|
}
|
|
17778
18783
|
isOutsideProjectPath(relativePath) {
|
|
17779
|
-
return relativePath === ".." || relativePath.startsWith(`..${
|
|
18784
|
+
return relativePath === ".." || relativePath.startsWith(`..${path24.sep}`) || path24.isAbsolute(relativePath);
|
|
17780
18785
|
}
|
|
17781
18786
|
getNearestExistingDirectory(directoryPath) {
|
|
17782
18787
|
let candidate = directoryPath;
|
|
17783
18788
|
while (!(0, import_fs14.existsSync)(candidate)) {
|
|
17784
|
-
const parent =
|
|
18789
|
+
const parent = path24.dirname(candidate);
|
|
17785
18790
|
if (parent === candidate) break;
|
|
17786
18791
|
candidate = parent;
|
|
17787
18792
|
}
|
|
@@ -17789,7 +18794,7 @@ var FileWatcher = class {
|
|
|
17789
18794
|
}
|
|
17790
18795
|
getProjectConfigRelativePaths() {
|
|
17791
18796
|
return this.projectConfigPaths.map(
|
|
17792
|
-
(configPath) =>
|
|
18797
|
+
(configPath) => path24.normalize(path24.relative(this.projectRoot, configPath))
|
|
17793
18798
|
);
|
|
17794
18799
|
}
|
|
17795
18800
|
getConfigPathStates() {
|
|
@@ -17847,7 +18852,7 @@ var FileWatcher = class {
|
|
|
17847
18852
|
return;
|
|
17848
18853
|
}
|
|
17849
18854
|
const changes = Array.from(this.pendingChanges.entries()).map(
|
|
17850
|
-
([
|
|
18855
|
+
([path31, type]) => ({ path: path31, type })
|
|
17851
18856
|
);
|
|
17852
18857
|
this.pendingChanges.clear();
|
|
17853
18858
|
try {
|
|
@@ -17893,7 +18898,7 @@ var FileWatcher = class {
|
|
|
17893
18898
|
};
|
|
17894
18899
|
|
|
17895
18900
|
// src/watcher/git-head-watcher.ts
|
|
17896
|
-
var
|
|
18901
|
+
var path25 = __toESM(require("path"), 1);
|
|
17897
18902
|
var GitHeadWatcher = class {
|
|
17898
18903
|
watcher = null;
|
|
17899
18904
|
projectRoot;
|
|
@@ -17915,13 +18920,13 @@ var GitHeadWatcher = class {
|
|
|
17915
18920
|
this.readyPromise = Promise.resolve();
|
|
17916
18921
|
return;
|
|
17917
18922
|
}
|
|
17918
|
-
this.readyPromise = new Promise((
|
|
17919
|
-
this.resolveReady =
|
|
18923
|
+
this.readyPromise = new Promise((resolve18) => {
|
|
18924
|
+
this.resolveReady = resolve18;
|
|
17920
18925
|
});
|
|
17921
18926
|
this.onBranchChange = handler;
|
|
17922
18927
|
this.currentBranch = getCurrentBranch(this.projectRoot);
|
|
17923
18928
|
const headPath = getHeadPath(this.projectRoot);
|
|
17924
|
-
const refsPath =
|
|
18929
|
+
const refsPath = path25.join(this.projectRoot, ".git", "refs", "heads");
|
|
17925
18930
|
this.watcher = chokidar_default.watch([headPath, refsPath], {
|
|
17926
18931
|
persistent: true,
|
|
17927
18932
|
ignoreInitial: true,
|
|
@@ -17989,7 +18994,9 @@ var GitHeadWatcher = class {
|
|
|
17989
18994
|
function createWatcherWithIndexer(getIndexer, projectRoot, config, host, options = {}) {
|
|
17990
18995
|
const fileWatcher = new FileWatcher(projectRoot, config, host, options);
|
|
17991
18996
|
const configPaths = getConfigPaths(projectRoot, host, options);
|
|
17992
|
-
configureAutoIndex(projectRoot, host, parseConfig(config), getIndexer
|
|
18997
|
+
configureAutoIndex(projectRoot, host, parseConfig(config), getIndexer, {
|
|
18998
|
+
synchronizeBackgroundWorker: false
|
|
18999
|
+
});
|
|
17993
19000
|
let stopped = false;
|
|
17994
19001
|
const requestReindex = () => {
|
|
17995
19002
|
if (stopped) return;
|
|
@@ -18009,7 +19016,9 @@ function createWatcherWithIndexer(getIndexer, projectRoot, config, host, options
|
|
|
18009
19016
|
const parsedConfig = options.configPath ? parseConfig(loadConfigFile(options.configPath)) : void 0;
|
|
18010
19017
|
const refreshedConfig = refreshIndexerForDirectory(projectRoot, host, parsedConfig);
|
|
18011
19018
|
if (refreshedConfig) {
|
|
18012
|
-
configureAutoIndex(projectRoot, host, refreshedConfig, getIndexer
|
|
19019
|
+
configureAutoIndex(projectRoot, host, refreshedConfig, getIndexer, {
|
|
19020
|
+
synchronizeBackgroundWorker: false
|
|
19021
|
+
});
|
|
18013
19022
|
}
|
|
18014
19023
|
}
|
|
18015
19024
|
requestReindex();
|
|
@@ -18785,7 +19794,7 @@ async function resolveCodebaseContextUnmeasured(projectRoot, host, input) {
|
|
|
18785
19794
|
const directory = input.directory ?? void 0;
|
|
18786
19795
|
const tokenBudget = input.tokenBudget ?? void 0;
|
|
18787
19796
|
if (from && to) {
|
|
18788
|
-
const
|
|
19797
|
+
const path31 = await getCallGraphPath(
|
|
18789
19798
|
projectRoot,
|
|
18790
19799
|
host,
|
|
18791
19800
|
from,
|
|
@@ -18794,25 +19803,25 @@ async function resolveCodebaseContextUnmeasured(projectRoot, host, input) {
|
|
|
18794
19803
|
fromFilePath,
|
|
18795
19804
|
toFilePath
|
|
18796
19805
|
);
|
|
18797
|
-
const pathText = formatCallGraphPathResult(
|
|
18798
|
-
if (
|
|
19806
|
+
const pathText = formatCallGraphPathResult(path31);
|
|
19807
|
+
if (path31.path.length > 0) {
|
|
18799
19808
|
const fitted2 = fitTextToContextBudget(
|
|
18800
19809
|
pathText,
|
|
18801
19810
|
tokenBudget
|
|
18802
19811
|
);
|
|
18803
19812
|
return {
|
|
18804
19813
|
text: fitted2.text,
|
|
18805
|
-
details: fittedDetails("path", fitted2,
|
|
19814
|
+
details: fittedDetails("path", fitted2, path31.path.length)
|
|
18806
19815
|
};
|
|
18807
19816
|
}
|
|
18808
|
-
if (
|
|
19817
|
+
if (path31.from.status !== "resolved" || path31.to.status !== "resolved") {
|
|
18809
19818
|
const fitted2 = fitTextToContextBudget(pathText, tokenBudget);
|
|
18810
19819
|
return {
|
|
18811
19820
|
text: fitted2.text,
|
|
18812
19821
|
details: fittedDetails("path", fitted2, 0)
|
|
18813
19822
|
};
|
|
18814
19823
|
}
|
|
18815
|
-
const resolvedFrom =
|
|
19824
|
+
const resolvedFrom = path31.from;
|
|
18816
19825
|
const { callers } = await getCallGraphData(projectRoot, host, {
|
|
18817
19826
|
name: to,
|
|
18818
19827
|
direction: "callers",
|
|
@@ -18973,7 +19982,7 @@ async function executeCallGraph(projectRoot, host, args) {
|
|
|
18973
19982
|
return { text: formatCallGraphResult(await getCallGraphData(projectRoot, host, args)) };
|
|
18974
19983
|
}
|
|
18975
19984
|
async function executeCallGraphPath(projectRoot, host, args) {
|
|
18976
|
-
const
|
|
19985
|
+
const path31 = await getCallGraphPath(
|
|
18977
19986
|
projectRoot,
|
|
18978
19987
|
host,
|
|
18979
19988
|
args.from,
|
|
@@ -18982,7 +19991,7 @@ async function executeCallGraphPath(projectRoot, host, args) {
|
|
|
18982
19991
|
args.fromFilePath,
|
|
18983
19992
|
args.toFilePath
|
|
18984
19993
|
);
|
|
18985
|
-
return { text: formatCallGraphPathResult(
|
|
19994
|
+
return { text: formatCallGraphPathResult(path31) };
|
|
18986
19995
|
}
|
|
18987
19996
|
async function executeCodeCommunities(projectRoot, host, args) {
|
|
18988
19997
|
const result = await getCodeCommunities(projectRoot, host, args);
|
|
@@ -18991,12 +20000,12 @@ async function executeCodeCommunities(projectRoot, host, args) {
|
|
|
18991
20000
|
|
|
18992
20001
|
// src/adapters/opencode/tools.ts
|
|
18993
20002
|
var import_fs15 = require("fs");
|
|
18994
|
-
var
|
|
18995
|
-
var
|
|
20003
|
+
var os8 = __toESM(require("os"), 1);
|
|
20004
|
+
var path28 = __toESM(require("path"), 1);
|
|
18996
20005
|
|
|
18997
20006
|
// src/tools/visualize/activity.ts
|
|
18998
20007
|
var import_child_process5 = require("child_process");
|
|
18999
|
-
var
|
|
20008
|
+
var path26 = __toESM(require("path"), 1);
|
|
19000
20009
|
function attachRecentActivity(data, projectRoot) {
|
|
19001
20010
|
const activity = readGitActivity(projectRoot);
|
|
19002
20011
|
const changes = activity.size > 0 ? buildGitChanges(data, activity, projectRoot) : buildGraphChanges(data);
|
|
@@ -19158,7 +20167,7 @@ function normalizePath3(filePath) {
|
|
|
19158
20167
|
return filePath.replace(/\\/g, "/");
|
|
19159
20168
|
}
|
|
19160
20169
|
function toGitRelativePath(projectRoot, filePath) {
|
|
19161
|
-
const relativePath =
|
|
20170
|
+
const relativePath = path26.isAbsolute(filePath) ? path26.relative(projectRoot, filePath) : filePath;
|
|
19162
20171
|
return normalizePath3(relativePath);
|
|
19163
20172
|
}
|
|
19164
20173
|
|
|
@@ -19416,7 +20425,7 @@ render();
|
|
|
19416
20425
|
}
|
|
19417
20426
|
|
|
19418
20427
|
// src/tools/visualize/transform.ts
|
|
19419
|
-
var
|
|
20428
|
+
var path27 = __toESM(require("path"), 1);
|
|
19420
20429
|
|
|
19421
20430
|
// src/tools/visualize/modules.ts
|
|
19422
20431
|
var MAX_MODULES = 18;
|
|
@@ -19676,7 +20685,7 @@ function transformForVisualization(symbols, edges, options = {}) {
|
|
|
19676
20685
|
filePath: s.filePath,
|
|
19677
20686
|
kind: s.kind,
|
|
19678
20687
|
line: s.startLine,
|
|
19679
|
-
directory:
|
|
20688
|
+
directory: path27.dirname(s.filePath),
|
|
19680
20689
|
moduleId: "",
|
|
19681
20690
|
moduleLabel: ""
|
|
19682
20691
|
}));
|
|
@@ -20005,7 +21014,7 @@ var index_visualize = tool({
|
|
|
20005
21014
|
return "No connected symbols found for visualization. Try including orphans with includeOrphans=true, or check that the call graph has resolved edges.";
|
|
20006
21015
|
}
|
|
20007
21016
|
const html = generateVisualizationHtml(vizData);
|
|
20008
|
-
const outputPath =
|
|
21017
|
+
const outputPath = path28.join(os8.tmpdir(), `call-graph-${Date.now()}.html`);
|
|
20009
21018
|
(0, import_fs15.writeFileSync)(outputPath, html, "utf-8");
|
|
20010
21019
|
let result = `Temporal call graph visualization generated: ${outputPath}
|
|
20011
21020
|
|
|
@@ -20118,7 +21127,7 @@ var MCP_TOOL_NAMES = [
|
|
|
20118
21127
|
|
|
20119
21128
|
// src/commands/loader.ts
|
|
20120
21129
|
var import_fs16 = require("fs");
|
|
20121
|
-
var
|
|
21130
|
+
var path29 = __toESM(require("path"), 1);
|
|
20122
21131
|
function parseFrontmatter(content) {
|
|
20123
21132
|
const frontmatterRegex = /^---\s*\n([\s\S]*?)\n---\s*\n([\s\S]*)$/;
|
|
20124
21133
|
const match = content.match(frontmatterRegex);
|
|
@@ -20144,7 +21153,7 @@ function loadCommandsFromDirectory(commandsDir) {
|
|
|
20144
21153
|
}
|
|
20145
21154
|
const files = (0, import_fs16.readdirSync)(commandsDir).filter((f) => f.endsWith(".md"));
|
|
20146
21155
|
for (const file of files) {
|
|
20147
|
-
const filePath =
|
|
21156
|
+
const filePath = path29.join(commandsDir, file);
|
|
20148
21157
|
let content;
|
|
20149
21158
|
try {
|
|
20150
21159
|
content = (0, import_fs16.readFileSync)(filePath, "utf-8");
|
|
@@ -20153,7 +21162,7 @@ function loadCommandsFromDirectory(commandsDir) {
|
|
|
20153
21162
|
throw new Error(`Failed to load command file ${filePath}: ${message}`);
|
|
20154
21163
|
}
|
|
20155
21164
|
const { frontmatter, body } = parseFrontmatter(content);
|
|
20156
|
-
const name =
|
|
21165
|
+
const name = path29.basename(file, ".md");
|
|
20157
21166
|
const description = frontmatter.description || `Run the ${name} command`;
|
|
20158
21167
|
commands.set(name, {
|
|
20159
21168
|
description,
|
|
@@ -20489,42 +21498,13 @@ var RoutingHintController = class {
|
|
|
20489
21498
|
|
|
20490
21499
|
// src/adapters/opencode.ts
|
|
20491
21500
|
var import_meta2 = {};
|
|
20492
|
-
var activeWatchers = /* @__PURE__ */ new Map();
|
|
20493
|
-
var watcherReplacementChains = /* @__PURE__ */ new Map();
|
|
20494
|
-
async function replaceActiveWatcher(projectRoot, createNextWatcher) {
|
|
20495
|
-
const chain = (watcherReplacementChains.get(projectRoot) ?? Promise.resolve()).catch(() => void 0).then(async () => {
|
|
20496
|
-
const existing = activeWatchers.get(projectRoot);
|
|
20497
|
-
if (existing) {
|
|
20498
|
-
try {
|
|
20499
|
-
await existing.stop();
|
|
20500
|
-
} catch (error) {
|
|
20501
|
-
console.error("[codebase-index] Failed to stop replaced watcher:", error);
|
|
20502
|
-
throw error;
|
|
20503
|
-
}
|
|
20504
|
-
if (activeWatchers.get(projectRoot) === existing) {
|
|
20505
|
-
activeWatchers.delete(projectRoot);
|
|
20506
|
-
}
|
|
20507
|
-
}
|
|
20508
|
-
if (createNextWatcher) {
|
|
20509
|
-
activeWatchers.set(projectRoot, createNextWatcher());
|
|
20510
|
-
}
|
|
20511
|
-
});
|
|
20512
|
-
watcherReplacementChains.set(projectRoot, chain);
|
|
20513
|
-
try {
|
|
20514
|
-
await chain;
|
|
20515
|
-
} finally {
|
|
20516
|
-
if (watcherReplacementChains.get(projectRoot) === chain) {
|
|
20517
|
-
watcherReplacementChains.delete(projectRoot);
|
|
20518
|
-
}
|
|
20519
|
-
}
|
|
20520
|
-
}
|
|
20521
21501
|
function getCommandsDir() {
|
|
20522
21502
|
let currentDir = process.cwd();
|
|
20523
21503
|
if (typeof import_meta2 !== "undefined" && import_meta2.url) {
|
|
20524
|
-
currentDir =
|
|
21504
|
+
currentDir = path30.dirname((0, import_url.fileURLToPath)(import_meta2.url));
|
|
20525
21505
|
}
|
|
20526
|
-
const packageRoot =
|
|
20527
|
-
return
|
|
21506
|
+
const packageRoot = path30.basename(currentDir) === "adapters" ? path30.join(currentDir, "..", "..") : path30.join(currentDir, "..");
|
|
21507
|
+
return path30.join(packageRoot, "commands");
|
|
20528
21508
|
}
|
|
20529
21509
|
function appendRoutingHints(output, hints, preferredRole) {
|
|
20530
21510
|
const preferredBucket = preferredRole === "developer" ? output.developer : output.system;
|
|
@@ -20550,8 +21530,9 @@ var plugin = async ({ directory, worktree }) => {
|
|
|
20550
21530
|
initializeTools2(projectRoot, config);
|
|
20551
21531
|
const getProjectIndexer = () => getIndexerForProject2(projectRoot);
|
|
20552
21532
|
const routingHints = config.search.routingHints ? new RoutingHintController(() => getProjectIndexer().getStatus(), 200, config.search.routingGraphHandoffHints) : null;
|
|
20553
|
-
const
|
|
20554
|
-
const
|
|
21533
|
+
const projectSafety = getProjectSafety(projectRoot, config);
|
|
21534
|
+
const isHomeDir = projectSafety.blockedReason === "home-directory";
|
|
21535
|
+
const isValidProject = projectSafety.safeToRun;
|
|
20555
21536
|
if (isHomeDir) {
|
|
20556
21537
|
console.warn(
|
|
20557
21538
|
`[codebase-index] Refusing to watch or index home directory "${projectRoot}". Open a specific project directory instead.`
|
|
@@ -20561,16 +21542,24 @@ var plugin = async ({ directory, worktree }) => {
|
|
|
20561
21542
|
`[codebase-index] Skipping file watching and auto-indexing: no project marker found in "${projectRoot}". Set "indexing.requireProjectMarker": false in config to override.`
|
|
20562
21543
|
);
|
|
20563
21544
|
}
|
|
20564
|
-
if (
|
|
20565
|
-
|
|
20566
|
-
|
|
20567
|
-
|
|
20568
|
-
await replaceActiveWatcher(
|
|
20569
|
-
projectRoot,
|
|
20570
|
-
() => createWatcherWithIndexer(getProjectIndexer, projectRoot, config, "opencode")
|
|
20571
|
-
);
|
|
21545
|
+
if (!isValidProject) {
|
|
21546
|
+
await stopBackgroundWorker(projectRoot, "opencode").catch((error) => {
|
|
21547
|
+
console.error("[codebase-index] Failed to stop unsafe OpenCode background worker:", error);
|
|
21548
|
+
});
|
|
20572
21549
|
} else {
|
|
20573
|
-
|
|
21550
|
+
const watcherFactoryForConfig = (refreshedConfig) => refreshedConfig.indexing.watchFiles ? () => createWatcherWithIndexer(getProjectIndexer, projectRoot, refreshedConfig, "opencode") : null;
|
|
21551
|
+
configureBackgroundWorker(projectRoot, "opencode", config, {
|
|
21552
|
+
startAutoIndex: (source, allowDisabledAutoIndex) => {
|
|
21553
|
+
startAutoIndexForBackgroundWorker(projectRoot, "opencode", source, allowDisabledAutoIndex);
|
|
21554
|
+
},
|
|
21555
|
+
stopAutoIndex: () => stopAutoIndexForBackgroundWorker(projectRoot, "opencode"),
|
|
21556
|
+
watcherFactory: watcherFactoryForConfig(config),
|
|
21557
|
+
watcherFactoryForConfig,
|
|
21558
|
+
replaceWatcher: true
|
|
21559
|
+
}, {
|
|
21560
|
+
restartAutoIndex: true
|
|
21561
|
+
});
|
|
21562
|
+
await waitForBackgroundWorkerStart(projectRoot, "opencode");
|
|
20574
21563
|
}
|
|
20575
21564
|
return {
|
|
20576
21565
|
tool: {
|