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.js
CHANGED
|
@@ -328,7 +328,7 @@ var require_ignore = __commonJS({
|
|
|
328
328
|
// path matching.
|
|
329
329
|
// - check `string` either `MODE_IGNORE` or `MODE_CHECK_IGNORE`
|
|
330
330
|
// @returns {TestResult} true if a file is ignored
|
|
331
|
-
test(
|
|
331
|
+
test(path31, checkUnignored, mode) {
|
|
332
332
|
let ignored = false;
|
|
333
333
|
let unignored = false;
|
|
334
334
|
let matchedRule;
|
|
@@ -337,7 +337,7 @@ var require_ignore = __commonJS({
|
|
|
337
337
|
if (unignored === negative && ignored !== unignored || negative && !ignored && !unignored && !checkUnignored) {
|
|
338
338
|
return;
|
|
339
339
|
}
|
|
340
|
-
const matched = rule[mode].test(
|
|
340
|
+
const matched = rule[mode].test(path31);
|
|
341
341
|
if (!matched) {
|
|
342
342
|
return;
|
|
343
343
|
}
|
|
@@ -358,17 +358,17 @@ var require_ignore = __commonJS({
|
|
|
358
358
|
var throwError = (message, Ctor) => {
|
|
359
359
|
throw new Ctor(message);
|
|
360
360
|
};
|
|
361
|
-
var checkPath = (
|
|
362
|
-
if (!isString(
|
|
361
|
+
var checkPath = (path31, originalPath, doThrow) => {
|
|
362
|
+
if (!isString(path31)) {
|
|
363
363
|
return doThrow(
|
|
364
364
|
`path must be a string, but got \`${originalPath}\``,
|
|
365
365
|
TypeError
|
|
366
366
|
);
|
|
367
367
|
}
|
|
368
|
-
if (!
|
|
368
|
+
if (!path31) {
|
|
369
369
|
return doThrow(`path must not be empty`, TypeError);
|
|
370
370
|
}
|
|
371
|
-
if (checkPath.isNotRelative(
|
|
371
|
+
if (checkPath.isNotRelative(path31)) {
|
|
372
372
|
const r = "`path.relative()`d";
|
|
373
373
|
return doThrow(
|
|
374
374
|
`path should be a ${r} string, but got "${originalPath}"`,
|
|
@@ -377,7 +377,7 @@ var require_ignore = __commonJS({
|
|
|
377
377
|
}
|
|
378
378
|
return true;
|
|
379
379
|
};
|
|
380
|
-
var isNotRelative = (
|
|
380
|
+
var isNotRelative = (path31) => REGEX_TEST_INVALID_PATH.test(path31);
|
|
381
381
|
checkPath.isNotRelative = isNotRelative;
|
|
382
382
|
checkPath.convert = (p) => p;
|
|
383
383
|
var Ignore2 = class {
|
|
@@ -407,19 +407,19 @@ var require_ignore = __commonJS({
|
|
|
407
407
|
}
|
|
408
408
|
// @returns {TestResult}
|
|
409
409
|
_test(originalPath, cache, checkUnignored, slices) {
|
|
410
|
-
const
|
|
410
|
+
const path31 = originalPath && checkPath.convert(originalPath);
|
|
411
411
|
checkPath(
|
|
412
|
-
|
|
412
|
+
path31,
|
|
413
413
|
originalPath,
|
|
414
414
|
this._strictPathCheck ? throwError : RETURN_FALSE
|
|
415
415
|
);
|
|
416
|
-
return this._t(
|
|
416
|
+
return this._t(path31, cache, checkUnignored, slices);
|
|
417
417
|
}
|
|
418
|
-
checkIgnore(
|
|
419
|
-
if (!REGEX_TEST_TRAILING_SLASH.test(
|
|
420
|
-
return this.test(
|
|
418
|
+
checkIgnore(path31) {
|
|
419
|
+
if (!REGEX_TEST_TRAILING_SLASH.test(path31)) {
|
|
420
|
+
return this.test(path31);
|
|
421
421
|
}
|
|
422
|
-
const slices =
|
|
422
|
+
const slices = path31.split(SLASH2).filter(Boolean);
|
|
423
423
|
slices.pop();
|
|
424
424
|
if (slices.length) {
|
|
425
425
|
const parent = this._t(
|
|
@@ -432,18 +432,18 @@ var require_ignore = __commonJS({
|
|
|
432
432
|
return parent;
|
|
433
433
|
}
|
|
434
434
|
}
|
|
435
|
-
return this._rules.test(
|
|
435
|
+
return this._rules.test(path31, false, MODE_CHECK_IGNORE);
|
|
436
436
|
}
|
|
437
|
-
_t(
|
|
438
|
-
if (
|
|
439
|
-
return cache[
|
|
437
|
+
_t(path31, cache, checkUnignored, slices) {
|
|
438
|
+
if (path31 in cache) {
|
|
439
|
+
return cache[path31];
|
|
440
440
|
}
|
|
441
441
|
if (!slices) {
|
|
442
|
-
slices =
|
|
442
|
+
slices = path31.split(SLASH2).filter(Boolean);
|
|
443
443
|
}
|
|
444
444
|
slices.pop();
|
|
445
445
|
if (!slices.length) {
|
|
446
|
-
return cache[
|
|
446
|
+
return cache[path31] = this._rules.test(path31, checkUnignored, MODE_IGNORE);
|
|
447
447
|
}
|
|
448
448
|
const parent = this._t(
|
|
449
449
|
slices.join(SLASH2) + SLASH2,
|
|
@@ -451,29 +451,29 @@ var require_ignore = __commonJS({
|
|
|
451
451
|
checkUnignored,
|
|
452
452
|
slices
|
|
453
453
|
);
|
|
454
|
-
return cache[
|
|
454
|
+
return cache[path31] = parent.ignored ? parent : this._rules.test(path31, checkUnignored, MODE_IGNORE);
|
|
455
455
|
}
|
|
456
|
-
ignores(
|
|
457
|
-
return this._test(
|
|
456
|
+
ignores(path31) {
|
|
457
|
+
return this._test(path31, this._ignoreCache, false).ignored;
|
|
458
458
|
}
|
|
459
459
|
createFilter() {
|
|
460
|
-
return (
|
|
460
|
+
return (path31) => !this.ignores(path31);
|
|
461
461
|
}
|
|
462
462
|
filter(paths) {
|
|
463
463
|
return makeArray(paths).filter(this.createFilter());
|
|
464
464
|
}
|
|
465
465
|
// @returns {TestResult}
|
|
466
|
-
test(
|
|
467
|
-
return this._test(
|
|
466
|
+
test(path31) {
|
|
467
|
+
return this._test(path31, this._testCache, true);
|
|
468
468
|
}
|
|
469
469
|
};
|
|
470
470
|
var factory = (options) => new Ignore2(options);
|
|
471
|
-
var isPathValid = (
|
|
471
|
+
var isPathValid = (path31) => checkPath(path31 && checkPath.convert(path31), path31, RETURN_FALSE);
|
|
472
472
|
var setupWindows = () => {
|
|
473
473
|
const makePosix = (str) => /^\\\\\?\\/.test(str) || /["<>|\u0000-\u001F]+/u.test(str) ? str : str.replace(/\\/g, "/");
|
|
474
474
|
checkPath.convert = makePosix;
|
|
475
475
|
const REGEX_TEST_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i;
|
|
476
|
-
checkPath.isNotRelative = (
|
|
476
|
+
checkPath.isNotRelative = (path31) => REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path31) || isNotRelative(path31);
|
|
477
477
|
};
|
|
478
478
|
if (
|
|
479
479
|
// Detect `process` so that it can run in browsers.
|
|
@@ -651,7 +651,7 @@ var require_eventemitter3 = __commonJS({
|
|
|
651
651
|
});
|
|
652
652
|
|
|
653
653
|
// src/adapters/opencode.ts
|
|
654
|
-
import * as
|
|
654
|
+
import * as path30 from "path";
|
|
655
655
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
656
656
|
|
|
657
657
|
// src/config/constants.ts
|
|
@@ -1749,8 +1749,8 @@ function loadMergedConfig(projectRoot, host) {
|
|
|
1749
1749
|
}
|
|
1750
1750
|
|
|
1751
1751
|
// src/tools/operations.ts
|
|
1752
|
-
import { existsSync as
|
|
1753
|
-
import * as
|
|
1752
|
+
import { existsSync as existsSync13, realpathSync as realpathSync6, statSync as statSync5 } from "fs";
|
|
1753
|
+
import * as path21 from "path";
|
|
1754
1754
|
|
|
1755
1755
|
// src/tools/knowledge-base-paths.ts
|
|
1756
1756
|
import * as path8 from "path";
|
|
@@ -2599,8 +2599,8 @@ function formatExactSearchHandoff(results) {
|
|
|
2599
2599
|
}
|
|
2600
2600
|
function formatContextEvidence(result, index) {
|
|
2601
2601
|
const symbol = result.name ? ` ${JSON.stringify(compactEvidenceValue(result.name, 80))}` : "";
|
|
2602
|
-
const
|
|
2603
|
-
return `[${index}] ${result.chunkType}${symbol} in ${
|
|
2602
|
+
const path31 = compactEvidenceValue(result.filePath, 120);
|
|
2603
|
+
return `[${index}] ${result.chunkType}${symbol} in ${path31}:${result.startLine}-${result.endLine} (score ${result.score.toFixed(2)})`;
|
|
2604
2604
|
}
|
|
2605
2605
|
function formatContextPack(heading, selected, candidateCount, duplicateCount, limitOmittedCount, budgetOmittedCount, includeExactSearchHandoff) {
|
|
2606
2606
|
const lines = selected.map((result, index) => formatContextEvidence(result, index + 1));
|
|
@@ -3242,9 +3242,9 @@ function formatEffectivenessMetrics(snapshot) {
|
|
|
3242
3242
|
}
|
|
3243
3243
|
|
|
3244
3244
|
// src/utils/auto-index.ts
|
|
3245
|
-
import { existsSync as
|
|
3246
|
-
import * as
|
|
3247
|
-
import * as
|
|
3245
|
+
import { existsSync as existsSync8, realpathSync as realpathSync4 } from "fs";
|
|
3246
|
+
import * as os4 from "os";
|
|
3247
|
+
import * as path12 from "path";
|
|
3248
3248
|
|
|
3249
3249
|
// src/indexer/index-lock.ts
|
|
3250
3250
|
import { randomUUID } from "crypto";
|
|
@@ -3501,7 +3501,7 @@ function removeDeadReclaimMarker(lockPath, expectedOwner) {
|
|
|
3501
3501
|
return true;
|
|
3502
3502
|
}
|
|
3503
3503
|
function reclaimDeadOwner(indexPath, lockPath, expectedOwner) {
|
|
3504
|
-
const
|
|
3504
|
+
const reclaimPath2 = path9.join(lockPath, RECLAIM_DIRECTORY_NAME);
|
|
3505
3505
|
const reclaimOwner = {
|
|
3506
3506
|
pid: process.pid,
|
|
3507
3507
|
hostname: os2.hostname(),
|
|
@@ -3510,19 +3510,19 @@ function reclaimDeadOwner(indexPath, lockPath, expectedOwner) {
|
|
|
3510
3510
|
expectedOwnerToken: expectedOwner.token
|
|
3511
3511
|
};
|
|
3512
3512
|
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
3513
|
-
if (publishJsonDirectory(
|
|
3513
|
+
if (publishJsonDirectory(reclaimPath2, reclaimOwner)) break;
|
|
3514
3514
|
if (attempt === 0 && removeDeadReclaimMarker(lockPath, expectedOwner)) continue;
|
|
3515
3515
|
return false;
|
|
3516
3516
|
}
|
|
3517
3517
|
try {
|
|
3518
|
-
const currentReclaimer = readReclaimOwner(
|
|
3518
|
+
const currentReclaimer = readReclaimOwner(reclaimPath2);
|
|
3519
3519
|
const currentOwner = readDirectoryOwner(lockPath);
|
|
3520
3520
|
if (!currentReclaimer || !sameReclaimOwner(currentReclaimer, reclaimOwner) || !currentOwner || !sameOwner(currentOwner, expectedOwner) || getOwnerLiveness(currentOwner) !== "dead") {
|
|
3521
3521
|
return false;
|
|
3522
3522
|
}
|
|
3523
3523
|
publishRecoveryMarker(indexPath, expectedOwner);
|
|
3524
3524
|
const ownerBeforeQuarantine = readDirectoryOwner(lockPath);
|
|
3525
|
-
const reclaimerBeforeQuarantine = readReclaimOwner(
|
|
3525
|
+
const reclaimerBeforeQuarantine = readReclaimOwner(reclaimPath2);
|
|
3526
3526
|
if (!ownerBeforeQuarantine || !sameOwner(ownerBeforeQuarantine, expectedOwner) || getOwnerLiveness(ownerBeforeQuarantine) !== "dead" || !reclaimerBeforeQuarantine || !sameReclaimOwner(reclaimerBeforeQuarantine, reclaimOwner)) {
|
|
3527
3527
|
return false;
|
|
3528
3528
|
}
|
|
@@ -3692,10 +3692,893 @@ function completeLeaseRecovery(lease) {
|
|
|
3692
3692
|
}
|
|
3693
3693
|
}
|
|
3694
3694
|
|
|
3695
|
+
// src/utils/background-worker.ts
|
|
3696
|
+
import { createHash, randomUUID as randomUUID2 } from "crypto";
|
|
3697
|
+
import {
|
|
3698
|
+
existsSync as existsSync6,
|
|
3699
|
+
lstatSync as lstatSync2,
|
|
3700
|
+
mkdirSync as mkdirSync2,
|
|
3701
|
+
readFileSync as readFileSync5,
|
|
3702
|
+
realpathSync as realpathSync3,
|
|
3703
|
+
renameSync as renameSync2,
|
|
3704
|
+
rmSync as rmSync2,
|
|
3705
|
+
writeFileSync as writeFileSync2
|
|
3706
|
+
} from "fs";
|
|
3707
|
+
import * as os3 from "os";
|
|
3708
|
+
import * as path10 from "path";
|
|
3709
|
+
var OWNER_FILE_NAME2 = "owner.json";
|
|
3710
|
+
var HEARTBEAT_FILE_PREFIX = "heartbeat.";
|
|
3711
|
+
var RECLAIM_DIRECTORY_NAME2 = "reclaim";
|
|
3712
|
+
var REFRESH_REQUEST_FILE_NAME = "refresh-request.json";
|
|
3713
|
+
var HEARTBEAT_INTERVAL_MS = 5e3;
|
|
3714
|
+
var STALE_LEASE_MS = 3e4;
|
|
3715
|
+
var RETRY_DELAY_MS = 5e3;
|
|
3716
|
+
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;
|
|
3717
|
+
var BackgroundWorkerStopError = class extends Error {
|
|
3718
|
+
constructor(watcherError, autoIndexError) {
|
|
3719
|
+
super("Failed to stop background worker");
|
|
3720
|
+
this.watcherError = watcherError;
|
|
3721
|
+
this.autoIndexError = autoIndexError;
|
|
3722
|
+
this.name = "BackgroundWorkerStopError";
|
|
3723
|
+
}
|
|
3724
|
+
watcherError;
|
|
3725
|
+
autoIndexError;
|
|
3726
|
+
};
|
|
3727
|
+
var workers = /* @__PURE__ */ new Map();
|
|
3728
|
+
var workerKeysByProject = /* @__PURE__ */ new Map();
|
|
3729
|
+
var workerReplacementBarriers = /* @__PURE__ */ new Map();
|
|
3730
|
+
function getErrorCode2(error) {
|
|
3731
|
+
return typeof error === "object" && error !== null && "code" in error ? String(error.code) : void 0;
|
|
3732
|
+
}
|
|
3733
|
+
function canonicalizePath(targetPath) {
|
|
3734
|
+
const resolved = path10.resolve(targetPath);
|
|
3735
|
+
if (existsSync6(resolved)) {
|
|
3736
|
+
try {
|
|
3737
|
+
return realpathSync3.native(resolved);
|
|
3738
|
+
} catch {
|
|
3739
|
+
return resolved;
|
|
3740
|
+
}
|
|
3741
|
+
}
|
|
3742
|
+
const parent = path10.dirname(resolved);
|
|
3743
|
+
if (parent === resolved) return resolved;
|
|
3744
|
+
return path10.join(canonicalizePath(parent), path10.basename(resolved));
|
|
3745
|
+
}
|
|
3746
|
+
function projectLookupKey(projectRoot, host) {
|
|
3747
|
+
return `${host}::${canonicalizePath(projectRoot)}`;
|
|
3748
|
+
}
|
|
3749
|
+
function resolveIdentity(projectRoot, config, host) {
|
|
3750
|
+
const canonicalProjectRoot = canonicalizePath(projectRoot);
|
|
3751
|
+
const canonicalIndexPath = canonicalizePath(resolveProjectIndexPath(projectRoot, config.scope, host));
|
|
3752
|
+
return {
|
|
3753
|
+
canonicalIndexPath,
|
|
3754
|
+
canonicalProjectRoot,
|
|
3755
|
+
key: `${canonicalIndexPath}::${canonicalProjectRoot}`
|
|
3756
|
+
};
|
|
3757
|
+
}
|
|
3758
|
+
function controllerKey(identity, host) {
|
|
3759
|
+
return `${identity.key}::${host}`;
|
|
3760
|
+
}
|
|
3761
|
+
function leaseDirectoryName(identity) {
|
|
3762
|
+
const hash = createHash("sha256").update(identity.key).digest("hex").slice(0, 32);
|
|
3763
|
+
return `background-worker.${hash}.lease`;
|
|
3764
|
+
}
|
|
3765
|
+
function leasePathFor(identity) {
|
|
3766
|
+
return path10.join(identity.canonicalIndexPath, leaseDirectoryName(identity));
|
|
3767
|
+
}
|
|
3768
|
+
function parseOwner2(value) {
|
|
3769
|
+
if (typeof value !== "object" || value === null) return null;
|
|
3770
|
+
const candidate = value;
|
|
3771
|
+
if (candidate.version !== 1) return null;
|
|
3772
|
+
if (!Number.isInteger(candidate.pid) || (candidate.pid ?? 0) <= 0) return null;
|
|
3773
|
+
if (typeof candidate.hostname !== "string" || candidate.hostname.length === 0) return null;
|
|
3774
|
+
if (typeof candidate.startedAt !== "string" || Number.isNaN(Date.parse(candidate.startedAt))) return null;
|
|
3775
|
+
if (typeof candidate.heartbeatAt !== "string" || Number.isNaN(Date.parse(candidate.heartbeatAt))) return null;
|
|
3776
|
+
if (typeof candidate.projectRoot !== "string" || candidate.projectRoot.length === 0) return null;
|
|
3777
|
+
if (typeof candidate.indexPath !== "string" || candidate.indexPath.length === 0) return null;
|
|
3778
|
+
if (typeof candidate.token !== "string" || !UUID_PATTERN2.test(candidate.token)) return null;
|
|
3779
|
+
return candidate;
|
|
3780
|
+
}
|
|
3781
|
+
function parseHeartbeat(value, expectedToken) {
|
|
3782
|
+
if (typeof value !== "object" || value === null) return null;
|
|
3783
|
+
const candidate = value;
|
|
3784
|
+
if (candidate.version !== 1 || candidate.token !== expectedToken) return null;
|
|
3785
|
+
if (typeof candidate.heartbeatAt !== "string" || Number.isNaN(Date.parse(candidate.heartbeatAt))) return null;
|
|
3786
|
+
return candidate;
|
|
3787
|
+
}
|
|
3788
|
+
function parseReclaimOwner2(value) {
|
|
3789
|
+
if (typeof value !== "object" || value === null) return null;
|
|
3790
|
+
const candidate = value;
|
|
3791
|
+
if (candidate.version !== 1) return null;
|
|
3792
|
+
if (!Number.isInteger(candidate.pid) || (candidate.pid ?? 0) <= 0) return null;
|
|
3793
|
+
if (typeof candidate.hostname !== "string" || candidate.hostname.length === 0) return null;
|
|
3794
|
+
if (typeof candidate.startedAt !== "string" || Number.isNaN(Date.parse(candidate.startedAt))) return null;
|
|
3795
|
+
if (typeof candidate.token !== "string" || !UUID_PATTERN2.test(candidate.token)) return null;
|
|
3796
|
+
if (candidate.expectedOwnerToken !== null && (typeof candidate.expectedOwnerToken !== "string" || !UUID_PATTERN2.test(candidate.expectedOwnerToken))) return null;
|
|
3797
|
+
return candidate;
|
|
3798
|
+
}
|
|
3799
|
+
function heartbeatPath(leasePath, token) {
|
|
3800
|
+
return path10.join(leasePath, `${HEARTBEAT_FILE_PREFIX}${token}.json`);
|
|
3801
|
+
}
|
|
3802
|
+
function reclaimPath(leasePath) {
|
|
3803
|
+
return path10.join(leasePath, RECLAIM_DIRECTORY_NAME2);
|
|
3804
|
+
}
|
|
3805
|
+
function refreshRequestPath(leasePath) {
|
|
3806
|
+
return path10.join(leasePath, REFRESH_REQUEST_FILE_NAME);
|
|
3807
|
+
}
|
|
3808
|
+
function readLeaseOwner(leasePath) {
|
|
3809
|
+
try {
|
|
3810
|
+
return parseOwner2(JSON.parse(readFileSync5(path10.join(leasePath, OWNER_FILE_NAME2), "utf-8")));
|
|
3811
|
+
} catch {
|
|
3812
|
+
return null;
|
|
3813
|
+
}
|
|
3814
|
+
}
|
|
3815
|
+
function readOwner(leasePath) {
|
|
3816
|
+
const owner = readLeaseOwner(leasePath);
|
|
3817
|
+
if (!owner) return null;
|
|
3818
|
+
try {
|
|
3819
|
+
const heartbeat = parseHeartbeat(
|
|
3820
|
+
JSON.parse(readFileSync5(heartbeatPath(leasePath, owner.token), "utf-8")),
|
|
3821
|
+
owner.token
|
|
3822
|
+
);
|
|
3823
|
+
return heartbeat ? { ...owner, heartbeatAt: heartbeat.heartbeatAt } : owner;
|
|
3824
|
+
} catch {
|
|
3825
|
+
return owner;
|
|
3826
|
+
}
|
|
3827
|
+
}
|
|
3828
|
+
function readReclaimOwner2(leasePath) {
|
|
3829
|
+
try {
|
|
3830
|
+
return parseReclaimOwner2(JSON.parse(readFileSync5(path10.join(reclaimPath(leasePath), OWNER_FILE_NAME2), "utf-8")));
|
|
3831
|
+
} catch {
|
|
3832
|
+
return null;
|
|
3833
|
+
}
|
|
3834
|
+
}
|
|
3835
|
+
function ownerLiveness(owner) {
|
|
3836
|
+
if (owner.hostname !== os3.hostname()) return "unknown";
|
|
3837
|
+
try {
|
|
3838
|
+
process.kill(owner.pid, 0);
|
|
3839
|
+
return "alive";
|
|
3840
|
+
} catch (error) {
|
|
3841
|
+
const code = getErrorCode2(error);
|
|
3842
|
+
if (code === "ESRCH") return "dead";
|
|
3843
|
+
if (code === "EPERM") return "alive";
|
|
3844
|
+
return "unknown";
|
|
3845
|
+
}
|
|
3846
|
+
}
|
|
3847
|
+
function isHeartbeatExpired(owner) {
|
|
3848
|
+
return Date.now() - Date.parse(owner.heartbeatAt) >= STALE_LEASE_MS;
|
|
3849
|
+
}
|
|
3850
|
+
function sameOwner2(left, right) {
|
|
3851
|
+
return left.pid === right.pid && left.hostname === right.hostname && left.token === right.token;
|
|
3852
|
+
}
|
|
3853
|
+
function writeHeartbeat(leasePath, owner) {
|
|
3854
|
+
const targetPath = heartbeatPath(leasePath, owner.token);
|
|
3855
|
+
const temporaryPath = `${targetPath}.tmp.${process.pid}.${owner.token}.${randomUUID2()}`;
|
|
3856
|
+
const heartbeat = {
|
|
3857
|
+
version: 1,
|
|
3858
|
+
token: owner.token,
|
|
3859
|
+
heartbeatAt: owner.heartbeatAt
|
|
3860
|
+
};
|
|
3861
|
+
try {
|
|
3862
|
+
writeFileSync2(temporaryPath, JSON.stringify(heartbeat), {
|
|
3863
|
+
encoding: "utf-8",
|
|
3864
|
+
flag: "wx",
|
|
3865
|
+
mode: 384
|
|
3866
|
+
});
|
|
3867
|
+
renameSync2(temporaryPath, targetPath);
|
|
3868
|
+
const currentOwner = readLeaseOwner(leasePath);
|
|
3869
|
+
return currentOwner !== null && sameOwner2(currentOwner, owner);
|
|
3870
|
+
} finally {
|
|
3871
|
+
if (existsSync6(temporaryPath)) rmSync2(temporaryPath, { force: true });
|
|
3872
|
+
}
|
|
3873
|
+
}
|
|
3874
|
+
function requestRefreshFromLeader(leasePath, allowDisabledAutoIndex) {
|
|
3875
|
+
const requestPath = refreshRequestPath(leasePath);
|
|
3876
|
+
const temporaryPath = `${requestPath}.tmp.${process.pid}.${randomUUID2()}`;
|
|
3877
|
+
try {
|
|
3878
|
+
const request = {
|
|
3879
|
+
allowDisabledAutoIndex,
|
|
3880
|
+
requestedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3881
|
+
version: 1
|
|
3882
|
+
};
|
|
3883
|
+
writeFileSync2(temporaryPath, JSON.stringify(request), {
|
|
3884
|
+
encoding: "utf-8",
|
|
3885
|
+
flag: "wx",
|
|
3886
|
+
mode: 384
|
|
3887
|
+
});
|
|
3888
|
+
renameSync2(temporaryPath, requestPath);
|
|
3889
|
+
} catch (error) {
|
|
3890
|
+
if (getErrorCode2(error) !== "ENOENT") {
|
|
3891
|
+
console.error("[codebase-index] Failed to request background index refresh from the project worker:", error);
|
|
3892
|
+
}
|
|
3893
|
+
} finally {
|
|
3894
|
+
if (existsSync6(temporaryPath)) rmSync2(temporaryPath, { force: true });
|
|
3895
|
+
}
|
|
3896
|
+
}
|
|
3897
|
+
function consumeRefreshRequest(leasePath) {
|
|
3898
|
+
const requestPath = refreshRequestPath(leasePath);
|
|
3899
|
+
const claimedPath = `${requestPath}.handling.${process.pid}.${randomUUID2()}`;
|
|
3900
|
+
try {
|
|
3901
|
+
renameSync2(requestPath, claimedPath);
|
|
3902
|
+
} catch (error) {
|
|
3903
|
+
if (getErrorCode2(error) === "ENOENT") return null;
|
|
3904
|
+
throw error;
|
|
3905
|
+
}
|
|
3906
|
+
try {
|
|
3907
|
+
const value = JSON.parse(readFileSync5(claimedPath, "utf-8"));
|
|
3908
|
+
return {
|
|
3909
|
+
allowDisabledAutoIndex: value.version === 1 && value.allowDisabledAutoIndex === true,
|
|
3910
|
+
requestedAt: typeof value.requestedAt === "string" ? value.requestedAt : (/* @__PURE__ */ new Date()).toISOString(),
|
|
3911
|
+
version: 1
|
|
3912
|
+
};
|
|
3913
|
+
} catch {
|
|
3914
|
+
return { allowDisabledAutoIndex: false, requestedAt: (/* @__PURE__ */ new Date()).toISOString(), version: 1 };
|
|
3915
|
+
} finally {
|
|
3916
|
+
rmSync2(claimedPath, { force: true });
|
|
3917
|
+
}
|
|
3918
|
+
}
|
|
3919
|
+
function publishLease(leasePath, owner) {
|
|
3920
|
+
const candidatePath = `${leasePath}.candidate.${process.pid}.${owner.token}`;
|
|
3921
|
+
try {
|
|
3922
|
+
mkdirSync2(candidatePath, { mode: 448 });
|
|
3923
|
+
} catch (error) {
|
|
3924
|
+
if (getErrorCode2(error) === "ENOENT") return false;
|
|
3925
|
+
throw error;
|
|
3926
|
+
}
|
|
3927
|
+
try {
|
|
3928
|
+
writeFileSync2(path10.join(candidatePath, OWNER_FILE_NAME2), JSON.stringify(owner), {
|
|
3929
|
+
encoding: "utf-8",
|
|
3930
|
+
flag: "wx",
|
|
3931
|
+
mode: 384
|
|
3932
|
+
});
|
|
3933
|
+
if (existsSync6(leasePath)) return false;
|
|
3934
|
+
try {
|
|
3935
|
+
renameSync2(candidatePath, leasePath);
|
|
3936
|
+
return true;
|
|
3937
|
+
} catch (error) {
|
|
3938
|
+
if (existsSync6(leasePath) || getErrorCode2(error) === "ENOENT") return false;
|
|
3939
|
+
throw error;
|
|
3940
|
+
}
|
|
3941
|
+
} finally {
|
|
3942
|
+
if (existsSync6(candidatePath)) rmSync2(candidatePath, { recursive: true, force: true });
|
|
3943
|
+
}
|
|
3944
|
+
}
|
|
3945
|
+
function sameReclaimOwner2(left, right) {
|
|
3946
|
+
return left.pid === right.pid && left.hostname === right.hostname && left.token === right.token && left.expectedOwnerToken === right.expectedOwnerToken;
|
|
3947
|
+
}
|
|
3948
|
+
function reclaimerLiveness(owner) {
|
|
3949
|
+
return ownerLiveness(owner);
|
|
3950
|
+
}
|
|
3951
|
+
function isReclaimMarkerExpired(leasePath, owner) {
|
|
3952
|
+
const startedAt = owner ? Date.parse(owner.startedAt) : (() => {
|
|
3953
|
+
try {
|
|
3954
|
+
return lstatSync2(reclaimPath(leasePath)).mtimeMs;
|
|
3955
|
+
} catch {
|
|
3956
|
+
return Date.now();
|
|
3957
|
+
}
|
|
3958
|
+
})();
|
|
3959
|
+
return Date.now() - startedAt >= STALE_LEASE_MS;
|
|
3960
|
+
}
|
|
3961
|
+
function hasActiveReclaimMarker(leasePath, owner) {
|
|
3962
|
+
const marker = readReclaimOwner2(leasePath);
|
|
3963
|
+
return marker !== null && marker.expectedOwnerToken === owner.token && (marker.hostname !== os3.hostname() || ownerLiveness(owner) !== "alive");
|
|
3964
|
+
}
|
|
3965
|
+
function publishReclaimMarker(leasePath, expectedOwner) {
|
|
3966
|
+
const markerPath = reclaimPath(leasePath);
|
|
3967
|
+
const owner = {
|
|
3968
|
+
version: 1,
|
|
3969
|
+
pid: process.pid,
|
|
3970
|
+
hostname: os3.hostname(),
|
|
3971
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3972
|
+
token: randomUUID2(),
|
|
3973
|
+
expectedOwnerToken: expectedOwner?.token ?? null
|
|
3974
|
+
};
|
|
3975
|
+
try {
|
|
3976
|
+
mkdirSync2(markerPath, { mode: 448 });
|
|
3977
|
+
} catch (error) {
|
|
3978
|
+
if (getErrorCode2(error) === "EEXIST" || getErrorCode2(error) === "ENOENT") return null;
|
|
3979
|
+
throw error;
|
|
3980
|
+
}
|
|
3981
|
+
try {
|
|
3982
|
+
writeFileSync2(path10.join(markerPath, OWNER_FILE_NAME2), JSON.stringify(owner), {
|
|
3983
|
+
encoding: "utf-8",
|
|
3984
|
+
flag: "wx",
|
|
3985
|
+
mode: 384
|
|
3986
|
+
});
|
|
3987
|
+
return owner;
|
|
3988
|
+
} catch (error) {
|
|
3989
|
+
rmSync2(markerPath, { recursive: true, force: true });
|
|
3990
|
+
throw error;
|
|
3991
|
+
}
|
|
3992
|
+
}
|
|
3993
|
+
function removeExpiredReclaimMarker(leasePath, expectedOwner) {
|
|
3994
|
+
const marker = readReclaimOwner2(leasePath);
|
|
3995
|
+
const markerPath = reclaimPath(leasePath);
|
|
3996
|
+
if (!existsSync6(markerPath)) return false;
|
|
3997
|
+
if (marker && marker.expectedOwnerToken !== (expectedOwner?.token ?? null)) return false;
|
|
3998
|
+
if (marker && (reclaimerLiveness(marker) === "alive" || !isReclaimMarkerExpired(leasePath, marker))) return false;
|
|
3999
|
+
if (!marker && !isReclaimMarkerExpired(leasePath, null)) return false;
|
|
4000
|
+
const staleMarkerPath = `${markerPath}.stale.${marker?.pid ?? process.pid}.${marker?.token ?? randomUUID2()}.${randomUUID2()}`;
|
|
4001
|
+
try {
|
|
4002
|
+
renameSync2(markerPath, staleMarkerPath);
|
|
4003
|
+
} catch (error) {
|
|
4004
|
+
if (getErrorCode2(error) === "ENOENT") return false;
|
|
4005
|
+
throw error;
|
|
4006
|
+
}
|
|
4007
|
+
try {
|
|
4008
|
+
let claimedMarker = null;
|
|
4009
|
+
try {
|
|
4010
|
+
claimedMarker = parseReclaimOwner2(
|
|
4011
|
+
JSON.parse(readFileSync5(path10.join(staleMarkerPath, OWNER_FILE_NAME2), "utf-8"))
|
|
4012
|
+
);
|
|
4013
|
+
} catch {
|
|
4014
|
+
claimedMarker = null;
|
|
4015
|
+
}
|
|
4016
|
+
const markerMatches = marker ? claimedMarker !== null && sameReclaimOwner2(claimedMarker, marker) : claimedMarker === null;
|
|
4017
|
+
if (!markerMatches || !canReclaimLease(leasePath, expectedOwner)) {
|
|
4018
|
+
if (!existsSync6(markerPath) && existsSync6(staleMarkerPath)) renameSync2(staleMarkerPath, markerPath);
|
|
4019
|
+
return false;
|
|
4020
|
+
}
|
|
4021
|
+
rmSync2(staleMarkerPath, { recursive: true, force: true });
|
|
4022
|
+
return true;
|
|
4023
|
+
} catch (error) {
|
|
4024
|
+
if (getErrorCode2(error) === "ENOENT") return false;
|
|
4025
|
+
throw error;
|
|
4026
|
+
}
|
|
4027
|
+
}
|
|
4028
|
+
function canReclaimLease(leasePath, expectedOwner) {
|
|
4029
|
+
if (!existsSync6(leasePath)) return false;
|
|
4030
|
+
if (!expectedOwner) return false;
|
|
4031
|
+
const currentOwner = readOwner(leasePath);
|
|
4032
|
+
if (!currentOwner || !sameOwner2(currentOwner, expectedOwner)) return false;
|
|
4033
|
+
if (currentOwner.hostname === os3.hostname()) {
|
|
4034
|
+
return ownerLiveness(currentOwner) === "dead";
|
|
4035
|
+
}
|
|
4036
|
+
return isHeartbeatExpired(currentOwner);
|
|
4037
|
+
}
|
|
4038
|
+
function reclaimLease(leasePath, expectedOwner) {
|
|
4039
|
+
let marker = null;
|
|
4040
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
4041
|
+
marker = publishReclaimMarker(leasePath, expectedOwner);
|
|
4042
|
+
if (marker) break;
|
|
4043
|
+
if (attempt === 0 && removeExpiredReclaimMarker(leasePath, expectedOwner)) continue;
|
|
4044
|
+
return false;
|
|
4045
|
+
}
|
|
4046
|
+
if (!marker) return false;
|
|
4047
|
+
const markerPath = reclaimPath(leasePath);
|
|
4048
|
+
try {
|
|
4049
|
+
const currentMarker = readReclaimOwner2(leasePath);
|
|
4050
|
+
if (!currentMarker || !sameReclaimOwner2(currentMarker, marker) || !canReclaimLease(leasePath, expectedOwner)) {
|
|
4051
|
+
return false;
|
|
4052
|
+
}
|
|
4053
|
+
const stalePath = `${leasePath}.stale.${process.pid}.${marker.token}`;
|
|
4054
|
+
renameSync2(leasePath, stalePath);
|
|
4055
|
+
const quarantinedOwner = readOwner(stalePath);
|
|
4056
|
+
const quarantinedMarker = readReclaimOwner2(stalePath);
|
|
4057
|
+
if (!quarantinedMarker || !sameReclaimOwner2(quarantinedMarker, marker) || expectedOwner !== null && (!quarantinedOwner || !sameOwner2(quarantinedOwner, expectedOwner))) {
|
|
4058
|
+
if (!existsSync6(leasePath) && existsSync6(stalePath)) renameSync2(stalePath, leasePath);
|
|
4059
|
+
return false;
|
|
4060
|
+
}
|
|
4061
|
+
rmSync2(stalePath, { recursive: true, force: true });
|
|
4062
|
+
return true;
|
|
4063
|
+
} catch (error) {
|
|
4064
|
+
if (getErrorCode2(error) === "ENOENT") return false;
|
|
4065
|
+
throw error;
|
|
4066
|
+
} finally {
|
|
4067
|
+
const currentMarker = readReclaimOwner2(leasePath);
|
|
4068
|
+
if (currentMarker && sameReclaimOwner2(currentMarker, marker)) {
|
|
4069
|
+
rmSync2(markerPath, { recursive: true, force: true });
|
|
4070
|
+
}
|
|
4071
|
+
}
|
|
4072
|
+
}
|
|
4073
|
+
function acquireLease(identity) {
|
|
4074
|
+
mkdirSync2(identity.canonicalIndexPath, { recursive: true, mode: 448 });
|
|
4075
|
+
const canonicalIndexPath = realpathSync3.native(identity.canonicalIndexPath);
|
|
4076
|
+
const leasePath = path10.join(canonicalIndexPath, leaseDirectoryName({ ...identity, canonicalIndexPath }));
|
|
4077
|
+
for (let attempt = 0; attempt < 4; attempt += 1) {
|
|
4078
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
4079
|
+
const owner = {
|
|
4080
|
+
version: 1,
|
|
4081
|
+
pid: process.pid,
|
|
4082
|
+
hostname: os3.hostname(),
|
|
4083
|
+
startedAt: timestamp,
|
|
4084
|
+
heartbeatAt: timestamp,
|
|
4085
|
+
projectRoot: identity.canonicalProjectRoot,
|
|
4086
|
+
indexPath: canonicalIndexPath,
|
|
4087
|
+
token: randomUUID2()
|
|
4088
|
+
};
|
|
4089
|
+
if (publishLease(leasePath, owner)) {
|
|
4090
|
+
return { leasePath, owner };
|
|
4091
|
+
}
|
|
4092
|
+
const existingOwner = readOwner(leasePath);
|
|
4093
|
+
if (existingOwner) {
|
|
4094
|
+
if (canReclaimLease(leasePath, existingOwner) && reclaimLease(leasePath, existingOwner)) continue;
|
|
4095
|
+
return null;
|
|
4096
|
+
}
|
|
4097
|
+
return null;
|
|
4098
|
+
}
|
|
4099
|
+
return null;
|
|
4100
|
+
}
|
|
4101
|
+
function releaseLease(lease) {
|
|
4102
|
+
const currentOwner = readOwner(lease.leasePath);
|
|
4103
|
+
if (!currentOwner || !sameOwner2(currentOwner, lease.owner)) return false;
|
|
4104
|
+
const releasePath = `${lease.leasePath}.release.${lease.owner.pid}.${lease.owner.token}`;
|
|
4105
|
+
try {
|
|
4106
|
+
renameSync2(lease.leasePath, releasePath);
|
|
4107
|
+
} catch (error) {
|
|
4108
|
+
if (getErrorCode2(error) === "ENOENT") return false;
|
|
4109
|
+
throw error;
|
|
4110
|
+
}
|
|
4111
|
+
const claimedOwner = readOwner(releasePath);
|
|
4112
|
+
if (!claimedOwner || !sameOwner2(claimedOwner, lease.owner)) {
|
|
4113
|
+
if (!existsSync6(lease.leasePath) && existsSync6(releasePath)) {
|
|
4114
|
+
renameSync2(releasePath, lease.leasePath);
|
|
4115
|
+
}
|
|
4116
|
+
return false;
|
|
4117
|
+
}
|
|
4118
|
+
rmSync2(releasePath, { recursive: true, force: true });
|
|
4119
|
+
return true;
|
|
4120
|
+
}
|
|
4121
|
+
var BackgroundWorkerController = class {
|
|
4122
|
+
constructor(projectRoot, host, config, hooks, identity) {
|
|
4123
|
+
this.projectRoot = projectRoot;
|
|
4124
|
+
this.host = host;
|
|
4125
|
+
this.config = config;
|
|
4126
|
+
this.hooks = hooks;
|
|
4127
|
+
this.identity = identity;
|
|
4128
|
+
}
|
|
4129
|
+
projectRoot;
|
|
4130
|
+
host;
|
|
4131
|
+
config;
|
|
4132
|
+
hooks;
|
|
4133
|
+
identity;
|
|
4134
|
+
lease = null;
|
|
4135
|
+
watcher = null;
|
|
4136
|
+
leaderReady = Promise.resolve();
|
|
4137
|
+
heartbeatTimer = null;
|
|
4138
|
+
retryTimer = null;
|
|
4139
|
+
teardownRetryTimer = null;
|
|
4140
|
+
transition = Promise.resolve();
|
|
4141
|
+
stopPromise = null;
|
|
4142
|
+
stopped = false;
|
|
4143
|
+
stopping = false;
|
|
4144
|
+
losingLeadership = false;
|
|
4145
|
+
restartAfterStop = false;
|
|
4146
|
+
leaderWorkStopped = false;
|
|
4147
|
+
startingLeaderWork = false;
|
|
4148
|
+
stopAutoIndexOnTeardown = true;
|
|
4149
|
+
autoIndexStarted = false;
|
|
4150
|
+
reportedError = null;
|
|
4151
|
+
update(config, hooks, options) {
|
|
4152
|
+
const autoIndexWasEnabled = this.config.indexing.autoIndex;
|
|
4153
|
+
const shouldReplaceWatcher = this.watcher !== null && hooks.watcherFactory !== void 0 && (hooks.watcherFactory === null || hooks.replaceWatcher === true);
|
|
4154
|
+
this.config = config;
|
|
4155
|
+
this.hooks = {
|
|
4156
|
+
...this.hooks,
|
|
4157
|
+
...hooks,
|
|
4158
|
+
watcherFactory: hooks.watcherFactory === void 0 ? this.hooks.watcherFactory : hooks.watcherFactory,
|
|
4159
|
+
watcherFactoryForConfig: hooks.watcherFactoryForConfig === void 0 ? this.hooks.watcherFactoryForConfig : hooks.watcherFactoryForConfig
|
|
4160
|
+
};
|
|
4161
|
+
if (autoIndexWasEnabled && !config.indexing.autoIndex || options.restartAutoIndex === true && config.indexing.autoIndex && !this.startingLeaderWork) {
|
|
4162
|
+
this.autoIndexStarted = false;
|
|
4163
|
+
}
|
|
4164
|
+
if (!this.canRun()) {
|
|
4165
|
+
void this.stop().catch((error) => {
|
|
4166
|
+
console.error("[codebase-index] Failed to stop background worker after disabling automatic work:", error);
|
|
4167
|
+
});
|
|
4168
|
+
return;
|
|
4169
|
+
}
|
|
4170
|
+
if (shouldReplaceWatcher) {
|
|
4171
|
+
void this.enqueue(async () => {
|
|
4172
|
+
const watcher = this.watcher;
|
|
4173
|
+
if (watcher) {
|
|
4174
|
+
await watcher.stop();
|
|
4175
|
+
if (this.watcher === watcher) this.watcher = null;
|
|
4176
|
+
}
|
|
4177
|
+
if (this.lease && !this.stopped) this.startLeaderWork();
|
|
4178
|
+
}).catch((error) => {
|
|
4179
|
+
console.error("[codebase-index] Failed to replace background file watcher:", error);
|
|
4180
|
+
});
|
|
4181
|
+
}
|
|
4182
|
+
this.start();
|
|
4183
|
+
}
|
|
4184
|
+
startAfter(activation) {
|
|
4185
|
+
this.transition = activation.catch(() => void 0);
|
|
4186
|
+
this.start();
|
|
4187
|
+
}
|
|
4188
|
+
start() {
|
|
4189
|
+
if (!this.canRun() || this.losingLeadership) return;
|
|
4190
|
+
if (this.stopping) {
|
|
4191
|
+
this.restartAfterStop = true;
|
|
4192
|
+
return;
|
|
4193
|
+
}
|
|
4194
|
+
this.stopped = false;
|
|
4195
|
+
void this.enqueue(async () => {
|
|
4196
|
+
if (this.stopped || this.stopping || this.losingLeadership || !this.canRun()) return;
|
|
4197
|
+
if (!this.lease) {
|
|
4198
|
+
try {
|
|
4199
|
+
this.lease = acquireLease(this.identity);
|
|
4200
|
+
this.reportedError = null;
|
|
4201
|
+
} catch (error) {
|
|
4202
|
+
this.reportAcquireError(error);
|
|
4203
|
+
this.scheduleRetry();
|
|
4204
|
+
return;
|
|
4205
|
+
}
|
|
4206
|
+
}
|
|
4207
|
+
if (!this.lease) {
|
|
4208
|
+
this.scheduleRetry();
|
|
4209
|
+
return;
|
|
4210
|
+
}
|
|
4211
|
+
this.startHeartbeat();
|
|
4212
|
+
this.startLeaderWork();
|
|
4213
|
+
});
|
|
4214
|
+
}
|
|
4215
|
+
waitForStart() {
|
|
4216
|
+
return this.transition.catch(() => void 0).then(() => this.leaderReady);
|
|
4217
|
+
}
|
|
4218
|
+
requestRefresh(allowDisabledAutoIndex = false) {
|
|
4219
|
+
this.start();
|
|
4220
|
+
if (!this.isLeader()) {
|
|
4221
|
+
requestRefreshFromLeader(leasePathFor(this.identity), allowDisabledAutoIndex);
|
|
4222
|
+
return;
|
|
4223
|
+
}
|
|
4224
|
+
void this.enqueue(async () => {
|
|
4225
|
+
if (this.stopped || !this.lease) return;
|
|
4226
|
+
this.hooks.startAutoIndex("retrieval", allowDisabledAutoIndex);
|
|
4227
|
+
});
|
|
4228
|
+
}
|
|
4229
|
+
isLeader() {
|
|
4230
|
+
return this.lease !== null && !this.stopping && !this.losingLeadership;
|
|
4231
|
+
}
|
|
4232
|
+
isStopping() {
|
|
4233
|
+
return this.stopping;
|
|
4234
|
+
}
|
|
4235
|
+
getHooksForConfig(config) {
|
|
4236
|
+
const watcherFactoryForConfig = this.hooks.watcherFactoryForConfig;
|
|
4237
|
+
if (!watcherFactoryForConfig) return this.hooks;
|
|
4238
|
+
return {
|
|
4239
|
+
...this.hooks,
|
|
4240
|
+
watcherFactory: watcherFactoryForConfig(config),
|
|
4241
|
+
replaceWatcher: true
|
|
4242
|
+
};
|
|
4243
|
+
}
|
|
4244
|
+
attachWatcher(watcherFactory, watcherFactoryForConfig) {
|
|
4245
|
+
if (this.hooks.watcherFactory !== void 0) return;
|
|
4246
|
+
this.hooks = {
|
|
4247
|
+
...this.hooks,
|
|
4248
|
+
watcherFactory,
|
|
4249
|
+
watcherFactoryForConfig: watcherFactoryForConfig ?? this.hooks.watcherFactoryForConfig
|
|
4250
|
+
};
|
|
4251
|
+
this.start();
|
|
4252
|
+
}
|
|
4253
|
+
async stop(stopAutoIndex = true) {
|
|
4254
|
+
if (this.stopPromise) return this.stopPromise;
|
|
4255
|
+
this.stopped = true;
|
|
4256
|
+
this.stopping = true;
|
|
4257
|
+
this.stopAutoIndexOnTeardown &&= stopAutoIndex;
|
|
4258
|
+
this.clearRetryTimer();
|
|
4259
|
+
const attempt = this.enqueue(async () => {
|
|
4260
|
+
try {
|
|
4261
|
+
const lease = this.lease;
|
|
4262
|
+
if (this.leaderWorkStopped) {
|
|
4263
|
+
if (lease) {
|
|
4264
|
+
this.releaseStoppedLease(lease);
|
|
4265
|
+
} else {
|
|
4266
|
+
this.finishStoppedLease();
|
|
4267
|
+
}
|
|
4268
|
+
return;
|
|
4269
|
+
}
|
|
4270
|
+
const hadLeaderWork = lease !== null || this.watcher !== null || this.autoIndexStarted;
|
|
4271
|
+
const stopped = await this.stopLeaderWork(hadLeaderWork && this.stopAutoIndexOnTeardown);
|
|
4272
|
+
if (!lease) {
|
|
4273
|
+
this.finishStoppedLease();
|
|
4274
|
+
return;
|
|
4275
|
+
}
|
|
4276
|
+
if (!stopped.completed) {
|
|
4277
|
+
this.releaseLeaseWhenAutoIndexStops(lease, stopped.completion);
|
|
4278
|
+
return;
|
|
4279
|
+
}
|
|
4280
|
+
this.leaderWorkStopped = true;
|
|
4281
|
+
this.releaseStoppedLease(lease);
|
|
4282
|
+
} catch (error) {
|
|
4283
|
+
this.scheduleTeardownRetry();
|
|
4284
|
+
throw error;
|
|
4285
|
+
}
|
|
4286
|
+
});
|
|
4287
|
+
const completion = attempt.finally(() => {
|
|
4288
|
+
if (this.stopPromise === completion) this.stopPromise = null;
|
|
4289
|
+
});
|
|
4290
|
+
this.stopPromise = completion;
|
|
4291
|
+
return completion;
|
|
4292
|
+
}
|
|
4293
|
+
canRun() {
|
|
4294
|
+
return this.config.indexing.autoIndex || this.hooks.watcherFactory != null;
|
|
4295
|
+
}
|
|
4296
|
+
enqueue(operation) {
|
|
4297
|
+
const next = this.transition.catch(() => void 0).then(operation);
|
|
4298
|
+
this.transition = next;
|
|
4299
|
+
return next;
|
|
4300
|
+
}
|
|
4301
|
+
startLeaderWork() {
|
|
4302
|
+
if (this.stopped || this.stopping || this.losingLeadership) return;
|
|
4303
|
+
this.startingLeaderWork = true;
|
|
4304
|
+
try {
|
|
4305
|
+
if (this.config.indexing.autoIndex && !this.autoIndexStarted) {
|
|
4306
|
+
this.autoIndexStarted = true;
|
|
4307
|
+
this.hooks.startAutoIndex("startup");
|
|
4308
|
+
}
|
|
4309
|
+
if (!this.watcher && this.hooks.watcherFactory) {
|
|
4310
|
+
try {
|
|
4311
|
+
const watcher = this.hooks.watcherFactory();
|
|
4312
|
+
this.watcher = watcher;
|
|
4313
|
+
this.leaderReady = watcher.whenReady?.().catch((error) => {
|
|
4314
|
+
console.error("[codebase-index] Failed while waiting for background file watcher startup:", error);
|
|
4315
|
+
}) ?? Promise.resolve();
|
|
4316
|
+
} catch (error) {
|
|
4317
|
+
console.error("[codebase-index] Failed to start background file watcher:", error);
|
|
4318
|
+
this.leaderReady = Promise.resolve();
|
|
4319
|
+
}
|
|
4320
|
+
}
|
|
4321
|
+
} finally {
|
|
4322
|
+
this.startingLeaderWork = false;
|
|
4323
|
+
}
|
|
4324
|
+
}
|
|
4325
|
+
async stopLeaderWork(stopAutoIndex) {
|
|
4326
|
+
const watcher = this.watcher;
|
|
4327
|
+
let watcherError;
|
|
4328
|
+
if (watcher) {
|
|
4329
|
+
try {
|
|
4330
|
+
await watcher.stop();
|
|
4331
|
+
if (this.watcher === watcher) this.watcher = null;
|
|
4332
|
+
} catch (error) {
|
|
4333
|
+
watcherError = error;
|
|
4334
|
+
}
|
|
4335
|
+
}
|
|
4336
|
+
let autoIndexError;
|
|
4337
|
+
let autoIndexStop = {
|
|
4338
|
+
completed: true,
|
|
4339
|
+
completion: Promise.resolve()
|
|
4340
|
+
};
|
|
4341
|
+
if (stopAutoIndex) {
|
|
4342
|
+
try {
|
|
4343
|
+
autoIndexStop = await this.hooks.stopAutoIndex();
|
|
4344
|
+
this.autoIndexStarted = false;
|
|
4345
|
+
} catch (error) {
|
|
4346
|
+
autoIndexError = error;
|
|
4347
|
+
}
|
|
4348
|
+
}
|
|
4349
|
+
if (watcherError !== void 0 || autoIndexError !== void 0) {
|
|
4350
|
+
throw new BackgroundWorkerStopError(watcherError, autoIndexError);
|
|
4351
|
+
}
|
|
4352
|
+
return autoIndexStop;
|
|
4353
|
+
}
|
|
4354
|
+
releaseLeaseWhenAutoIndexStops(lease, completion) {
|
|
4355
|
+
void completion.then(
|
|
4356
|
+
() => {
|
|
4357
|
+
void this.enqueue(async () => {
|
|
4358
|
+
if (this.lease !== lease || !this.stopping) return;
|
|
4359
|
+
this.leaderWorkStopped = true;
|
|
4360
|
+
this.releaseStoppedLease(lease);
|
|
4361
|
+
}).catch((error) => {
|
|
4362
|
+
console.error("[codebase-index] Failed to release background worker lease after automatic indexing stopped:", error);
|
|
4363
|
+
this.scheduleTeardownRetry();
|
|
4364
|
+
});
|
|
4365
|
+
},
|
|
4366
|
+
(error) => {
|
|
4367
|
+
console.error("[codebase-index] Failed while waiting for automatic indexing to stop:", error);
|
|
4368
|
+
this.scheduleTeardownRetry();
|
|
4369
|
+
}
|
|
4370
|
+
);
|
|
4371
|
+
}
|
|
4372
|
+
releaseStoppedLease(lease) {
|
|
4373
|
+
if (this.lease !== lease) {
|
|
4374
|
+
this.finishStoppedLease();
|
|
4375
|
+
return;
|
|
4376
|
+
}
|
|
4377
|
+
releaseLease(lease);
|
|
4378
|
+
this.lease = null;
|
|
4379
|
+
this.finishStoppedLease();
|
|
4380
|
+
}
|
|
4381
|
+
finishStoppedLease() {
|
|
4382
|
+
this.leaderWorkStopped = false;
|
|
4383
|
+
this.stopAutoIndexOnTeardown = true;
|
|
4384
|
+
this.stopping = false;
|
|
4385
|
+
this.clearTimers();
|
|
4386
|
+
this.restartAfterTeardown();
|
|
4387
|
+
if (!this.stopped || this.stopping) return;
|
|
4388
|
+
const projectKey = projectLookupKey(this.projectRoot, this.host);
|
|
4389
|
+
const key = controllerKey(this.identity, this.host);
|
|
4390
|
+
if (workers.get(key) === this) workers.delete(key);
|
|
4391
|
+
if (workerKeysByProject.get(projectKey) === key) workerKeysByProject.delete(projectKey);
|
|
4392
|
+
}
|
|
4393
|
+
startHeartbeat() {
|
|
4394
|
+
if (this.heartbeatTimer) return;
|
|
4395
|
+
const heartbeat = () => {
|
|
4396
|
+
void this.heartbeat();
|
|
4397
|
+
};
|
|
4398
|
+
this.heartbeatTimer = setInterval(heartbeat, HEARTBEAT_INTERVAL_MS);
|
|
4399
|
+
this.heartbeatTimer.unref?.();
|
|
4400
|
+
}
|
|
4401
|
+
async heartbeat() {
|
|
4402
|
+
const lease = this.lease;
|
|
4403
|
+
if (!lease || this.losingLeadership || this.stopped && !this.stopping) return;
|
|
4404
|
+
if (hasActiveReclaimMarker(lease.leasePath, lease.owner)) {
|
|
4405
|
+
await this.loseLeadership();
|
|
4406
|
+
return;
|
|
4407
|
+
}
|
|
4408
|
+
const currentOwner = readOwner(lease.leasePath);
|
|
4409
|
+
if (!currentOwner || !sameOwner2(currentOwner, lease.owner)) {
|
|
4410
|
+
await this.loseLeadership();
|
|
4411
|
+
return;
|
|
4412
|
+
}
|
|
4413
|
+
try {
|
|
4414
|
+
const nextOwner = { ...lease.owner, heartbeatAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
4415
|
+
if (!writeHeartbeat(lease.leasePath, nextOwner)) {
|
|
4416
|
+
await this.loseLeadership();
|
|
4417
|
+
return;
|
|
4418
|
+
}
|
|
4419
|
+
lease.owner = nextOwner;
|
|
4420
|
+
const refreshRequest = !this.stopping ? consumeRefreshRequest(lease.leasePath) : null;
|
|
4421
|
+
if (refreshRequest) {
|
|
4422
|
+
this.hooks.startAutoIndex("retrieval", refreshRequest.allowDisabledAutoIndex);
|
|
4423
|
+
}
|
|
4424
|
+
} catch (error) {
|
|
4425
|
+
const ownerAfterError = readOwner(lease.leasePath);
|
|
4426
|
+
if (hasActiveReclaimMarker(lease.leasePath, lease.owner) || !ownerAfterError || !sameOwner2(ownerAfterError, lease.owner)) {
|
|
4427
|
+
await this.loseLeadership();
|
|
4428
|
+
return;
|
|
4429
|
+
}
|
|
4430
|
+
console.error("[codebase-index] Failed to renew background worker lease:", error);
|
|
4431
|
+
}
|
|
4432
|
+
}
|
|
4433
|
+
async loseLeadership() {
|
|
4434
|
+
if (this.losingLeadership) return;
|
|
4435
|
+
this.losingLeadership = true;
|
|
4436
|
+
this.clearHeartbeat();
|
|
4437
|
+
await this.enqueue(async () => this.stopAfterLeadershipLoss());
|
|
4438
|
+
}
|
|
4439
|
+
async stopAfterLeadershipLoss() {
|
|
4440
|
+
const lease = this.lease;
|
|
4441
|
+
if (!lease) {
|
|
4442
|
+
this.losingLeadership = false;
|
|
4443
|
+
return;
|
|
4444
|
+
}
|
|
4445
|
+
try {
|
|
4446
|
+
const stopped = await this.stopLeaderWork(true);
|
|
4447
|
+
this.lease = null;
|
|
4448
|
+
this.losingLeadership = false;
|
|
4449
|
+
if (stopped.completed) {
|
|
4450
|
+
this.scheduleRetry();
|
|
4451
|
+
} else {
|
|
4452
|
+
void stopped.completion.then(() => this.scheduleRetry());
|
|
4453
|
+
}
|
|
4454
|
+
} catch (error) {
|
|
4455
|
+
console.error("[codebase-index] Failed to stop background work after losing its lease:", error);
|
|
4456
|
+
this.scheduleLostLeadershipTeardownRetry();
|
|
4457
|
+
}
|
|
4458
|
+
}
|
|
4459
|
+
scheduleRetry() {
|
|
4460
|
+
if (this.stopped || !this.canRun() || this.retryTimer) return;
|
|
4461
|
+
this.retryTimer = setTimeout(() => {
|
|
4462
|
+
this.retryTimer = null;
|
|
4463
|
+
this.start();
|
|
4464
|
+
}, RETRY_DELAY_MS);
|
|
4465
|
+
this.retryTimer.unref?.();
|
|
4466
|
+
}
|
|
4467
|
+
scheduleTeardownRetry() {
|
|
4468
|
+
if (!this.stopping || this.teardownRetryTimer) return;
|
|
4469
|
+
this.teardownRetryTimer = setTimeout(() => {
|
|
4470
|
+
this.teardownRetryTimer = null;
|
|
4471
|
+
void this.stop(this.stopAutoIndexOnTeardown).catch((error) => {
|
|
4472
|
+
console.error("[codebase-index] Failed to retry background worker teardown:", error);
|
|
4473
|
+
});
|
|
4474
|
+
}, RETRY_DELAY_MS);
|
|
4475
|
+
this.teardownRetryTimer.unref?.();
|
|
4476
|
+
}
|
|
4477
|
+
restartAfterTeardown() {
|
|
4478
|
+
if (!this.restartAfterStop || !this.canRun() || this.losingLeadership) return;
|
|
4479
|
+
this.restartAfterStop = false;
|
|
4480
|
+
this.stopped = false;
|
|
4481
|
+
this.start();
|
|
4482
|
+
}
|
|
4483
|
+
scheduleLostLeadershipTeardownRetry() {
|
|
4484
|
+
if (this.stopped || !this.losingLeadership || this.retryTimer) return;
|
|
4485
|
+
this.retryTimer = setTimeout(() => {
|
|
4486
|
+
this.retryTimer = null;
|
|
4487
|
+
void this.enqueue(async () => this.stopAfterLeadershipLoss());
|
|
4488
|
+
}, RETRY_DELAY_MS);
|
|
4489
|
+
this.retryTimer.unref?.();
|
|
4490
|
+
}
|
|
4491
|
+
clearHeartbeat() {
|
|
4492
|
+
if (!this.heartbeatTimer) return;
|
|
4493
|
+
clearInterval(this.heartbeatTimer);
|
|
4494
|
+
this.heartbeatTimer = null;
|
|
4495
|
+
}
|
|
4496
|
+
clearTimers() {
|
|
4497
|
+
this.clearHeartbeat();
|
|
4498
|
+
this.clearRetryTimer();
|
|
4499
|
+
if (this.teardownRetryTimer) {
|
|
4500
|
+
clearTimeout(this.teardownRetryTimer);
|
|
4501
|
+
this.teardownRetryTimer = null;
|
|
4502
|
+
}
|
|
4503
|
+
}
|
|
4504
|
+
clearRetryTimer() {
|
|
4505
|
+
if (!this.retryTimer) return;
|
|
4506
|
+
clearTimeout(this.retryTimer);
|
|
4507
|
+
this.retryTimer = null;
|
|
4508
|
+
}
|
|
4509
|
+
reportAcquireError(error) {
|
|
4510
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
4511
|
+
if (this.reportedError === message) return;
|
|
4512
|
+
this.reportedError = message;
|
|
4513
|
+
console.error("[codebase-index] Failed to acquire background worker lease:", error);
|
|
4514
|
+
}
|
|
4515
|
+
};
|
|
4516
|
+
function configureBackgroundWorker(projectRoot, host, config, hooks, options = {}) {
|
|
4517
|
+
const projectKey = projectLookupKey(projectRoot, host);
|
|
4518
|
+
const identity = resolveIdentity(projectRoot, config, host);
|
|
4519
|
+
const key = controllerKey(identity, host);
|
|
4520
|
+
const previousKey = workerKeysByProject.get(projectKey);
|
|
4521
|
+
if (previousKey && previousKey !== key) {
|
|
4522
|
+
const previous = workers.get(previousKey);
|
|
4523
|
+
const previousBarrier = workerReplacementBarriers.get(projectKey) ?? Promise.resolve();
|
|
4524
|
+
const stopPrevious = previous?.stop(options.stopPreviousAutoIndex ?? true) ?? Promise.resolve();
|
|
4525
|
+
const activation = Promise.all([previousBarrier, stopPrevious]).then(() => void 0);
|
|
4526
|
+
workerReplacementBarriers.set(projectKey, activation);
|
|
4527
|
+
workers.delete(previousKey);
|
|
4528
|
+
const worker2 = new BackgroundWorkerController(projectRoot, host, config, hooks, identity);
|
|
4529
|
+
worker2.startAfter(activation);
|
|
4530
|
+
workers.set(key, worker2);
|
|
4531
|
+
workerKeysByProject.set(projectKey, key);
|
|
4532
|
+
return;
|
|
4533
|
+
}
|
|
4534
|
+
let worker = workers.get(key);
|
|
4535
|
+
if (!worker) {
|
|
4536
|
+
worker = new BackgroundWorkerController(projectRoot, host, config, hooks, identity);
|
|
4537
|
+
workers.set(key, worker);
|
|
4538
|
+
} else {
|
|
4539
|
+
worker.update(config, hooks, options);
|
|
4540
|
+
}
|
|
4541
|
+
workerKeysByProject.set(projectKey, key);
|
|
4542
|
+
worker.start();
|
|
4543
|
+
}
|
|
4544
|
+
function updateBackgroundWorkerConfig(projectRoot, host, config) {
|
|
4545
|
+
const projectKey = projectLookupKey(projectRoot, host);
|
|
4546
|
+
const key = workerKeysByProject.get(projectKey);
|
|
4547
|
+
const worker = key ? workers.get(key) : void 0;
|
|
4548
|
+
if (!worker) return;
|
|
4549
|
+
configureBackgroundWorker(projectRoot, host, config, worker.getHooksForConfig(config), {
|
|
4550
|
+
stopPreviousAutoIndex: false,
|
|
4551
|
+
restartAutoIndex: true
|
|
4552
|
+
});
|
|
4553
|
+
}
|
|
4554
|
+
function waitForBackgroundWorkerStart(projectRoot, host) {
|
|
4555
|
+
const key = workerKeysByProject.get(projectLookupKey(projectRoot, host));
|
|
4556
|
+
return workers.get(key ?? "")?.waitForStart() ?? Promise.resolve();
|
|
4557
|
+
}
|
|
4558
|
+
function requestBackgroundWorkerRefresh(projectRoot, host, allowDisabledAutoIndex = false) {
|
|
4559
|
+
const key = workerKeysByProject.get(projectLookupKey(projectRoot, host));
|
|
4560
|
+
workers.get(key ?? "")?.requestRefresh(allowDisabledAutoIndex);
|
|
4561
|
+
}
|
|
4562
|
+
function isBackgroundWorkerManaged(projectRoot, host) {
|
|
4563
|
+
const key = workerKeysByProject.get(projectLookupKey(projectRoot, host));
|
|
4564
|
+
return key !== void 0 && workers.has(key);
|
|
4565
|
+
}
|
|
4566
|
+
function isBackgroundWorkerLeader(projectRoot, host) {
|
|
4567
|
+
const key = workerKeysByProject.get(projectLookupKey(projectRoot, host));
|
|
4568
|
+
return key !== void 0 && workers.get(key)?.isLeader() === true;
|
|
4569
|
+
}
|
|
4570
|
+
async function stopBackgroundWorker(projectRoot, host) {
|
|
4571
|
+
const projectKey = projectLookupKey(projectRoot, host);
|
|
4572
|
+
const key = workerKeysByProject.get(projectKey);
|
|
4573
|
+
const worker = key ? workers.get(key) : void 0;
|
|
4574
|
+
if (!worker) return;
|
|
4575
|
+
await worker.stop();
|
|
4576
|
+
}
|
|
4577
|
+
|
|
3695
4578
|
// src/utils/files.ts
|
|
3696
4579
|
var import_ignore = __toESM(require_ignore(), 1);
|
|
3697
|
-
import { existsSync as
|
|
3698
|
-
import * as
|
|
4580
|
+
import { existsSync as existsSync7, readFileSync as readFileSync6, promises as fsPromises } from "fs";
|
|
4581
|
+
import * as path11 from "path";
|
|
3699
4582
|
var PROJECT_MARKERS = [
|
|
3700
4583
|
".git",
|
|
3701
4584
|
"package.json",
|
|
@@ -3713,7 +4596,7 @@ var PROJECT_MARKERS = [
|
|
|
3713
4596
|
];
|
|
3714
4597
|
function hasProjectMarker(projectRoot) {
|
|
3715
4598
|
for (const marker of PROJECT_MARKERS) {
|
|
3716
|
-
if (
|
|
4599
|
+
if (existsSync7(path11.join(projectRoot, marker))) {
|
|
3717
4600
|
return true;
|
|
3718
4601
|
}
|
|
3719
4602
|
}
|
|
@@ -3740,33 +4623,53 @@ function createIgnoreFilter(projectRoot) {
|
|
|
3740
4623
|
"**/*build*/**"
|
|
3741
4624
|
];
|
|
3742
4625
|
ig.add(defaultIgnores);
|
|
3743
|
-
const gitignorePath =
|
|
3744
|
-
if (
|
|
3745
|
-
const gitignoreContent =
|
|
4626
|
+
const gitignorePath = path11.join(projectRoot, ".gitignore");
|
|
4627
|
+
if (existsSync7(gitignorePath)) {
|
|
4628
|
+
const gitignoreContent = readFileSync6(gitignorePath, "utf-8");
|
|
3746
4629
|
ig.add(gitignoreContent);
|
|
3747
4630
|
}
|
|
3748
4631
|
return ig;
|
|
3749
4632
|
}
|
|
3750
|
-
function
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
4633
|
+
function toPosixRelativePath(relativePath) {
|
|
4634
|
+
return relativePath.split(path11.sep).join("/");
|
|
4635
|
+
}
|
|
4636
|
+
function matchesAnyGlob(filePath, patterns) {
|
|
4637
|
+
const normalized = toPosixRelativePath(filePath);
|
|
4638
|
+
return patterns.some((pattern) => matchGlob(normalized, pattern));
|
|
4639
|
+
}
|
|
4640
|
+
function isExcludedByPatterns(relativePath, excludePatterns) {
|
|
4641
|
+
return matchesAnyGlob(relativePath, excludePatterns);
|
|
4642
|
+
}
|
|
4643
|
+
function isExcludedDirectory(relativePath, excludePatterns) {
|
|
4644
|
+
const normalized = toPosixRelativePath(relativePath);
|
|
4645
|
+
if (matchesAnyGlob(normalized, excludePatterns)) {
|
|
4646
|
+
return true;
|
|
3757
4647
|
}
|
|
3758
4648
|
for (const pattern of excludePatterns) {
|
|
3759
|
-
|
|
3760
|
-
|
|
4649
|
+
const posixPattern = toPosixRelativePath(pattern).replace(/\/+$/, "");
|
|
4650
|
+
if (!posixPattern.endsWith("/**")) {
|
|
4651
|
+
continue;
|
|
3761
4652
|
}
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
if (matchGlob(relativePath, pattern)) {
|
|
4653
|
+
const directoryPattern = posixPattern.slice(0, -3);
|
|
4654
|
+
if (directoryPattern && matchesAnyGlob(normalized, [directoryPattern])) {
|
|
3765
4655
|
return true;
|
|
3766
4656
|
}
|
|
3767
4657
|
}
|
|
3768
4658
|
return false;
|
|
3769
4659
|
}
|
|
4660
|
+
function shouldIncludeFile(filePath, projectRoot, includePatterns, excludePatterns, ignoreFilter) {
|
|
4661
|
+
const relativePath = toPosixRelativePath(path11.relative(projectRoot, filePath));
|
|
4662
|
+
if (hasFilteredPathSegment(relativePath, "/")) {
|
|
4663
|
+
return false;
|
|
4664
|
+
}
|
|
4665
|
+
if (ignoreFilter.ignores(relativePath)) {
|
|
4666
|
+
return false;
|
|
4667
|
+
}
|
|
4668
|
+
if (isExcludedByPatterns(relativePath, excludePatterns)) {
|
|
4669
|
+
return false;
|
|
4670
|
+
}
|
|
4671
|
+
return matchesAnyGlob(relativePath, includePatterns);
|
|
4672
|
+
}
|
|
3770
4673
|
function matchGlob(filePath, pattern) {
|
|
3771
4674
|
if (pattern.startsWith("**/")) {
|
|
3772
4675
|
const withoutPrefix = pattern.slice(3);
|
|
@@ -3787,8 +4690,8 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
|
|
|
3787
4690
|
const filesInDir = [];
|
|
3788
4691
|
const subdirs = [];
|
|
3789
4692
|
for (const entry of entries) {
|
|
3790
|
-
const fullPath =
|
|
3791
|
-
const relativePath =
|
|
4693
|
+
const fullPath = path11.join(dir, entry.name);
|
|
4694
|
+
const relativePath = toPosixRelativePath(path11.relative(projectRoot, fullPath));
|
|
3792
4695
|
if (isHiddenPathSegment(entry.name)) {
|
|
3793
4696
|
if (entry.isDirectory()) {
|
|
3794
4697
|
skipped.push({ path: relativePath, reason: "excluded" });
|
|
@@ -3806,6 +4709,10 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
|
|
|
3806
4709
|
continue;
|
|
3807
4710
|
}
|
|
3808
4711
|
if (entry.isDirectory()) {
|
|
4712
|
+
if (isExcludedDirectory(relativePath, excludePatterns)) {
|
|
4713
|
+
skipped.push({ path: relativePath, reason: "excluded" });
|
|
4714
|
+
continue;
|
|
4715
|
+
}
|
|
3809
4716
|
subdirs.push({ fullPath, relativePath });
|
|
3810
4717
|
} else if (entry.isFile()) {
|
|
3811
4718
|
const stat5 = await fsPromises.stat(fullPath);
|
|
@@ -3813,20 +4720,11 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
|
|
|
3813
4720
|
skipped.push({ path: relativePath, reason: "too_large" });
|
|
3814
4721
|
continue;
|
|
3815
4722
|
}
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
continue;
|
|
3820
|
-
}
|
|
3821
|
-
}
|
|
3822
|
-
let matched = false;
|
|
3823
|
-
for (const pattern of includePatterns) {
|
|
3824
|
-
if (matchGlob(relativePath, pattern)) {
|
|
3825
|
-
matched = true;
|
|
3826
|
-
break;
|
|
3827
|
-
}
|
|
4723
|
+
if (isExcludedByPatterns(relativePath, excludePatterns)) {
|
|
4724
|
+
skipped.push({ path: relativePath, reason: "excluded" });
|
|
4725
|
+
continue;
|
|
3828
4726
|
}
|
|
3829
|
-
if (
|
|
4727
|
+
if (matchesAnyGlob(relativePath, includePatterns)) {
|
|
3830
4728
|
filesInDir.push({ path: fullPath, size: stat5.size });
|
|
3831
4729
|
}
|
|
3832
4730
|
}
|
|
@@ -3837,7 +4735,7 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
|
|
|
3837
4735
|
yield f;
|
|
3838
4736
|
}
|
|
3839
4737
|
for (let i = options.maxFilesPerDirectory; i < filesInDir.length; i++) {
|
|
3840
|
-
skipped.push({ path:
|
|
4738
|
+
skipped.push({ path: toPosixRelativePath(path11.relative(projectRoot, filesInDir[i].path)), reason: "excluded" });
|
|
3841
4739
|
}
|
|
3842
4740
|
const canRecurse = options.maxDepth === -1 || currentDepth < options.maxDepth;
|
|
3843
4741
|
if (canRecurse) {
|
|
@@ -3877,8 +4775,8 @@ async function collectFiles(projectRoot, includePatterns, excludePatterns, maxFi
|
|
|
3877
4775
|
if (additionalRoots && additionalRoots.length > 0) {
|
|
3878
4776
|
const normalizedRoots = /* @__PURE__ */ new Set();
|
|
3879
4777
|
for (const kbRoot of additionalRoots) {
|
|
3880
|
-
const resolved =
|
|
3881
|
-
|
|
4778
|
+
const resolved = path11.normalize(
|
|
4779
|
+
path11.isAbsolute(kbRoot) ? kbRoot : path11.resolve(projectRoot, kbRoot)
|
|
3882
4780
|
);
|
|
3883
4781
|
normalizedRoots.add(resolved);
|
|
3884
4782
|
}
|
|
@@ -3919,7 +4817,7 @@ function getErrorMessage(error) {
|
|
|
3919
4817
|
return error instanceof Error ? error.message : String(error);
|
|
3920
4818
|
}
|
|
3921
4819
|
function runCommand(file, args, options) {
|
|
3922
|
-
return new Promise((
|
|
4820
|
+
return new Promise((resolve18, reject) => {
|
|
3923
4821
|
childProcess.execFile(
|
|
3924
4822
|
file,
|
|
3925
4823
|
args,
|
|
@@ -3929,7 +4827,7 @@ function runCommand(file, args, options) {
|
|
|
3929
4827
|
reject(error);
|
|
3930
4828
|
return;
|
|
3931
4829
|
}
|
|
3932
|
-
|
|
4830
|
+
resolve18(stdout);
|
|
3933
4831
|
}
|
|
3934
4832
|
);
|
|
3935
4833
|
});
|
|
@@ -4021,29 +4919,29 @@ var AutoIndexCancelledError = class extends Error {
|
|
|
4021
4919
|
function now() {
|
|
4022
4920
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
4023
4921
|
}
|
|
4024
|
-
function
|
|
4025
|
-
const resolved =
|
|
4026
|
-
if (
|
|
4922
|
+
function canonicalizePath2(targetPath) {
|
|
4923
|
+
const resolved = path12.resolve(targetPath);
|
|
4924
|
+
if (existsSync8(resolved)) {
|
|
4027
4925
|
try {
|
|
4028
|
-
return
|
|
4926
|
+
return realpathSync4.native(resolved);
|
|
4029
4927
|
} catch {
|
|
4030
4928
|
return resolved;
|
|
4031
4929
|
}
|
|
4032
4930
|
}
|
|
4033
|
-
const parent =
|
|
4931
|
+
const parent = path12.dirname(resolved);
|
|
4034
4932
|
if (parent === resolved) return resolved;
|
|
4035
|
-
return
|
|
4933
|
+
return path12.join(canonicalizePath2(parent), path12.basename(resolved));
|
|
4036
4934
|
}
|
|
4037
4935
|
function isHomeDirectory(projectRoot) {
|
|
4038
|
-
return
|
|
4936
|
+
return canonicalizePath2(projectRoot) === canonicalizePath2(os4.homedir());
|
|
4039
4937
|
}
|
|
4040
|
-
function
|
|
4041
|
-
return `${host}::${
|
|
4938
|
+
function projectLookupKey2(projectRoot, host) {
|
|
4939
|
+
return `${host}::${canonicalizePath2(projectRoot)}`;
|
|
4042
4940
|
}
|
|
4043
4941
|
function coordinatorKey(projectRoot, config, host) {
|
|
4044
|
-
const canonicalProjectRoot =
|
|
4942
|
+
const canonicalProjectRoot = canonicalizePath2(projectRoot);
|
|
4045
4943
|
const indexPath = resolveProjectIndexPath(projectRoot, config.scope, host);
|
|
4046
|
-
return `${
|
|
4944
|
+
return `${canonicalizePath2(indexPath)}::${canonicalProjectRoot}`;
|
|
4047
4945
|
}
|
|
4048
4946
|
function getProjectSafety(projectRoot, config) {
|
|
4049
4947
|
if (isHomeDirectory(projectRoot)) {
|
|
@@ -4074,10 +4972,10 @@ function safeFailureMessage(error) {
|
|
|
4074
4972
|
}
|
|
4075
4973
|
function cancellableDelay(delayMs, signal) {
|
|
4076
4974
|
if (signal.aborted) return Promise.reject(new AutoIndexCancelledError());
|
|
4077
|
-
return new Promise((
|
|
4975
|
+
return new Promise((resolve18, reject) => {
|
|
4078
4976
|
const timer = setTimeout(() => {
|
|
4079
4977
|
signal.removeEventListener("abort", onAbort);
|
|
4080
|
-
|
|
4978
|
+
resolve18();
|
|
4081
4979
|
}, delayMs);
|
|
4082
4980
|
timer.unref?.();
|
|
4083
4981
|
const onAbort = () => {
|
|
@@ -4089,18 +4987,44 @@ function cancellableDelay(delayMs, signal) {
|
|
|
4089
4987
|
}
|
|
4090
4988
|
function withTimeout(promise, timeoutMs) {
|
|
4091
4989
|
if (timeoutMs <= 0) return Promise.resolve(void 0);
|
|
4092
|
-
return new Promise((
|
|
4093
|
-
const timer = setTimeout(() =>
|
|
4990
|
+
return new Promise((resolve18) => {
|
|
4991
|
+
const timer = setTimeout(() => resolve18(void 0), timeoutMs);
|
|
4094
4992
|
timer.unref?.();
|
|
4095
4993
|
void promise.then((value) => {
|
|
4096
4994
|
clearTimeout(timer);
|
|
4097
|
-
|
|
4995
|
+
resolve18(value);
|
|
4098
4996
|
}, () => {
|
|
4099
4997
|
clearTimeout(timer);
|
|
4100
|
-
|
|
4998
|
+
resolve18(void 0);
|
|
4101
4999
|
});
|
|
4102
5000
|
});
|
|
4103
5001
|
}
|
|
5002
|
+
function settlesWithin(promise, timeoutMs) {
|
|
5003
|
+
if (timeoutMs <= 0) return Promise.resolve(false);
|
|
5004
|
+
return new Promise((resolve18) => {
|
|
5005
|
+
let settled = false;
|
|
5006
|
+
const timer = setTimeout(() => {
|
|
5007
|
+
if (settled) return;
|
|
5008
|
+
settled = true;
|
|
5009
|
+
resolve18(false);
|
|
5010
|
+
}, timeoutMs);
|
|
5011
|
+
timer.unref?.();
|
|
5012
|
+
void promise.then(
|
|
5013
|
+
() => {
|
|
5014
|
+
if (settled) return;
|
|
5015
|
+
settled = true;
|
|
5016
|
+
clearTimeout(timer);
|
|
5017
|
+
resolve18(true);
|
|
5018
|
+
},
|
|
5019
|
+
() => {
|
|
5020
|
+
if (settled) return;
|
|
5021
|
+
settled = true;
|
|
5022
|
+
clearTimeout(timer);
|
|
5023
|
+
resolve18(true);
|
|
5024
|
+
}
|
|
5025
|
+
);
|
|
5026
|
+
});
|
|
5027
|
+
}
|
|
4104
5028
|
function requestPriority(request) {
|
|
4105
5029
|
if (request.force) return 4;
|
|
4106
5030
|
if (request.source === "manual") return 3;
|
|
@@ -4111,6 +5035,7 @@ function mergeRequests(current, next) {
|
|
|
4111
5035
|
if (!current) return next;
|
|
4112
5036
|
const preferred = requestPriority(next) > requestPriority(current) ? next : current;
|
|
4113
5037
|
return {
|
|
5038
|
+
allowDisabledAutoIndex: current.allowDisabledAutoIndex || next.allowDisabledAutoIndex,
|
|
4114
5039
|
checkFreshness: current.checkFreshness && next.checkFreshness,
|
|
4115
5040
|
force: current.force || next.force,
|
|
4116
5041
|
onProgress: next.onProgress ?? current.onProgress,
|
|
@@ -4172,11 +5097,11 @@ var AutoIndexCoordinator = class {
|
|
|
4172
5097
|
progress: this.status.progress ? { ...this.status.progress } : void 0
|
|
4173
5098
|
};
|
|
4174
5099
|
}
|
|
4175
|
-
start(source) {
|
|
5100
|
+
start(source, allowDisabledAutoIndex = false) {
|
|
4176
5101
|
this.refreshSafety();
|
|
4177
|
-
if (!this.registration.config.indexing.autoIndex || !this.registration.safeToRun) return null;
|
|
5102
|
+
if (!this.registration.config.indexing.autoIndex && !allowDisabledAutoIndex || !this.registration.safeToRun) return null;
|
|
4178
5103
|
if (this.status.state === "failed") return this.inFlight;
|
|
4179
|
-
return this.request({ checkFreshness: true, force: false, source });
|
|
5104
|
+
return this.request({ allowDisabledAutoIndex, checkFreshness: true, force: false, source });
|
|
4180
5105
|
}
|
|
4181
5106
|
request(request) {
|
|
4182
5107
|
if (this.stopped) {
|
|
@@ -4251,13 +5176,15 @@ var AutoIndexCoordinator = class {
|
|
|
4251
5176
|
retryAttempt: void 0
|
|
4252
5177
|
});
|
|
4253
5178
|
const inFlight = this.inFlight;
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
|
|
5179
|
+
const completion = inFlight ? inFlight.then(() => void 0, () => void 0) : Promise.resolve();
|
|
5180
|
+
if (!inFlight) {
|
|
5181
|
+
return { completed: true, completion };
|
|
5182
|
+
}
|
|
5183
|
+
if (waitForCompletion) {
|
|
5184
|
+
await completion;
|
|
5185
|
+
return { completed: true, completion };
|
|
4260
5186
|
}
|
|
5187
|
+
return { completed: await settlesWithin(completion, SHUTDOWN_WAIT_MS), completion };
|
|
4261
5188
|
}
|
|
4262
5189
|
startRequest(request) {
|
|
4263
5190
|
if (this.stopped || !this.canRun(request)) {
|
|
@@ -4446,7 +5373,7 @@ var AutoIndexCoordinator = class {
|
|
|
4446
5373
|
if (request.source === "manual" || request.source === "watcher") {
|
|
4447
5374
|
return true;
|
|
4448
5375
|
}
|
|
4449
|
-
return this.registration.safeToRun && this.registration.config.indexing.autoIndex;
|
|
5376
|
+
return this.registration.safeToRun && (this.registration.config.indexing.autoIndex || request.allowDisabledAutoIndex === true);
|
|
4450
5377
|
}
|
|
4451
5378
|
shouldDeferForBattery(request) {
|
|
4452
5379
|
return this.registration.backgroundIndexingPolicy !== null && (request.source === "startup" || request.source === "watcher");
|
|
@@ -4479,17 +5406,17 @@ var AutoIndexCoordinator = class {
|
|
|
4479
5406
|
}
|
|
4480
5407
|
}
|
|
4481
5408
|
waitForBatteryRetry(delayMs) {
|
|
4482
|
-
return new Promise((
|
|
5409
|
+
return new Promise((resolve18) => {
|
|
4483
5410
|
const timer = setTimeout(() => {
|
|
4484
5411
|
if (this.batteryRetryTimer === timer) {
|
|
4485
5412
|
this.batteryRetryTimer = null;
|
|
4486
5413
|
this.resolveBatteryRetry = null;
|
|
4487
5414
|
}
|
|
4488
|
-
|
|
5415
|
+
resolve18();
|
|
4489
5416
|
}, delayMs);
|
|
4490
5417
|
timer.unref?.();
|
|
4491
5418
|
this.batteryRetryTimer = timer;
|
|
4492
|
-
this.resolveBatteryRetry =
|
|
5419
|
+
this.resolveBatteryRetry = resolve18;
|
|
4493
5420
|
});
|
|
4494
5421
|
}
|
|
4495
5422
|
cancelBatteryRetry() {
|
|
@@ -4497,9 +5424,9 @@ var AutoIndexCoordinator = class {
|
|
|
4497
5424
|
clearTimeout(this.batteryRetryTimer);
|
|
4498
5425
|
this.batteryRetryTimer = null;
|
|
4499
5426
|
}
|
|
4500
|
-
const
|
|
5427
|
+
const resolve18 = this.resolveBatteryRetry;
|
|
4501
5428
|
this.resolveBatteryRetry = null;
|
|
4502
|
-
|
|
5429
|
+
resolve18?.();
|
|
4503
5430
|
}
|
|
4504
5431
|
finishBatteryCheck(batteryCheck) {
|
|
4505
5432
|
if (this.batteryCheck !== batteryCheck) return;
|
|
@@ -4512,12 +5439,25 @@ var AutoIndexCoordinator = class {
|
|
|
4512
5439
|
}
|
|
4513
5440
|
};
|
|
4514
5441
|
function getCoordinator(projectRoot, host) {
|
|
4515
|
-
const key = coordinatorKeysByProject.get(
|
|
5442
|
+
const key = coordinatorKeysByProject.get(projectLookupKey2(projectRoot, host));
|
|
4516
5443
|
return key ? coordinators.get(key) ?? null : null;
|
|
4517
5444
|
}
|
|
4518
|
-
function
|
|
4519
|
-
|
|
5445
|
+
function synchronizeBackgroundWorker(projectRoot, host, config, safeToRun) {
|
|
5446
|
+
if (safeToRun) {
|
|
5447
|
+
updateBackgroundWorkerConfig(projectRoot, host, config);
|
|
5448
|
+
return;
|
|
5449
|
+
}
|
|
5450
|
+
void stopBackgroundWorker(projectRoot, host).catch((error) => {
|
|
5451
|
+
console.error("[codebase-index] Failed to stop background worker after project safety changed:", error);
|
|
5452
|
+
});
|
|
5453
|
+
}
|
|
5454
|
+
function configureAutoIndex(projectRoot, host, config, getIndexer, options = {}) {
|
|
5455
|
+
const projectKey = projectLookupKey2(projectRoot, host);
|
|
4520
5456
|
const safety = getProjectSafety(projectRoot, config);
|
|
5457
|
+
const synchronizeWorker = options.synchronizeBackgroundWorker ?? true;
|
|
5458
|
+
if (options.preserveManagedWorker === true && isBackgroundWorkerManaged(projectRoot, host)) {
|
|
5459
|
+
return;
|
|
5460
|
+
}
|
|
4521
5461
|
const registration = {
|
|
4522
5462
|
backgroundIndexingPolicy: createBackgroundIndexingPolicy(
|
|
4523
5463
|
config.indexing.pauseBackgroundIndexingOnBattery
|
|
@@ -4535,6 +5475,9 @@ function configureAutoIndex(projectRoot, host, config, getIndexer) {
|
|
|
4535
5475
|
const stopPrevious = previousCoordinator?.stop(true) ?? Promise.resolve();
|
|
4536
5476
|
const activation = Promise.all([previousBarrier, stopPrevious]).then(() => void 0);
|
|
4537
5477
|
coordinatorReplacementBarriers.set(projectKey, activation);
|
|
5478
|
+
if (synchronizeWorker) {
|
|
5479
|
+
synchronizeBackgroundWorker(projectRoot, host, config, safety.safeToRun);
|
|
5480
|
+
}
|
|
4538
5481
|
coordinators.delete(previousKey);
|
|
4539
5482
|
const coordinator2 = new AutoIndexCoordinator(registration);
|
|
4540
5483
|
coordinator2.activateAfter(activation);
|
|
@@ -4550,11 +5493,17 @@ function configureAutoIndex(projectRoot, host, config, getIndexer) {
|
|
|
4550
5493
|
coordinator.update(registration);
|
|
4551
5494
|
}
|
|
4552
5495
|
coordinatorKeysByProject.set(projectKey, key);
|
|
5496
|
+
if (synchronizeWorker) {
|
|
5497
|
+
synchronizeBackgroundWorker(projectRoot, host, config, safety.safeToRun);
|
|
5498
|
+
}
|
|
4553
5499
|
}
|
|
4554
|
-
function
|
|
4555
|
-
return getCoordinator(projectRoot, host)?.start(source) ?? null;
|
|
5500
|
+
function startAutoIndexForBackgroundWorker(projectRoot, host, source = "startup", allowDisabledAutoIndex = false) {
|
|
5501
|
+
return getCoordinator(projectRoot, host)?.start(source, allowDisabledAutoIndex) ?? null;
|
|
4556
5502
|
}
|
|
4557
5503
|
function requestBackgroundIndex(projectRoot, host) {
|
|
5504
|
+
if (isBackgroundWorkerManaged(projectRoot, host) && !isBackgroundWorkerLeader(projectRoot, host)) {
|
|
5505
|
+
return null;
|
|
5506
|
+
}
|
|
4558
5507
|
return getCoordinator(projectRoot, host)?.request({
|
|
4559
5508
|
checkFreshness: false,
|
|
4560
5509
|
force: false,
|
|
@@ -4594,15 +5543,23 @@ async function waitForAutoIndexForRetrieval(projectRoot, host) {
|
|
|
4594
5543
|
};
|
|
4595
5544
|
}
|
|
4596
5545
|
try {
|
|
4597
|
-
|
|
5546
|
+
const readiness = await getSearchReadiness(coordinator);
|
|
5547
|
+
if (readiness.searchable) {
|
|
5548
|
+
return { ready: true };
|
|
5549
|
+
}
|
|
5550
|
+
if (readiness.blocked) return unavailableSnapshotResult(readiness.reason);
|
|
4598
5551
|
} catch {
|
|
4599
5552
|
}
|
|
4600
|
-
const job =
|
|
5553
|
+
const job = startRetrievalRefresh(projectRoot, host, coordinator);
|
|
4601
5554
|
if (job) {
|
|
4602
5555
|
await withTimeout(job, coordinator.getWaitMs());
|
|
5556
|
+
} else if (isBackgroundWorkerManaged(projectRoot, host)) {
|
|
5557
|
+
await waitForPublishedSnapshot(coordinator, coordinator.getWaitMs());
|
|
4603
5558
|
}
|
|
4604
5559
|
try {
|
|
4605
|
-
|
|
5560
|
+
const readiness = await getSearchReadiness(coordinator);
|
|
5561
|
+
if (readiness.searchable) return { ready: true };
|
|
5562
|
+
if (readiness.blocked) return unavailableSnapshotResult(readiness.reason);
|
|
4606
5563
|
} catch {
|
|
4607
5564
|
}
|
|
4608
5565
|
const status = coordinator.snapshot();
|
|
@@ -4623,18 +5580,52 @@ async function waitForAutoIndexForRetrieval(projectRoot, host) {
|
|
|
4623
5580
|
text: `Automatic indexing is ${status.state}. Retry shortly or call index_status for progress. You can also run index_codebase explicitly.`
|
|
4624
5581
|
};
|
|
4625
5582
|
}
|
|
4626
|
-
async function
|
|
5583
|
+
async function stopAutoIndexForBackgroundWorker(projectRoot, host, waitForCompletion = false) {
|
|
5584
|
+
const coordinator = getCoordinator(projectRoot, host);
|
|
5585
|
+
if (!coordinator) {
|
|
5586
|
+
return { completed: true, completion: Promise.resolve() };
|
|
5587
|
+
}
|
|
5588
|
+
return coordinator.stop(waitForCompletion);
|
|
5589
|
+
}
|
|
5590
|
+
async function getSearchReadiness(coordinator) {
|
|
4627
5591
|
const indexer = coordinator.getIndexer();
|
|
4628
5592
|
if (indexer.getIndexFreshness) {
|
|
4629
5593
|
const freshness = await indexer.getIndexFreshness();
|
|
4630
|
-
|
|
5594
|
+
const searchable = freshness.readable && freshness.current && freshness.reason === "current";
|
|
5595
|
+
return {
|
|
5596
|
+
blocked: freshness.reason === "unreadable" || freshness.reason === "incompatible" || freshness.reason === "failed-batches" || freshness.reason === "migration-required",
|
|
5597
|
+
reason: freshness.reason,
|
|
5598
|
+
searchable
|
|
5599
|
+
};
|
|
5600
|
+
}
|
|
5601
|
+
const indexed = (await indexer.getStatus()).indexed;
|
|
5602
|
+
return { blocked: false, searchable: indexed };
|
|
5603
|
+
}
|
|
5604
|
+
function unavailableSnapshotResult(reason) {
|
|
5605
|
+
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.";
|
|
5606
|
+
return {
|
|
5607
|
+
ready: false,
|
|
5608
|
+
text: `${detail} Run index_codebase before retrying retrieval.`
|
|
5609
|
+
};
|
|
5610
|
+
}
|
|
5611
|
+
function startRetrievalRefresh(projectRoot, host, coordinator) {
|
|
5612
|
+
if (isBackgroundWorkerManaged(projectRoot, host)) {
|
|
5613
|
+
requestBackgroundWorkerRefresh(projectRoot, host, true);
|
|
5614
|
+
return isBackgroundWorkerLeader(projectRoot, host) ? coordinator.currentJob() : null;
|
|
5615
|
+
}
|
|
5616
|
+
return coordinator.start("retrieval") ?? coordinator.currentJob();
|
|
5617
|
+
}
|
|
5618
|
+
async function waitForPublishedSnapshot(coordinator, waitMs) {
|
|
5619
|
+
const deadline = Date.now() + waitMs;
|
|
5620
|
+
while (Date.now() < deadline) {
|
|
5621
|
+
if ((await getSearchReadiness(coordinator)).searchable) return;
|
|
5622
|
+
await new Promise((resolve18) => setTimeout(resolve18, Math.min(250, deadline - Date.now())));
|
|
4631
5623
|
}
|
|
4632
|
-
return (await indexer.getStatus()).indexed;
|
|
4633
5624
|
}
|
|
4634
5625
|
|
|
4635
5626
|
// src/tools/config-state.ts
|
|
4636
|
-
import { existsSync as
|
|
4637
|
-
import * as
|
|
5627
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
5628
|
+
import * as path13 from "path";
|
|
4638
5629
|
function normalizeKnowledgeBasePaths(config, projectRoot) {
|
|
4639
5630
|
const normalized = { ...config };
|
|
4640
5631
|
if (Array.isArray(normalized.knowledgeBases)) {
|
|
@@ -4661,10 +5652,10 @@ function loadEditableConfig(projectRoot, host) {
|
|
|
4661
5652
|
}
|
|
4662
5653
|
function saveConfig(projectRoot, config, host) {
|
|
4663
5654
|
const configPath = getConfigPath(projectRoot, host);
|
|
4664
|
-
const configDir =
|
|
4665
|
-
const configBaseDir =
|
|
4666
|
-
if (!
|
|
4667
|
-
|
|
5655
|
+
const configDir = path13.dirname(configPath);
|
|
5656
|
+
const configBaseDir = path13.dirname(configDir);
|
|
5657
|
+
if (!existsSync9(configDir)) {
|
|
5658
|
+
mkdirSync3(configDir, { recursive: true });
|
|
4668
5659
|
}
|
|
4669
5660
|
const serializableConfig = { ...config };
|
|
4670
5661
|
if (Array.isArray(serializableConfig.knowledgeBases)) {
|
|
@@ -4672,12 +5663,12 @@ function saveConfig(projectRoot, config, host) {
|
|
|
4672
5663
|
(kb) => serializeConfigPathValue(kb, configBaseDir)
|
|
4673
5664
|
);
|
|
4674
5665
|
}
|
|
4675
|
-
|
|
5666
|
+
writeFileSync3(configPath, JSON.stringify(serializableConfig, null, 2) + "\n", "utf-8");
|
|
4676
5667
|
}
|
|
4677
5668
|
|
|
4678
5669
|
// src/indexer/index.ts
|
|
4679
|
-
import { existsSync as
|
|
4680
|
-
import * as
|
|
5670
|
+
import { existsSync as existsSync12, readFileSync as readFileSync9, statSync as statSync4, writeFileSync as writeFileSync4, renameSync as renameSync4, unlinkSync as unlinkSync2, mkdirSync as mkdirSync5, promises as fsPromises3 } from "fs";
|
|
5671
|
+
import * as path20 from "path";
|
|
4681
5672
|
import { performance as performance2 } from "perf_hooks";
|
|
4682
5673
|
import { execFile as execFile5 } from "child_process";
|
|
4683
5674
|
import { promisify as promisify4 } from "util";
|
|
@@ -4704,7 +5695,7 @@ function pTimeout(promise, options) {
|
|
|
4704
5695
|
} = options;
|
|
4705
5696
|
let timer;
|
|
4706
5697
|
let abortHandler;
|
|
4707
|
-
const wrappedPromise = new Promise((
|
|
5698
|
+
const wrappedPromise = new Promise((resolve18, reject) => {
|
|
4708
5699
|
if (typeof milliseconds !== "number" || Math.sign(milliseconds) !== 1) {
|
|
4709
5700
|
throw new TypeError(`Expected \`milliseconds\` to be a positive number, got \`${milliseconds}\``);
|
|
4710
5701
|
}
|
|
@@ -4718,7 +5709,7 @@ function pTimeout(promise, options) {
|
|
|
4718
5709
|
};
|
|
4719
5710
|
signal.addEventListener("abort", abortHandler, { once: true });
|
|
4720
5711
|
}
|
|
4721
|
-
promise.then(
|
|
5712
|
+
promise.then(resolve18, reject);
|
|
4722
5713
|
if (milliseconds === Number.POSITIVE_INFINITY) {
|
|
4723
5714
|
return;
|
|
4724
5715
|
}
|
|
@@ -4726,7 +5717,7 @@ function pTimeout(promise, options) {
|
|
|
4726
5717
|
timer = customTimers.setTimeout.call(void 0, () => {
|
|
4727
5718
|
if (fallback) {
|
|
4728
5719
|
try {
|
|
4729
|
-
|
|
5720
|
+
resolve18(fallback());
|
|
4730
5721
|
} catch (error) {
|
|
4731
5722
|
reject(error);
|
|
4732
5723
|
}
|
|
@@ -4736,7 +5727,7 @@ function pTimeout(promise, options) {
|
|
|
4736
5727
|
promise.cancel();
|
|
4737
5728
|
}
|
|
4738
5729
|
if (message === false) {
|
|
4739
|
-
|
|
5730
|
+
resolve18();
|
|
4740
5731
|
} else if (message instanceof Error) {
|
|
4741
5732
|
reject(message);
|
|
4742
5733
|
} else {
|
|
@@ -5138,7 +6129,7 @@ var PQueue = class extends import_index.default {
|
|
|
5138
6129
|
// Assign unique ID if not provided
|
|
5139
6130
|
id: options.id ?? (this.#idAssigner++).toString()
|
|
5140
6131
|
};
|
|
5141
|
-
return new Promise((
|
|
6132
|
+
return new Promise((resolve18, reject) => {
|
|
5142
6133
|
const taskSymbol = /* @__PURE__ */ Symbol(`task-${options.id}`);
|
|
5143
6134
|
let cleanupQueueAbortHandler = () => void 0;
|
|
5144
6135
|
const run = async () => {
|
|
@@ -5178,7 +6169,7 @@ var PQueue = class extends import_index.default {
|
|
|
5178
6169
|
})]);
|
|
5179
6170
|
}
|
|
5180
6171
|
const result = await operation;
|
|
5181
|
-
|
|
6172
|
+
resolve18(result);
|
|
5182
6173
|
this.emit("completed", result);
|
|
5183
6174
|
} catch (error) {
|
|
5184
6175
|
reject(error);
|
|
@@ -5366,13 +6357,13 @@ var PQueue = class extends import_index.default {
|
|
|
5366
6357
|
});
|
|
5367
6358
|
}
|
|
5368
6359
|
async #onEvent(event, filter) {
|
|
5369
|
-
return new Promise((
|
|
6360
|
+
return new Promise((resolve18) => {
|
|
5370
6361
|
const listener = () => {
|
|
5371
6362
|
if (filter && !filter()) {
|
|
5372
6363
|
return;
|
|
5373
6364
|
}
|
|
5374
6365
|
this.off(event, listener);
|
|
5375
|
-
|
|
6366
|
+
resolve18();
|
|
5376
6367
|
};
|
|
5377
6368
|
this.on(event, listener);
|
|
5378
6369
|
});
|
|
@@ -5658,7 +6649,7 @@ async function onAttemptFailure({ error, attemptNumber, retriesConsumed, startTi
|
|
|
5658
6649
|
const finalDelay = Math.min(delayTime, remainingTime);
|
|
5659
6650
|
options.signal?.throwIfAborted();
|
|
5660
6651
|
if (finalDelay > 0) {
|
|
5661
|
-
await new Promise((
|
|
6652
|
+
await new Promise((resolve18, reject) => {
|
|
5662
6653
|
const onAbort = () => {
|
|
5663
6654
|
clearTimeout(timeoutToken);
|
|
5664
6655
|
options.signal?.removeEventListener("abort", onAbort);
|
|
@@ -5666,7 +6657,7 @@ async function onAttemptFailure({ error, attemptNumber, retriesConsumed, startTi
|
|
|
5666
6657
|
};
|
|
5667
6658
|
const timeoutToken = setTimeout(() => {
|
|
5668
6659
|
options.signal?.removeEventListener("abort", onAbort);
|
|
5669
|
-
|
|
6660
|
+
resolve18();
|
|
5670
6661
|
}, finalDelay);
|
|
5671
6662
|
if (options.unref) {
|
|
5672
6663
|
timeoutToken.unref?.();
|
|
@@ -5727,17 +6718,17 @@ async function pRetry(input, options = {}) {
|
|
|
5727
6718
|
}
|
|
5728
6719
|
|
|
5729
6720
|
// src/embeddings/detector.ts
|
|
5730
|
-
import { existsSync as
|
|
5731
|
-
import * as
|
|
5732
|
-
import * as
|
|
6721
|
+
import { existsSync as existsSync10, readFileSync as readFileSync7 } from "fs";
|
|
6722
|
+
import * as path14 from "path";
|
|
6723
|
+
import * as os5 from "os";
|
|
5733
6724
|
function getOpenCodeAuthPath() {
|
|
5734
|
-
return
|
|
6725
|
+
return path14.join(os5.homedir(), ".local", "share", "opencode", "auth.json");
|
|
5735
6726
|
}
|
|
5736
6727
|
function loadOpenCodeAuth() {
|
|
5737
6728
|
const authPath = getOpenCodeAuthPath();
|
|
5738
6729
|
try {
|
|
5739
|
-
if (
|
|
5740
|
-
return JSON.parse(
|
|
6730
|
+
if (existsSync10(authPath)) {
|
|
6731
|
+
return JSON.parse(readFileSync7(authPath, "utf-8"));
|
|
5741
6732
|
}
|
|
5742
6733
|
} catch {
|
|
5743
6734
|
}
|
|
@@ -6028,17 +7019,17 @@ function validateExternalUrl(urlString) {
|
|
|
6028
7019
|
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
6029
7020
|
return { valid: false, reason: `Blocked protocol: ${parsed.protocol}` };
|
|
6030
7021
|
}
|
|
6031
|
-
const
|
|
6032
|
-
if (BLOCKED_HOSTNAMES.has(
|
|
6033
|
-
return { valid: false, reason: `Blocked: cloud metadata service (${
|
|
7022
|
+
const hostname3 = parsed.hostname.toLowerCase();
|
|
7023
|
+
if (BLOCKED_HOSTNAMES.has(hostname3)) {
|
|
7024
|
+
return { valid: false, reason: `Blocked: cloud metadata service (${hostname3})` };
|
|
6034
7025
|
}
|
|
6035
7026
|
for (const pattern of BLOCKED_METADATA_IPS) {
|
|
6036
|
-
if (pattern.test(
|
|
6037
|
-
return { valid: false, reason: `Blocked: cloud metadata IP (${
|
|
7027
|
+
if (pattern.test(hostname3)) {
|
|
7028
|
+
return { valid: false, reason: `Blocked: cloud metadata IP (${hostname3})` };
|
|
6038
7029
|
}
|
|
6039
7030
|
}
|
|
6040
|
-
if (/^169\.254\./.test(
|
|
6041
|
-
return { valid: false, reason: `Blocked: link-local address (${
|
|
7031
|
+
if (/^169\.254\./.test(hostname3)) {
|
|
7032
|
+
return { valid: false, reason: `Blocked: link-local address (${hostname3})` };
|
|
6042
7033
|
}
|
|
6043
7034
|
return { valid: true };
|
|
6044
7035
|
}
|
|
@@ -7130,8 +8121,8 @@ function extractParamNames(params) {
|
|
|
7130
8121
|
}
|
|
7131
8122
|
|
|
7132
8123
|
// src/native/binding.ts
|
|
7133
|
-
import * as
|
|
7134
|
-
import * as
|
|
8124
|
+
import * as os6 from "os";
|
|
8125
|
+
import * as path15 from "path";
|
|
7135
8126
|
import * as module from "module";
|
|
7136
8127
|
import { fileURLToPath } from "url";
|
|
7137
8128
|
|
|
@@ -7167,7 +8158,7 @@ var MCP_BINARY_CURRENT_NAME = CURRENT_PRODUCT.mcpBinary;
|
|
|
7167
8158
|
var STABLE_NATIVE_BINARY_NAME = IDENTITY_CATALOG.native.binaryName;
|
|
7168
8159
|
|
|
7169
8160
|
// src/native/binding.ts
|
|
7170
|
-
function getNativeBindingFilename(platform2 =
|
|
8161
|
+
function getNativeBindingFilename(platform2 = os6.platform(), arch2 = os6.arch()) {
|
|
7171
8162
|
if (platform2 === "darwin" && arch2 === "arm64") {
|
|
7172
8163
|
return `${STABLE_NATIVE_BINARY_NAME}.darwin-arm64.node`;
|
|
7173
8164
|
}
|
|
@@ -7185,25 +8176,25 @@ function getNativeBindingFilename(platform2 = os5.platform(), arch2 = os5.arch()
|
|
|
7185
8176
|
}
|
|
7186
8177
|
throw new Error(`Unsupported platform: ${platform2}-${arch2}`);
|
|
7187
8178
|
}
|
|
7188
|
-
function resolveNativeBindingPath(packageRoot, platform2 =
|
|
7189
|
-
return
|
|
8179
|
+
function resolveNativeBindingPath(packageRoot, platform2 = os6.platform(), arch2 = os6.arch()) {
|
|
8180
|
+
return path15.join(packageRoot, "native", getNativeBindingFilename(platform2, arch2));
|
|
7190
8181
|
}
|
|
7191
8182
|
function getNativeBinding() {
|
|
7192
8183
|
let currentDir;
|
|
7193
8184
|
let requireTarget;
|
|
7194
8185
|
if (typeof import.meta !== "undefined" && import.meta.url) {
|
|
7195
|
-
currentDir =
|
|
8186
|
+
currentDir = path15.dirname(fileURLToPath(import.meta.url));
|
|
7196
8187
|
requireTarget = import.meta.url;
|
|
7197
8188
|
} else if (typeof __dirname !== "undefined") {
|
|
7198
8189
|
currentDir = __dirname;
|
|
7199
8190
|
requireTarget = __filename;
|
|
7200
8191
|
} else {
|
|
7201
8192
|
currentDir = process.cwd();
|
|
7202
|
-
requireTarget =
|
|
8193
|
+
requireTarget = path15.join(currentDir, "index.js");
|
|
7203
8194
|
}
|
|
7204
8195
|
const normalizedDir = currentDir.replace(/\\/g, "/");
|
|
7205
|
-
const isDevMode = normalizedDir.includes("/src/native") || currentDir.includes(
|
|
7206
|
-
const packageRoot = isDevMode ?
|
|
8196
|
+
const isDevMode = normalizedDir.includes("/src/native") || currentDir.includes(path15.join("src", "native"));
|
|
8197
|
+
const packageRoot = isDevMode ? path15.resolve(currentDir, "../..") : path15.resolve(currentDir, "..");
|
|
7207
8198
|
const nativePath = resolveNativeBindingPath(packageRoot);
|
|
7208
8199
|
const require2 = module.createRequire(requireTarget);
|
|
7209
8200
|
return require2(nativePath);
|
|
@@ -7787,8 +8778,8 @@ var Database = class _Database {
|
|
|
7787
8778
|
|
|
7788
8779
|
// src/git/branch-materialization.ts
|
|
7789
8780
|
import { promises as fsPromises2 } from "fs";
|
|
7790
|
-
import * as
|
|
7791
|
-
import * as
|
|
8781
|
+
import * as os7 from "os";
|
|
8782
|
+
import * as path16 from "path";
|
|
7792
8783
|
|
|
7793
8784
|
// src/git/branch-resolution.ts
|
|
7794
8785
|
import { execFile as execFile2 } from "child_process";
|
|
@@ -8107,13 +9098,13 @@ async function isWorktreeRegistered(projectRoot, worktreePath) {
|
|
|
8107
9098
|
return false;
|
|
8108
9099
|
}
|
|
8109
9100
|
function isPathWithinRoot(filePath, rootPath) {
|
|
8110
|
-
const relative14 =
|
|
8111
|
-
return relative14 === "" || !relative14.startsWith(`..${
|
|
9101
|
+
const relative14 = path16.relative(path16.resolve(rootPath), path16.resolve(filePath));
|
|
9102
|
+
return relative14 === "" || !relative14.startsWith(`..${path16.sep}`) && relative14 !== ".." && !path16.isAbsolute(relative14);
|
|
8112
9103
|
}
|
|
8113
9104
|
async function pruneExactMissingWorktreeRegistration(projectRoot, worktreePath) {
|
|
8114
9105
|
if (await pathExists(worktreePath)) return false;
|
|
8115
9106
|
const commonDir = await runGit(projectRoot, ["rev-parse", "--path-format=absolute", "--git-common-dir"]);
|
|
8116
|
-
const registrationsRoot =
|
|
9107
|
+
const registrationsRoot = path16.join(commonDir, "worktrees");
|
|
8117
9108
|
let entries;
|
|
8118
9109
|
try {
|
|
8119
9110
|
entries = await fsPromises2.readdir(registrationsRoot, { withFileTypes: true });
|
|
@@ -8124,16 +9115,16 @@ async function pruneExactMissingWorktreeRegistration(projectRoot, worktreePath)
|
|
|
8124
9115
|
const target = canonicalizePathForComparison(worktreePath);
|
|
8125
9116
|
for (const entry of entries) {
|
|
8126
9117
|
if (!entry.isDirectory()) continue;
|
|
8127
|
-
const registrationPath =
|
|
9118
|
+
const registrationPath = path16.join(registrationsRoot, entry.name);
|
|
8128
9119
|
if (!isPathWithinRoot(registrationPath, registrationsRoot)) continue;
|
|
8129
9120
|
let gitdirPath;
|
|
8130
9121
|
try {
|
|
8131
|
-
gitdirPath = (await fsPromises2.readFile(
|
|
9122
|
+
gitdirPath = (await fsPromises2.readFile(path16.join(registrationPath, "gitdir"), "utf8")).trim();
|
|
8132
9123
|
} catch {
|
|
8133
9124
|
continue;
|
|
8134
9125
|
}
|
|
8135
|
-
const resolvedGitdirPath =
|
|
8136
|
-
if (canonicalizePathForComparison(
|
|
9126
|
+
const resolvedGitdirPath = path16.isAbsolute(gitdirPath) ? gitdirPath : path16.resolve(registrationPath, gitdirPath);
|
|
9127
|
+
if (canonicalizePathForComparison(path16.dirname(resolvedGitdirPath)) !== target) continue;
|
|
8137
9128
|
await fsPromises2.rm(registrationPath, { recursive: true, force: true });
|
|
8138
9129
|
return true;
|
|
8139
9130
|
}
|
|
@@ -8151,7 +9142,7 @@ async function removeWorktree(projectRoot, worktreePath) {
|
|
|
8151
9142
|
registered = await isWorktreeRegistered(projectRoot, worktreePath);
|
|
8152
9143
|
} catch (error) {
|
|
8153
9144
|
errors.push(asError(error));
|
|
8154
|
-
throw new AggregateError(errors, `Could not verify temporary worktree deregistration; preserved ${
|
|
9145
|
+
throw new AggregateError(errors, `Could not verify temporary worktree deregistration; preserved ${path16.dirname(worktreePath)}`);
|
|
8155
9146
|
}
|
|
8156
9147
|
if (registered) {
|
|
8157
9148
|
try {
|
|
@@ -8167,7 +9158,7 @@ async function removeWorktree(projectRoot, worktreePath) {
|
|
|
8167
9158
|
registered = await isWorktreeRegistered(projectRoot, worktreePath);
|
|
8168
9159
|
} catch (error) {
|
|
8169
9160
|
errors.push(asError(error));
|
|
8170
|
-
throw new AggregateError(errors, `Could not verify temporary worktree deregistration; preserved ${
|
|
9161
|
+
throw new AggregateError(errors, `Could not verify temporary worktree deregistration; preserved ${path16.dirname(worktreePath)}`);
|
|
8171
9162
|
}
|
|
8172
9163
|
}
|
|
8173
9164
|
if (registered && !await pathExists(worktreePath)) {
|
|
@@ -8180,13 +9171,13 @@ async function removeWorktree(projectRoot, worktreePath) {
|
|
|
8180
9171
|
}
|
|
8181
9172
|
if (registered) {
|
|
8182
9173
|
errors.push(new Error(`Temporary worktree remains registered: ${worktreePath}`));
|
|
8183
|
-
throw new AggregateError(errors, `Failed to deregister temporary worktree; preserved ${
|
|
9174
|
+
throw new AggregateError(errors, `Failed to deregister temporary worktree; preserved ${path16.dirname(worktreePath)}`);
|
|
8184
9175
|
}
|
|
8185
9176
|
try {
|
|
8186
|
-
await fsPromises2.rm(
|
|
9177
|
+
await fsPromises2.rm(path16.dirname(worktreePath), { recursive: true, force: true });
|
|
8187
9178
|
} catch (error) {
|
|
8188
9179
|
errors.push(asError(error));
|
|
8189
|
-
throw new AggregateError(errors, `Deregistered the temporary worktree but could not remove ${
|
|
9180
|
+
throw new AggregateError(errors, `Deregistered the temporary worktree but could not remove ${path16.dirname(worktreePath)}`);
|
|
8190
9181
|
}
|
|
8191
9182
|
}
|
|
8192
9183
|
async function cleanupTemporaryWorktree(projectRoot, worktreePath, temporaryRoot) {
|
|
@@ -8222,9 +9213,9 @@ async function withMaterializedBranch(request, callback) {
|
|
|
8222
9213
|
`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.`
|
|
8223
9214
|
);
|
|
8224
9215
|
}
|
|
8225
|
-
const temporaryRoot = await fsPromises2.mkdtemp(
|
|
8226
|
-
const worktreePath =
|
|
8227
|
-
const hooksPath =
|
|
9216
|
+
const temporaryRoot = await fsPromises2.mkdtemp(path16.join(os7.tmpdir(), "codebase-index-branch-"));
|
|
9217
|
+
const worktreePath = path16.join(temporaryRoot, "worktree");
|
|
9218
|
+
const hooksPath = path16.join(temporaryRoot, "hooks");
|
|
8228
9219
|
await fsPromises2.mkdir(hooksPath);
|
|
8229
9220
|
const info = {
|
|
8230
9221
|
branch: request.branch,
|
|
@@ -8275,8 +9266,8 @@ async function withMaterializedBranch(request, callback) {
|
|
|
8275
9266
|
|
|
8276
9267
|
// src/tools/changed-files.ts
|
|
8277
9268
|
import { execFile as execFile3 } from "child_process";
|
|
8278
|
-
import { realpathSync as
|
|
8279
|
-
import * as
|
|
9269
|
+
import { realpathSync as realpathSync5 } from "fs";
|
|
9270
|
+
import * as path17 from "path";
|
|
8280
9271
|
import { promisify as promisify2 } from "util";
|
|
8281
9272
|
var execFileAsync2 = promisify2(execFile3);
|
|
8282
9273
|
var GH_PR_VIEW_FIELDS = [
|
|
@@ -8418,9 +9409,9 @@ function getHeadRepositoryIdentity(data, host) {
|
|
|
8418
9409
|
return `${host}/${owner.toLowerCase()}/${repository.replace(/\.git$/i, "").toLowerCase()}`;
|
|
8419
9410
|
}
|
|
8420
9411
|
function getLocalRepositoryIdentity(projectRoot) {
|
|
8421
|
-
let canonicalRoot =
|
|
9412
|
+
let canonicalRoot = path17.resolve(projectRoot);
|
|
8422
9413
|
try {
|
|
8423
|
-
canonicalRoot =
|
|
9414
|
+
canonicalRoot = realpathSync5.native(canonicalRoot);
|
|
8424
9415
|
} catch {
|
|
8425
9416
|
}
|
|
8426
9417
|
return `local:${canonicalRoot}`;
|
|
@@ -8479,17 +9470,17 @@ async function getMergeBase(projectRoot, baseCommit, headCommit) {
|
|
|
8479
9470
|
return commit;
|
|
8480
9471
|
}
|
|
8481
9472
|
function normalizeFiles(rawFiles, projectRoot) {
|
|
8482
|
-
const root =
|
|
9473
|
+
const root = path17.resolve(projectRoot);
|
|
8483
9474
|
const seen = /* @__PURE__ */ new Set();
|
|
8484
9475
|
const result = [];
|
|
8485
9476
|
for (const raw of rawFiles) {
|
|
8486
9477
|
if (raw.length === 0) continue;
|
|
8487
|
-
const absolute =
|
|
8488
|
-
const relative14 =
|
|
8489
|
-
if (
|
|
9478
|
+
const absolute = path17.resolve(root, raw);
|
|
9479
|
+
const relative14 = path17.relative(root, absolute);
|
|
9480
|
+
if (path17.isAbsolute(raw) || relative14 === ".." || relative14.startsWith(`..${path17.sep}`) || path17.isAbsolute(relative14)) {
|
|
8490
9481
|
throw new Error(`Changed file escapes the project root: ${JSON.stringify(raw)}`);
|
|
8491
9482
|
}
|
|
8492
|
-
const cleaned = relative14.startsWith(`.${
|
|
9483
|
+
const cleaned = relative14.startsWith(`.${path17.sep}`) ? relative14.slice(2) : relative14;
|
|
8493
9484
|
if (!seen.has(cleaned)) {
|
|
8494
9485
|
seen.add(cleaned);
|
|
8495
9486
|
result.push(cleaned);
|
|
@@ -8500,7 +9491,7 @@ function normalizeFiles(rawFiles, projectRoot) {
|
|
|
8500
9491
|
|
|
8501
9492
|
// src/indexer/git-blame.ts
|
|
8502
9493
|
import { execFile as execFile4 } from "child_process";
|
|
8503
|
-
import * as
|
|
9494
|
+
import * as path18 from "path";
|
|
8504
9495
|
import { promisify as promisify3 } from "util";
|
|
8505
9496
|
var execFileAsync3 = promisify3(execFile4);
|
|
8506
9497
|
function parseGitBlamePorcelain(output) {
|
|
@@ -8538,7 +9529,7 @@ function parseGitBlamePorcelain(output) {
|
|
|
8538
9529
|
return Array.from(commits.values()).filter((commit) => commit.lines > 0).sort((a, b) => b.lines - a.lines || b.committedAt - a.committedAt)[0];
|
|
8539
9530
|
}
|
|
8540
9531
|
async function getChunkGitBlame(projectRoot, filePath, startLine, endLine) {
|
|
8541
|
-
const relativePath =
|
|
9532
|
+
const relativePath = path18.relative(projectRoot, filePath);
|
|
8542
9533
|
try {
|
|
8543
9534
|
const { stdout } = await execFileAsync3(
|
|
8544
9535
|
"git",
|
|
@@ -9117,8 +10108,8 @@ function pathSegmentsForAffinityMatch(filePath) {
|
|
|
9117
10108
|
if (segments.length === 0) {
|
|
9118
10109
|
return [];
|
|
9119
10110
|
}
|
|
9120
|
-
const
|
|
9121
|
-
const basenameWithoutExt =
|
|
10111
|
+
const basename10 = segments[segments.length - 1] ?? "";
|
|
10112
|
+
const basenameWithoutExt = basename10.replace(/\.[^/.]+$/u, "");
|
|
9122
10113
|
const normalizedSegments = segments.map((segment) => segment.toLowerCase());
|
|
9123
10114
|
return Array.from(/* @__PURE__ */ new Set([
|
|
9124
10115
|
...normalizedSegments,
|
|
@@ -9427,8 +10418,8 @@ function hasAllEmbeddingParts(parts, expectedPartCount) {
|
|
|
9427
10418
|
|
|
9428
10419
|
// src/indexer/failed-state-persistence.ts
|
|
9429
10420
|
import * as fs2 from "fs";
|
|
9430
|
-
import { createHash, randomBytes as randomBytes3 } from "crypto";
|
|
9431
|
-
import * as
|
|
10421
|
+
import { createHash as createHash2, randomBytes as randomBytes3 } from "crypto";
|
|
10422
|
+
import * as path19 from "path";
|
|
9432
10423
|
import { StringDecoder } from "string_decoder";
|
|
9433
10424
|
var CURRENT_FAILED_BATCH_VERSION = 1;
|
|
9434
10425
|
var DEFAULT_MALFORMED_LINE_ACTION = "skip";
|
|
@@ -9446,7 +10437,7 @@ function* readFailedBatchRecords(filePath, options = {}) {
|
|
|
9446
10437
|
function createFailedBatchWriter(targetPath) {
|
|
9447
10438
|
const temporaryPath = createTemporaryPath(targetPath);
|
|
9448
10439
|
let finalized = false;
|
|
9449
|
-
fs2.mkdirSync(
|
|
10440
|
+
fs2.mkdirSync(path19.dirname(targetPath), { recursive: true });
|
|
9450
10441
|
fs2.closeSync(fs2.openSync(temporaryPath, "w"));
|
|
9451
10442
|
const write = (record) => {
|
|
9452
10443
|
if (finalized) {
|
|
@@ -9465,7 +10456,7 @@ function createFailedBatchWriter(targetPath) {
|
|
|
9465
10456
|
if (lines.length === 0) {
|
|
9466
10457
|
return;
|
|
9467
10458
|
}
|
|
9468
|
-
fs2.mkdirSync(
|
|
10459
|
+
fs2.mkdirSync(path19.dirname(targetPath), { recursive: true });
|
|
9469
10460
|
fs2.appendFileSync(temporaryPath, `${lines.join("\n")}
|
|
9470
10461
|
`, "utf-8");
|
|
9471
10462
|
};
|
|
@@ -9473,7 +10464,7 @@ function createFailedBatchWriter(targetPath) {
|
|
|
9473
10464
|
if (finalized) {
|
|
9474
10465
|
return;
|
|
9475
10466
|
}
|
|
9476
|
-
fs2.mkdirSync(
|
|
10467
|
+
fs2.mkdirSync(path19.dirname(targetPath), { recursive: true });
|
|
9477
10468
|
fs2.renameSync(temporaryPath, targetPath);
|
|
9478
10469
|
finalized = true;
|
|
9479
10470
|
};
|
|
@@ -9619,10 +10610,10 @@ function stripLeadingBomAndWhitespace(value) {
|
|
|
9619
10610
|
return result;
|
|
9620
10611
|
}
|
|
9621
10612
|
function createTemporaryPath(targetPath) {
|
|
9622
|
-
const randomId =
|
|
9623
|
-
const targetDir =
|
|
9624
|
-
const baseName =
|
|
9625
|
-
return
|
|
10613
|
+
const randomId = createHash2("sha1").update(`${Date.now()}:${randomBytes3(8).toString("hex")}`).digest("hex");
|
|
10614
|
+
const targetDir = path19.dirname(targetPath);
|
|
10615
|
+
const baseName = path19.basename(targetPath);
|
|
10616
|
+
return path19.join(targetDir, `.${baseName}.${randomId}.tmp`);
|
|
9626
10617
|
}
|
|
9627
10618
|
function handleMalformedLine(filePath, lineNumber, line, error, options) {
|
|
9628
10619
|
const action = options.malformedLineAction ?? DEFAULT_MALFORMED_LINE_ACTION;
|
|
@@ -9868,9 +10859,9 @@ var SWIFT_PARSER_VERSION = "1";
|
|
|
9868
10859
|
var METAL_PARSER_VERSION = "1";
|
|
9869
10860
|
var SYMBOL_EXTRACTOR_VERSION = "1";
|
|
9870
10861
|
function isPathWithinRoot2(filePath, rootPath) {
|
|
9871
|
-
const normalizedFilePath =
|
|
9872
|
-
const normalizedRoot =
|
|
9873
|
-
return normalizedFilePath === normalizedRoot || normalizedFilePath.startsWith(`${normalizedRoot}${
|
|
10862
|
+
const normalizedFilePath = path20.resolve(filePath);
|
|
10863
|
+
const normalizedRoot = path20.resolve(rootPath);
|
|
10864
|
+
return normalizedFilePath === normalizedRoot || normalizedFilePath.startsWith(`${normalizedRoot}${path20.sep}`);
|
|
9874
10865
|
}
|
|
9875
10866
|
function promoteIdentifierMatches(query, combined, semanticCandidates, keywordCandidates, database, branchChunkIds, prioritizeSourcePaths = classifyQueryIntentRaw(query) === "source") {
|
|
9876
10867
|
if (combined.length === 0) {
|
|
@@ -10201,10 +11192,10 @@ function matchesHardSearchFilters(candidate, options, projectRoot) {
|
|
|
10201
11192
|
}
|
|
10202
11193
|
if (options?.directory) {
|
|
10203
11194
|
const candidatePath = canonicalizePathForComparison(
|
|
10204
|
-
|
|
11195
|
+
path20.resolve(projectRoot, candidate.metadata.filePath.replace(/\\/g, path20.sep))
|
|
10205
11196
|
);
|
|
10206
11197
|
const directoryPath = canonicalizePathForComparison(
|
|
10207
|
-
|
|
11198
|
+
path20.resolve(projectRoot, options.directory.trim().replace(/\\/g, path20.sep))
|
|
10208
11199
|
);
|
|
10209
11200
|
if (!isPathWithinRoot2(candidatePath, directoryPath)) return false;
|
|
10210
11201
|
}
|
|
@@ -10317,26 +11308,37 @@ var Indexer = class _Indexer {
|
|
|
10317
11308
|
return this.indexPathOverride ?? resolveProjectIndexPath(this.projectRoot, this.config.scope, this.host);
|
|
10318
11309
|
}
|
|
10319
11310
|
toCanonicalFilePath(filePath) {
|
|
10320
|
-
if (!
|
|
11311
|
+
if (!path20.isAbsolute(filePath)) {
|
|
10321
11312
|
return this.resolveStoredFilePath(filePath, this.projectRoot);
|
|
10322
11313
|
}
|
|
10323
|
-
if (
|
|
11314
|
+
if (path20.resolve(this.materializedProjectRoot) === path20.resolve(this.projectRoot) || !isPathWithinRoot2(filePath, this.materializedProjectRoot)) {
|
|
10324
11315
|
return filePath;
|
|
10325
11316
|
}
|
|
10326
|
-
return
|
|
11317
|
+
return path20.resolve(this.projectRoot, path20.relative(this.materializedProjectRoot, filePath));
|
|
10327
11318
|
}
|
|
10328
11319
|
toStoredFilePath(filePath) {
|
|
10329
11320
|
const canonicalFilePath = this.toCanonicalFilePath(filePath);
|
|
10330
11321
|
if (this.config.scope !== "project" || !isPathWithinRoot2(canonicalFilePath, this.projectRoot)) {
|
|
10331
11322
|
return canonicalFilePath;
|
|
10332
11323
|
}
|
|
10333
|
-
return
|
|
11324
|
+
return path20.relative(this.projectRoot, canonicalFilePath).split(path20.sep).join("/");
|
|
11325
|
+
}
|
|
11326
|
+
isStoredPathExcluded(storedPath) {
|
|
11327
|
+
let matchPath = storedPath.split(path20.sep).join("/");
|
|
11328
|
+
if (path20.isAbsolute(storedPath)) {
|
|
11329
|
+
const relativePath = path20.relative(this.projectRoot, storedPath).split(path20.sep).join("/");
|
|
11330
|
+
if (relativePath.startsWith("..") || path20.isAbsolute(relativePath)) {
|
|
11331
|
+
return false;
|
|
11332
|
+
}
|
|
11333
|
+
matchPath = relativePath;
|
|
11334
|
+
}
|
|
11335
|
+
return isExcludedByPatterns(matchPath, this.config.exclude);
|
|
10334
11336
|
}
|
|
10335
11337
|
resolveStoredFilePath(filePath, rootPath = this.projectRoot) {
|
|
10336
|
-
if (
|
|
11338
|
+
if (path20.isAbsolute(filePath)) {
|
|
10337
11339
|
return filePath;
|
|
10338
11340
|
}
|
|
10339
|
-
const resolvedPath =
|
|
11341
|
+
const resolvedPath = path20.resolve(rootPath, ...filePath.split("/"));
|
|
10340
11342
|
if (!isPathWithinRoot2(resolvedPath, rootPath)) {
|
|
10341
11343
|
throw new Error(`Stored project path escapes project root: ${JSON.stringify(filePath)}`);
|
|
10342
11344
|
}
|
|
@@ -10360,7 +11362,7 @@ var Indexer = class _Indexer {
|
|
|
10360
11362
|
}
|
|
10361
11363
|
toMaterializedFilePath(filePath) {
|
|
10362
11364
|
const storedFilePath = this.toStoredFilePath(filePath);
|
|
10363
|
-
if (
|
|
11365
|
+
if (path20.isAbsolute(storedFilePath)) {
|
|
10364
11366
|
return storedFilePath;
|
|
10365
11367
|
}
|
|
10366
11368
|
return this.resolveStoredFilePath(storedFilePath, this.materializedProjectRoot);
|
|
@@ -10377,10 +11379,10 @@ var Indexer = class _Indexer {
|
|
|
10377
11379
|
}
|
|
10378
11380
|
getRuntimeArtifactPath(fileName) {
|
|
10379
11381
|
const namespace = this.getRuntimeArtifactNamespace();
|
|
10380
|
-
if (!namespace) return
|
|
10381
|
-
const extension =
|
|
11382
|
+
if (!namespace) return path20.join(this.indexPath, fileName);
|
|
11383
|
+
const extension = path20.extname(fileName);
|
|
10382
11384
|
const baseName = fileName.slice(0, fileName.length - extension.length);
|
|
10383
|
-
return
|
|
11385
|
+
return path20.join(this.indexPath, `${baseName}.${namespace}${extension}`);
|
|
10384
11386
|
}
|
|
10385
11387
|
refreshRuntimeArtifactPaths() {
|
|
10386
11388
|
this.fileHashCachePath = this.getRuntimeArtifactPath("file-hashes.json");
|
|
@@ -10393,14 +11395,14 @@ var Indexer = class _Indexer {
|
|
|
10393
11395
|
getMaterializedKnowledgeBases() {
|
|
10394
11396
|
const canonicalProjectRoot = this.getCanonicalPath(this.projectRoot);
|
|
10395
11397
|
return this.config.knowledgeBases.map((knowledgeBase) => {
|
|
10396
|
-
const configuredPath =
|
|
11398
|
+
const configuredPath = path20.isAbsolute(knowledgeBase) ? knowledgeBase : path20.resolve(this.projectRoot, knowledgeBase);
|
|
10397
11399
|
const canonicalPath = this.getCanonicalPath(configuredPath);
|
|
10398
11400
|
if (!isPathWithinRoot2(canonicalPath, canonicalProjectRoot)) {
|
|
10399
11401
|
return canonicalPath;
|
|
10400
11402
|
}
|
|
10401
|
-
return
|
|
11403
|
+
return path20.resolve(
|
|
10402
11404
|
this.materializedProjectRoot,
|
|
10403
|
-
|
|
11405
|
+
path20.relative(canonicalProjectRoot, canonicalPath)
|
|
10404
11406
|
);
|
|
10405
11407
|
});
|
|
10406
11408
|
}
|
|
@@ -10408,7 +11410,7 @@ var Indexer = class _Indexer {
|
|
|
10408
11410
|
try {
|
|
10409
11411
|
return canonicalizePathForComparison(targetPath);
|
|
10410
11412
|
} catch {
|
|
10411
|
-
return
|
|
11413
|
+
return path20.resolve(targetPath);
|
|
10412
11414
|
}
|
|
10413
11415
|
}
|
|
10414
11416
|
getProjectIdentityHash(projectRoot) {
|
|
@@ -10489,7 +11491,7 @@ var Indexer = class _Indexer {
|
|
|
10489
11491
|
} catch (error) {
|
|
10490
11492
|
releaseError = error;
|
|
10491
11493
|
this.writerArtifactFingerprint = null;
|
|
10492
|
-
if (!
|
|
11494
|
+
if (!existsSync12(lease.lockPath) && this.activeIndexLease?.owner.token === lease.owner.token) {
|
|
10493
11495
|
this.activeIndexLease = null;
|
|
10494
11496
|
}
|
|
10495
11497
|
}
|
|
@@ -10507,12 +11509,12 @@ var Indexer = class _Indexer {
|
|
|
10507
11509
|
return this.activeIndexLease;
|
|
10508
11510
|
}
|
|
10509
11511
|
loadFileHashCache() {
|
|
10510
|
-
if (!
|
|
11512
|
+
if (!existsSync12(this.fileHashCachePath)) {
|
|
10511
11513
|
this.fileHashCache = /* @__PURE__ */ new Map();
|
|
10512
11514
|
return;
|
|
10513
11515
|
}
|
|
10514
11516
|
try {
|
|
10515
|
-
const data =
|
|
11517
|
+
const data = readFileSync9(this.fileHashCachePath, "utf-8");
|
|
10516
11518
|
const parsed = JSON.parse(data);
|
|
10517
11519
|
this.fileHashCache = new Map(Object.entries(parsed));
|
|
10518
11520
|
} catch (error) {
|
|
@@ -10534,24 +11536,24 @@ var Indexer = class _Indexer {
|
|
|
10534
11536
|
atomicWriteSync(targetPath, data) {
|
|
10535
11537
|
const lease = this.requireActiveLease();
|
|
10536
11538
|
const tempPath = createLeaseTemporaryPath(targetPath, lease.owner, "tmp");
|
|
10537
|
-
|
|
11539
|
+
mkdirSync5(path20.dirname(targetPath), { recursive: true });
|
|
10538
11540
|
try {
|
|
10539
|
-
|
|
10540
|
-
|
|
11541
|
+
writeFileSync4(tempPath, data);
|
|
11542
|
+
renameSync4(tempPath, targetPath);
|
|
10541
11543
|
} finally {
|
|
10542
11544
|
removeLeaseTemporaryPath(tempPath);
|
|
10543
11545
|
}
|
|
10544
11546
|
}
|
|
10545
11547
|
saveInvertedIndex(invertedIndex) {
|
|
10546
11548
|
this.atomicWriteSync(
|
|
10547
|
-
|
|
11549
|
+
path20.join(this.indexPath, "inverted-index.json"),
|
|
10548
11550
|
invertedIndex.serialize()
|
|
10549
11551
|
);
|
|
10550
11552
|
}
|
|
10551
11553
|
getScopedRoots(projectRoot = this.projectRoot) {
|
|
10552
11554
|
const roots = /* @__PURE__ */ new Set([this.getCanonicalPath(projectRoot)]);
|
|
10553
11555
|
for (const kbRoot of this.config.knowledgeBases) {
|
|
10554
|
-
roots.add(this.getCanonicalPath(
|
|
11556
|
+
roots.add(this.getCanonicalPath(path20.resolve(projectRoot, kbRoot)));
|
|
10555
11557
|
}
|
|
10556
11558
|
return Array.from(roots);
|
|
10557
11559
|
}
|
|
@@ -10968,7 +11970,7 @@ var Indexer = class _Indexer {
|
|
|
10968
11970
|
return configuredProviderInfo !== null && recovery.embeddingProvider === configuredProviderInfo.provider && recovery.embeddingModel === configuredProviderInfo.modelInfo.model && recovery.embeddingDimensions === configuredProviderInfo.modelInfo.dimensions && recovery.embeddingStrategyVersion === EMBEDDING_STRATEGY_VERSION;
|
|
10969
11971
|
}
|
|
10970
11972
|
hasUnknownLegacyForceIndexClear(owner) {
|
|
10971
|
-
return owner.operation === "force-index" && owner.clearRecovery === void 0 && owner.recoveryProtocolVersion !== 1 &&
|
|
11973
|
+
return owner.operation === "force-index" && owner.clearRecovery === void 0 && owner.recoveryProtocolVersion !== 1 && existsSync12(path20.join(this.indexPath, "force-index-phase"));
|
|
10972
11974
|
}
|
|
10973
11975
|
async recoverFromInterruptedIndexingUnlocked(owners) {
|
|
10974
11976
|
for (const owner of owners) {
|
|
@@ -11154,7 +12156,7 @@ var Indexer = class _Indexer {
|
|
|
11154
12156
|
}
|
|
11155
12157
|
}
|
|
11156
12158
|
clearFailedBatchState() {
|
|
11157
|
-
if (
|
|
12159
|
+
if (existsSync12(this.failedBatchesPath)) {
|
|
11158
12160
|
try {
|
|
11159
12161
|
unlinkSync2(this.failedBatchesPath);
|
|
11160
12162
|
} catch {
|
|
@@ -11356,7 +12358,7 @@ var Indexer = class _Indexer {
|
|
|
11356
12358
|
await options.queue.onSizeLessThan(Math.max(1, options.providerRateLimits.concurrency));
|
|
11357
12359
|
const task = options.queue.add(async () => {
|
|
11358
12360
|
if (options.rateLimitState.backoffMs > 0) {
|
|
11359
|
-
await new Promise((
|
|
12361
|
+
await new Promise((resolve18) => setTimeout(resolve18, options.rateLimitState.backoffMs));
|
|
11360
12362
|
}
|
|
11361
12363
|
try {
|
|
11362
12364
|
const embeddingResult = await pRetry(
|
|
@@ -11775,12 +12777,12 @@ var Indexer = class _Indexer {
|
|
|
11775
12777
|
}
|
|
11776
12778
|
}
|
|
11777
12779
|
captureReaderArtifactFingerprint() {
|
|
11778
|
-
const storePath =
|
|
12780
|
+
const storePath = path20.join(this.indexPath, "vectors");
|
|
11779
12781
|
return {
|
|
11780
12782
|
vectors: `${this.getReaderFileFingerprint(storePath)}|${this.getReaderFileFingerprint(`${storePath}.meta.json`)}`,
|
|
11781
|
-
keyword: this.getReaderFileFingerprint(
|
|
11782
|
-
database: this.getReaderFileFingerprint(
|
|
11783
|
-
databaseIdentity: this.getReaderFileFingerprint(
|
|
12783
|
+
keyword: this.getReaderFileFingerprint(path20.join(this.indexPath, "inverted-index.json")),
|
|
12784
|
+
database: this.getReaderFileFingerprint(path20.join(this.indexPath, "codebase.db")),
|
|
12785
|
+
databaseIdentity: this.getReaderFileFingerprint(path20.join(this.indexPath, "codebase.db"), true)
|
|
11784
12786
|
};
|
|
11785
12787
|
}
|
|
11786
12788
|
refreshReaderArtifacts() {
|
|
@@ -11805,13 +12807,13 @@ var Indexer = class _Indexer {
|
|
|
11805
12807
|
issues.set(component, this.createReadIssue(component, message));
|
|
11806
12808
|
this.readerArtifactRetryAfter.set(component, Date.now() + READER_ARTIFACT_RETRY_INTERVAL_MS);
|
|
11807
12809
|
};
|
|
11808
|
-
const storePath =
|
|
12810
|
+
const storePath = path20.join(this.indexPath, "vectors");
|
|
11809
12811
|
const vectorMetadataPath = `${storePath}.meta.json`;
|
|
11810
|
-
const invertedIndexPath =
|
|
11811
|
-
const dbPath =
|
|
12812
|
+
const invertedIndexPath = path20.join(this.indexPath, "inverted-index.json");
|
|
12813
|
+
const dbPath = path20.join(this.indexPath, "codebase.db");
|
|
11812
12814
|
if (vectorsChanged || retryDue("vectors")) {
|
|
11813
|
-
const vectorStoreExists =
|
|
11814
|
-
const vectorMetadataExists =
|
|
12815
|
+
const vectorStoreExists = existsSync12(storePath);
|
|
12816
|
+
const vectorMetadataExists = existsSync12(vectorMetadataPath);
|
|
11815
12817
|
if (vectorStoreExists && vectorMetadataExists) {
|
|
11816
12818
|
try {
|
|
11817
12819
|
const store = new VectorStore(storePath, this.configuredProviderInfo.modelInfo.dimensions);
|
|
@@ -11826,8 +12828,8 @@ var Indexer = class _Indexer {
|
|
|
11826
12828
|
setIssue("vectors", this.getVectorReadIssueMessage());
|
|
11827
12829
|
}
|
|
11828
12830
|
}
|
|
11829
|
-
if (keywordChanged || retryDue("keyword") || !
|
|
11830
|
-
if (
|
|
12831
|
+
if (keywordChanged || retryDue("keyword") || !existsSync12(invertedIndexPath) && (this.store?.count() ?? 0) > 0) {
|
|
12832
|
+
if (existsSync12(invertedIndexPath)) {
|
|
11831
12833
|
try {
|
|
11832
12834
|
const invertedIndex = new InvertedIndex(invertedIndexPath);
|
|
11833
12835
|
invertedIndex.load();
|
|
@@ -11842,7 +12844,7 @@ var Indexer = class _Indexer {
|
|
|
11842
12844
|
}
|
|
11843
12845
|
}
|
|
11844
12846
|
if (databaseReplaced || databaseChanged && issues.has("database") || retryDue("database")) {
|
|
11845
|
-
if (
|
|
12847
|
+
if (existsSync12(dbPath)) {
|
|
11846
12848
|
try {
|
|
11847
12849
|
const database = Database.openReadOnly(dbPath);
|
|
11848
12850
|
if (this.database) {
|
|
@@ -11924,11 +12926,11 @@ var Indexer = class _Indexer {
|
|
|
11924
12926
|
});
|
|
11925
12927
|
this.provider = createEmbeddingProvider(this.configuredProviderInfo);
|
|
11926
12928
|
const dimensions = this.configuredProviderInfo.modelInfo.dimensions;
|
|
11927
|
-
const storePath =
|
|
12929
|
+
const storePath = path20.join(this.indexPath, "vectors");
|
|
11928
12930
|
const vectorMetadataPath = `${storePath}.meta.json`;
|
|
11929
|
-
const invertedIndexPath =
|
|
11930
|
-
const dbPath =
|
|
11931
|
-
let dbIsNew = !
|
|
12931
|
+
const invertedIndexPath = path20.join(this.indexPath, "inverted-index.json");
|
|
12932
|
+
const dbPath = path20.join(this.indexPath, "codebase.db");
|
|
12933
|
+
let dbIsNew = !existsSync12(dbPath);
|
|
11932
12934
|
const readerArtifactFingerprint = mode === "reader" ? this.captureReaderArtifactFingerprint() : null;
|
|
11933
12935
|
if (mode === "writer") {
|
|
11934
12936
|
await fsPromises3.mkdir(this.indexPath, { recursive: true });
|
|
@@ -11960,14 +12962,14 @@ var Indexer = class _Indexer {
|
|
|
11960
12962
|
}
|
|
11961
12963
|
}
|
|
11962
12964
|
this.store = new VectorStore(storePath, dimensions);
|
|
11963
|
-
if (
|
|
12965
|
+
if (existsSync12(storePath) || existsSync12(vectorMetadataPath)) {
|
|
11964
12966
|
this.store.load();
|
|
11965
12967
|
}
|
|
11966
12968
|
this.invertedIndex = new InvertedIndex(invertedIndexPath);
|
|
11967
12969
|
try {
|
|
11968
12970
|
this.invertedIndex.load();
|
|
11969
12971
|
} catch {
|
|
11970
|
-
if (
|
|
12972
|
+
if (existsSync12(invertedIndexPath)) {
|
|
11971
12973
|
await fsPromises3.unlink(invertedIndexPath);
|
|
11972
12974
|
}
|
|
11973
12975
|
this.invertedIndex = new InvertedIndex(invertedIndexPath);
|
|
@@ -11985,8 +12987,8 @@ var Indexer = class _Indexer {
|
|
|
11985
12987
|
}
|
|
11986
12988
|
} else {
|
|
11987
12989
|
this.store = new VectorStore(storePath, dimensions);
|
|
11988
|
-
const vectorStoreExists =
|
|
11989
|
-
const vectorMetadataExists =
|
|
12990
|
+
const vectorStoreExists = existsSync12(storePath);
|
|
12991
|
+
const vectorMetadataExists = existsSync12(vectorMetadataPath);
|
|
11990
12992
|
const vectorReadFailureMessage = this.getVectorReadIssueMessage();
|
|
11991
12993
|
if (vectorStoreExists !== vectorMetadataExists) {
|
|
11992
12994
|
this.recordReadIssue("vectors", vectorReadFailureMessage);
|
|
@@ -11999,7 +13001,7 @@ var Indexer = class _Indexer {
|
|
|
11999
13001
|
}
|
|
12000
13002
|
}
|
|
12001
13003
|
this.invertedIndex = new InvertedIndex(invertedIndexPath);
|
|
12002
|
-
if (
|
|
13004
|
+
if (existsSync12(invertedIndexPath)) {
|
|
12003
13005
|
try {
|
|
12004
13006
|
this.invertedIndex.load();
|
|
12005
13007
|
} catch (error) {
|
|
@@ -12013,7 +13015,7 @@ var Indexer = class _Indexer {
|
|
|
12013
13015
|
} else if (this.store.count() > 0) {
|
|
12014
13016
|
this.recordReadIssue("keyword", this.getKeywordReadIssueMessage());
|
|
12015
13017
|
}
|
|
12016
|
-
if (
|
|
13018
|
+
if (existsSync12(dbPath)) {
|
|
12017
13019
|
try {
|
|
12018
13020
|
this.database = Database.openReadOnly(dbPath);
|
|
12019
13021
|
} catch (error) {
|
|
@@ -12105,7 +13107,7 @@ var Indexer = class _Indexer {
|
|
|
12105
13107
|
if (await this.tryResetCorruptedIndex("running automatic orphan garbage collection", error)) {
|
|
12106
13108
|
return {
|
|
12107
13109
|
resetCorruptedIndex: true,
|
|
12108
|
-
warning: this.getCorruptedIndexWarning(
|
|
13110
|
+
warning: this.getCorruptedIndexWarning(path20.join(this.indexPath, "codebase.db"))
|
|
12109
13111
|
};
|
|
12110
13112
|
}
|
|
12111
13113
|
throw error;
|
|
@@ -12120,7 +13122,7 @@ var Indexer = class _Indexer {
|
|
|
12120
13122
|
return;
|
|
12121
13123
|
}
|
|
12122
13124
|
const retainedEntries = store.getAllMetadata().filter(({ key }) => !excludedSet.has(key));
|
|
12123
|
-
const storeBasePath =
|
|
13125
|
+
const storeBasePath = path20.join(this.indexPath, "vectors");
|
|
12124
13126
|
const storeIndexPath = storeBasePath;
|
|
12125
13127
|
const storeMetadataPath = `${storeBasePath}.meta.json`;
|
|
12126
13128
|
const lease = this.requireActiveLease();
|
|
@@ -12130,19 +13132,19 @@ var Indexer = class _Indexer {
|
|
|
12130
13132
|
let backedUpMetadata = false;
|
|
12131
13133
|
let rebuiltCount = 0;
|
|
12132
13134
|
let skippedCount = 0;
|
|
12133
|
-
if (
|
|
13135
|
+
if (existsSync12(backupIndexPath)) {
|
|
12134
13136
|
unlinkSync2(backupIndexPath);
|
|
12135
13137
|
}
|
|
12136
|
-
if (
|
|
13138
|
+
if (existsSync12(backupMetadataPath)) {
|
|
12137
13139
|
unlinkSync2(backupMetadataPath);
|
|
12138
13140
|
}
|
|
12139
13141
|
try {
|
|
12140
|
-
if (
|
|
12141
|
-
|
|
13142
|
+
if (existsSync12(storeIndexPath)) {
|
|
13143
|
+
renameSync4(storeIndexPath, backupIndexPath);
|
|
12142
13144
|
backedUpIndex = true;
|
|
12143
13145
|
}
|
|
12144
|
-
if (
|
|
12145
|
-
|
|
13146
|
+
if (existsSync12(storeMetadataPath)) {
|
|
13147
|
+
renameSync4(storeMetadataPath, backupMetadataPath);
|
|
12146
13148
|
backedUpMetadata = true;
|
|
12147
13149
|
}
|
|
12148
13150
|
store.clear();
|
|
@@ -12162,10 +13164,10 @@ var Indexer = class _Indexer {
|
|
|
12162
13164
|
rebuiltCount += 1;
|
|
12163
13165
|
}
|
|
12164
13166
|
store.save();
|
|
12165
|
-
if (backedUpIndex &&
|
|
13167
|
+
if (backedUpIndex && existsSync12(backupIndexPath)) {
|
|
12166
13168
|
unlinkSync2(backupIndexPath);
|
|
12167
13169
|
}
|
|
12168
|
-
if (backedUpMetadata &&
|
|
13170
|
+
if (backedUpMetadata && existsSync12(backupMetadataPath)) {
|
|
12169
13171
|
unlinkSync2(backupMetadataPath);
|
|
12170
13172
|
}
|
|
12171
13173
|
this.logger.gc("info", "Rebuilt vector store to avoid native remove", {
|
|
@@ -12178,17 +13180,17 @@ var Indexer = class _Indexer {
|
|
|
12178
13180
|
store.clear();
|
|
12179
13181
|
} catch {
|
|
12180
13182
|
}
|
|
12181
|
-
if (
|
|
13183
|
+
if (existsSync12(storeIndexPath)) {
|
|
12182
13184
|
unlinkSync2(storeIndexPath);
|
|
12183
13185
|
}
|
|
12184
|
-
if (
|
|
13186
|
+
if (existsSync12(storeMetadataPath)) {
|
|
12185
13187
|
unlinkSync2(storeMetadataPath);
|
|
12186
13188
|
}
|
|
12187
|
-
if (backedUpIndex &&
|
|
12188
|
-
|
|
13189
|
+
if (backedUpIndex && existsSync12(backupIndexPath)) {
|
|
13190
|
+
renameSync4(backupIndexPath, storeIndexPath);
|
|
12189
13191
|
}
|
|
12190
|
-
if (backedUpMetadata &&
|
|
12191
|
-
|
|
13192
|
+
if (backedUpMetadata && existsSync12(backupMetadataPath)) {
|
|
13193
|
+
renameSync4(backupMetadataPath, storeMetadataPath);
|
|
12192
13194
|
}
|
|
12193
13195
|
if (backedUpIndex || backedUpMetadata) {
|
|
12194
13196
|
store.load();
|
|
@@ -12203,11 +13205,11 @@ var Indexer = class _Indexer {
|
|
|
12203
13205
|
return `Detected a corrupted local SQLite index at ${dbPath} and reset the local index. Run index_codebase to rebuild search data.`;
|
|
12204
13206
|
}
|
|
12205
13207
|
async removeProjectRuntimeStateArtifacts() {
|
|
12206
|
-
if (!
|
|
13208
|
+
if (!existsSync12(this.indexPath)) return;
|
|
12207
13209
|
const names = await fsPromises3.readdir(this.indexPath);
|
|
12208
13210
|
const runtimeStatePattern = /^(?:file-hashes|failed-batches)(?:\.[a-f0-9]{16})?\.json$/;
|
|
12209
13211
|
await Promise.all(
|
|
12210
|
-
names.filter((name) => runtimeStatePattern.test(name)).map((name) => fsPromises3.rm(
|
|
13212
|
+
names.filter((name) => runtimeStatePattern.test(name)).map((name) => fsPromises3.rm(path20.join(this.indexPath, name), { force: true }))
|
|
12211
13213
|
);
|
|
12212
13214
|
}
|
|
12213
13215
|
async resetLocalIndexArtifacts() {
|
|
@@ -12223,13 +13225,13 @@ var Indexer = class _Indexer {
|
|
|
12223
13225
|
this.readerArtifactRetryAfter.clear();
|
|
12224
13226
|
this.fileHashCache.clear();
|
|
12225
13227
|
const resetPaths = [
|
|
12226
|
-
|
|
12227
|
-
|
|
12228
|
-
|
|
12229
|
-
|
|
12230
|
-
|
|
12231
|
-
|
|
12232
|
-
|
|
13228
|
+
path20.join(this.indexPath, "codebase.db"),
|
|
13229
|
+
path20.join(this.indexPath, "codebase.db-shm"),
|
|
13230
|
+
path20.join(this.indexPath, "codebase.db-wal"),
|
|
13231
|
+
path20.join(this.indexPath, "vectors"),
|
|
13232
|
+
path20.join(this.indexPath, "vectors.usearch"),
|
|
13233
|
+
path20.join(this.indexPath, "vectors.meta.json"),
|
|
13234
|
+
path20.join(this.indexPath, "inverted-index.json")
|
|
12233
13235
|
];
|
|
12234
13236
|
await Promise.all(resetPaths.map((targetPath) => fsPromises3.rm(targetPath, { recursive: true, force: true })));
|
|
12235
13237
|
await this.removeProjectRuntimeStateArtifacts();
|
|
@@ -12239,7 +13241,7 @@ var Indexer = class _Indexer {
|
|
|
12239
13241
|
if (!isSqliteCorruptionError(error)) {
|
|
12240
13242
|
return false;
|
|
12241
13243
|
}
|
|
12242
|
-
const dbPath =
|
|
13244
|
+
const dbPath = path20.join(this.indexPath, "codebase.db");
|
|
12243
13245
|
const warning = this.getCorruptedIndexWarning(dbPath);
|
|
12244
13246
|
const errorMessage = getErrorMessage4(error);
|
|
12245
13247
|
if (this.config.scope === "global") {
|
|
@@ -12626,10 +13628,10 @@ var Indexer = class _Indexer {
|
|
|
12626
13628
|
const reparseCachedMetalFiles = database.getMetadata(metalParserMetadataKey) !== METAL_PARSER_VERSION;
|
|
12627
13629
|
const symbolExtractorMetadataKey = this.getSymbolExtractorVersionMetadataKey();
|
|
12628
13630
|
const refreshCachedSymbols = database.getMetadata(symbolExtractorMetadataKey) !== SYMBOL_EXTRACTOR_VERSION;
|
|
12629
|
-
if (reparseCachedSwiftFiles && Array.from(this.fileHashCache.keys()).some((filePath) =>
|
|
13631
|
+
if (reparseCachedSwiftFiles && Array.from(this.fileHashCache.keys()).some((filePath) => path20.extname(filePath).toLowerCase() === ".swift")) {
|
|
12630
13632
|
this.logger.info("Reindexing cached Swift files for parser support");
|
|
12631
13633
|
}
|
|
12632
|
-
if (reparseCachedMetalFiles && Array.from(this.fileHashCache.keys()).some((filePath) =>
|
|
13634
|
+
if (reparseCachedMetalFiles && Array.from(this.fileHashCache.keys()).some((filePath) => path20.extname(filePath).toLowerCase() === ".metal")) {
|
|
12633
13635
|
this.logger.info("Reindexing cached Metal files for parser support");
|
|
12634
13636
|
}
|
|
12635
13637
|
const includePatterns = [...this.config.include, ...this.config.additionalInclude];
|
|
@@ -12673,8 +13675,8 @@ var Indexer = class _Indexer {
|
|
|
12673
13675
|
const needsCallGraphRefresh = cachedHashMatches && needsCallGraphResolutionMigration && database.getChunksByFile(storedPath).some(
|
|
12674
13676
|
(chunk) => chunk.language === "php" || chunk.language === "c" || chunk.language === "cpp"
|
|
12675
13677
|
);
|
|
12676
|
-
const requiresSwiftParserUpgrade = reparseCachedSwiftFiles &&
|
|
12677
|
-
const requiresMetalParserUpgrade = reparseCachedMetalFiles &&
|
|
13678
|
+
const requiresSwiftParserUpgrade = reparseCachedSwiftFiles && path20.extname(storedPath).toLowerCase() === ".swift";
|
|
13679
|
+
const requiresMetalParserUpgrade = reparseCachedMetalFiles && path20.extname(storedPath).toLowerCase() === ".metal";
|
|
12678
13680
|
const inMigrationScope = forceScopedReembed && scopedRoots !== null && this.isFileInCurrentScope(storedPath, scopedRoots);
|
|
12679
13681
|
if (cachedHashMatches && !inMigrationScope && !needsCallGraphRefresh && !requiresSwiftParserUpgrade && !requiresMetalParserUpgrade && !refreshCachedSymbols) {
|
|
12680
13682
|
unchangedFilePaths.add(storedPath);
|
|
@@ -12733,7 +13735,7 @@ var Indexer = class _Indexer {
|
|
|
12733
13735
|
}
|
|
12734
13736
|
}
|
|
12735
13737
|
}
|
|
12736
|
-
const shouldRetryFailedPath = (filePath) => filePath !== null && currentFileHashes.has(filePath) && unchangedFilePaths.has(filePath);
|
|
13738
|
+
const shouldRetryFailedPath = (filePath) => filePath !== null && !this.isStoredPathExcluded(filePath) && currentFileHashes.has(filePath) && unchangedFilePaths.has(filePath);
|
|
12737
13739
|
const failedProcessing = this.prepareFailedBatchProcessing(scopedRoots, shouldRetryFailedPath);
|
|
12738
13740
|
const maxChunkTokens = getSafeEmbeddingChunkTokenLimit(configuredProviderInfo);
|
|
12739
13741
|
const providerRateLimits = this.getProviderRateLimits(configuredProviderInfo.provider);
|
|
@@ -12837,7 +13839,7 @@ var Indexer = class _Indexer {
|
|
|
12837
13839
|
throw new Error(`Parsed file was not present in its source batch: ${parsed.path}`);
|
|
12838
13840
|
}
|
|
12839
13841
|
if (parsed.chunks.length === 0) {
|
|
12840
|
-
stats.parseFailures.push(
|
|
13842
|
+
stats.parseFailures.push(path20.isAbsolute(parsed.path) ? path20.relative(this.projectRoot, parsed.path) : parsed.path);
|
|
12841
13843
|
}
|
|
12842
13844
|
let chunksToProcess = parsed.chunks;
|
|
12843
13845
|
if (this.config.indexing.fallbackToTextOnMaxChunks && chunksToProcess.length > this.config.indexing.maxChunksPerFile) {
|
|
@@ -13172,8 +14174,8 @@ var Indexer = class _Indexer {
|
|
|
13172
14174
|
previousBranchSymbolIds,
|
|
13173
14175
|
Array.from(allSymbolIds)
|
|
13174
14176
|
);
|
|
13175
|
-
const vectorPath =
|
|
13176
|
-
const shouldFingerprintLegacyPair = !store.hasFingerprint() &&
|
|
14177
|
+
const vectorPath = path20.join(this.indexPath, "vectors");
|
|
14178
|
+
const shouldFingerprintLegacyPair = !store.hasFingerprint() && existsSync12(vectorPath) && existsSync12(`${vectorPath}.meta.json`);
|
|
13177
14179
|
if (backfilledBlameMetadata || shouldFingerprintLegacyPair || removedStoredChunks) {
|
|
13178
14180
|
store.save();
|
|
13179
14181
|
}
|
|
@@ -13968,7 +14970,7 @@ var Indexer = class _Indexer {
|
|
|
13968
14970
|
const missingChunkKeys = [];
|
|
13969
14971
|
const chunkKeysByRemovedFile = /* @__PURE__ */ new Map();
|
|
13970
14972
|
for (const [filePath, chunkKeys] of filePathsToChunkKeys) {
|
|
13971
|
-
if (!
|
|
14973
|
+
if (!existsSync12(this.toMaterializedFilePath(filePath))) {
|
|
13972
14974
|
chunkKeysByRemovedFile.set(filePath, chunkKeys);
|
|
13973
14975
|
for (const key of chunkKeys) {
|
|
13974
14976
|
missingChunkKeys.push(key);
|
|
@@ -14031,7 +15033,7 @@ var Indexer = class _Indexer {
|
|
|
14031
15033
|
gcOrphanSymbols: 0,
|
|
14032
15034
|
gcOrphanCallEdges: 0,
|
|
14033
15035
|
resetCorruptedIndex: true,
|
|
14034
|
-
warning: this.getCorruptedIndexWarning(
|
|
15036
|
+
warning: this.getCorruptedIndexWarning(path20.join(this.indexPath, "codebase.db"))
|
|
14035
15037
|
};
|
|
14036
15038
|
}
|
|
14037
15039
|
this.logger.recordGc(removedCount, gcOrphanChunks, gcOrphanEmbeddings);
|
|
@@ -14061,7 +15063,8 @@ var Indexer = class _Indexer {
|
|
|
14061
15063
|
const maxChunkTokens = getSafeEmbeddingChunkTokenLimit(configuredProviderInfo);
|
|
14062
15064
|
const providerRateLimits = this.getProviderRateLimits(configuredProviderInfo.provider);
|
|
14063
15065
|
const roots = this.config.scope === "global" ? this.getScopedRoots() : null;
|
|
14064
|
-
const
|
|
15066
|
+
const shouldProcessFailedPath = (filePath) => filePath === null || !this.isStoredPathExcluded(filePath);
|
|
15067
|
+
const failedProcessing = this.prepareFailedBatchProcessing(roots, shouldProcessFailedPath);
|
|
14065
15068
|
if (failedProcessing.latestById.size === 0) {
|
|
14066
15069
|
this.finalizeFailedBatchWriteState(failedProcessing.state);
|
|
14067
15070
|
return { succeeded: 0, failed: 0, remaining: 0 };
|
|
@@ -14074,7 +15077,7 @@ var Indexer = class _Indexer {
|
|
|
14074
15077
|
const retryableChunks = this.iterateLatestFailedChunks(
|
|
14075
15078
|
failedProcessing.latestById,
|
|
14076
15079
|
roots,
|
|
14077
|
-
|
|
15080
|
+
shouldProcessFailedPath,
|
|
14078
15081
|
maxChunkTokens
|
|
14079
15082
|
);
|
|
14080
15083
|
for (const retryBatch of iterateOrderedFileBatches(
|
|
@@ -14344,9 +15347,9 @@ var Indexer = class _Indexer {
|
|
|
14344
15347
|
this.requireReadableComponents(readIssues, "database");
|
|
14345
15348
|
let shortest = [];
|
|
14346
15349
|
for (const branchKey of this.getBranchCatalogKeys()) {
|
|
14347
|
-
const
|
|
14348
|
-
if (
|
|
14349
|
-
shortest =
|
|
15350
|
+
const path31 = database.findShortestPath(fromName, toName, branchKey, maxDepth);
|
|
15351
|
+
if (path31.length > 0 && (shortest.length === 0 || path31.length < shortest.length)) {
|
|
15352
|
+
shortest = path31;
|
|
14350
15353
|
}
|
|
14351
15354
|
}
|
|
14352
15355
|
return shortest.map((hop) => this.resolveFilePathRecord(hop));
|
|
@@ -14394,13 +15397,13 @@ var Indexer = class _Indexer {
|
|
|
14394
15397
|
}
|
|
14395
15398
|
}
|
|
14396
15399
|
if (!found) continue;
|
|
14397
|
-
const
|
|
15400
|
+
const path31 = [];
|
|
14398
15401
|
let currentSymbolId = toSymbolId;
|
|
14399
15402
|
while (true) {
|
|
14400
15403
|
const symbol = symbolsById.get(currentSymbolId);
|
|
14401
15404
|
if (!symbol) break;
|
|
14402
15405
|
const parent = parentBySymbolId.get(currentSymbolId);
|
|
14403
|
-
|
|
15406
|
+
path31.push({
|
|
14404
15407
|
symbolId: symbol.id,
|
|
14405
15408
|
symbolName: symbol.name,
|
|
14406
15409
|
filePath: symbol.filePath,
|
|
@@ -14410,9 +15413,9 @@ var Indexer = class _Indexer {
|
|
|
14410
15413
|
if (!parent) break;
|
|
14411
15414
|
currentSymbolId = parent.parentId;
|
|
14412
15415
|
}
|
|
14413
|
-
|
|
14414
|
-
if (
|
|
14415
|
-
shortest =
|
|
15416
|
+
path31.reverse();
|
|
15417
|
+
if (path31.length > 0 && (shortest.length === 0 || path31.length < shortest.length)) {
|
|
15418
|
+
shortest = path31;
|
|
14416
15419
|
}
|
|
14417
15420
|
}
|
|
14418
15421
|
return shortest.map((hop) => this.resolveFilePathRecord(hop));
|
|
@@ -14563,7 +15566,7 @@ var Indexer = class _Indexer {
|
|
|
14563
15566
|
);
|
|
14564
15567
|
}
|
|
14565
15568
|
}
|
|
14566
|
-
const toStoredChangedFiles = (filePaths) => filePaths.map((filePath) => this.toStoredFilePath(
|
|
15569
|
+
const toStoredChangedFiles = (filePaths) => filePaths.map((filePath) => this.toStoredFilePath(path20.resolve(this.projectRoot, filePath)));
|
|
14567
15570
|
const storedChangedFiles = toStoredChangedFiles(changedFiles);
|
|
14568
15571
|
const directSymbols = database.getSymbolsForFiles(storedChangedFiles, branchKey);
|
|
14569
15572
|
const directIds = directSymbols.map((s) => s.id);
|
|
@@ -14712,12 +15715,12 @@ var Indexer = class _Indexer {
|
|
|
14712
15715
|
if (meta.filePath) filePaths.add(meta.filePath);
|
|
14713
15716
|
}
|
|
14714
15717
|
const directory = options?.directory?.replace(/\/$/, "");
|
|
14715
|
-
const absoluteDirectoryFilter = directory ?
|
|
15718
|
+
const absoluteDirectoryFilter = directory ? path20.resolve(this.projectRoot, directory) : void 0;
|
|
14716
15719
|
for (const filePath of filePaths) {
|
|
14717
15720
|
if (directory) {
|
|
14718
15721
|
const absoluteFilePath = this.resolveStoredFilePath(filePath);
|
|
14719
15722
|
const matchesRelative = filePath === directory || filePath.startsWith(directory + "/");
|
|
14720
|
-
const matchesProjectRelative = absoluteDirectoryFilter !== void 0 && (absoluteFilePath === absoluteDirectoryFilter || absoluteFilePath.startsWith(absoluteDirectoryFilter +
|
|
15723
|
+
const matchesProjectRelative = absoluteDirectoryFilter !== void 0 && (absoluteFilePath === absoluteDirectoryFilter || absoluteFilePath.startsWith(absoluteDirectoryFilter + path20.sep));
|
|
14721
15724
|
if (!matchesRelative && !matchesProjectRelative) {
|
|
14722
15725
|
continue;
|
|
14723
15726
|
}
|
|
@@ -14834,15 +15837,24 @@ function getOrCreateIndexer(projectRoot, host) {
|
|
|
14834
15837
|
}
|
|
14835
15838
|
const indexer = new Indexer(projectRoot, config, host);
|
|
14836
15839
|
indexerCache.set(key, indexer);
|
|
14837
|
-
configureAutoIndex(projectRoot, host, config, () => getOrCreateIndexer(projectRoot, host)
|
|
15840
|
+
configureAutoIndex(projectRoot, host, config, () => getOrCreateIndexer(projectRoot, host), {
|
|
15841
|
+
preserveManagedWorker: true,
|
|
15842
|
+
synchronizeBackgroundWorker: false
|
|
15843
|
+
});
|
|
14838
15844
|
return indexer;
|
|
14839
15845
|
}
|
|
14840
|
-
function initializeTools(projectRoot, config, host) {
|
|
15846
|
+
function initializeTools(projectRoot, config, host, options = {}) {
|
|
14841
15847
|
defaultProjectRoots.set(host, projectRoot);
|
|
14842
15848
|
const key = getIndexerCacheKey(projectRoot, host);
|
|
15849
|
+
if (options.preserveManagedWorker === true && isBackgroundWorkerManaged(projectRoot, host) && indexerCache.has(key)) {
|
|
15850
|
+
return;
|
|
15851
|
+
}
|
|
14843
15852
|
configCache.set(key, config);
|
|
14844
15853
|
indexerCache.set(key, new Indexer(projectRoot, config, host));
|
|
14845
|
-
configureAutoIndex(projectRoot, host, config, () => getOrCreateIndexer(projectRoot, host)
|
|
15854
|
+
configureAutoIndex(projectRoot, host, config, () => getOrCreateIndexer(projectRoot, host), {
|
|
15855
|
+
preserveManagedWorker: options.preserveManagedWorker,
|
|
15856
|
+
synchronizeBackgroundWorker: false
|
|
15857
|
+
});
|
|
14846
15858
|
}
|
|
14847
15859
|
function getIndexerForProject(projectRoot, host) {
|
|
14848
15860
|
const root = getProjectRoot(projectRoot, host);
|
|
@@ -14856,7 +15868,9 @@ function refreshIndexerForDirectory(projectRoot, host, config = parseConfig(load
|
|
|
14856
15868
|
const key = getIndexerCacheKey(projectRoot, host);
|
|
14857
15869
|
configCache.set(key, config);
|
|
14858
15870
|
indexerCache.set(key, new Indexer(projectRoot, config, host));
|
|
14859
|
-
configureAutoIndex(projectRoot, host, config, () => getOrCreateIndexer(projectRoot, host)
|
|
15871
|
+
configureAutoIndex(projectRoot, host, config, () => getOrCreateIndexer(projectRoot, host), {
|
|
15872
|
+
synchronizeBackgroundWorker: true
|
|
15873
|
+
});
|
|
14860
15874
|
return config;
|
|
14861
15875
|
}
|
|
14862
15876
|
var AutoIndexRetrievalUnavailableError = class extends Error {
|
|
@@ -14883,7 +15897,7 @@ function trimOrUndefined(value) {
|
|
|
14883
15897
|
return normalized || void 0;
|
|
14884
15898
|
}
|
|
14885
15899
|
function normalizeCallGraphPath(value) {
|
|
14886
|
-
let normalized =
|
|
15900
|
+
let normalized = path21.posix.normalize(value.trim().replaceAll("\\", "/"));
|
|
14887
15901
|
if (normalized.startsWith("./")) {
|
|
14888
15902
|
normalized = normalized.slice(2);
|
|
14889
15903
|
}
|
|
@@ -15076,12 +16090,12 @@ async function getCallGraphPath(projectRoot, host, from, to, maxDepth, fromFileP
|
|
|
15076
16090
|
if (fromResolution.status !== "resolved" || toResolution.status !== "resolved") {
|
|
15077
16091
|
return { from: fromResolution, to: toResolution, path: [] };
|
|
15078
16092
|
}
|
|
15079
|
-
const
|
|
16093
|
+
const path31 = await indexer.findCallPathBySymbolIds(
|
|
15080
16094
|
fromResolution.symbolId,
|
|
15081
16095
|
toResolution.symbolId,
|
|
15082
16096
|
maxDepth
|
|
15083
16097
|
);
|
|
15084
|
-
return { from: fromResolution, to: toResolution, path:
|
|
16098
|
+
return { from: fromResolution, to: toResolution, path: path31 };
|
|
15085
16099
|
}
|
|
15086
16100
|
async function runIndexCodebase(projectRoot, host, args, onProgress) {
|
|
15087
16101
|
const root = getProjectRoot(projectRoot, host);
|
|
@@ -15267,15 +16281,15 @@ async function getIndexLogs(projectRoot, host, args) {
|
|
|
15267
16281
|
function addKnowledgeBase(projectRoot, host, knowledgeBasePath) {
|
|
15268
16282
|
const root = getProjectRoot(projectRoot, host);
|
|
15269
16283
|
const inputPath = knowledgeBasePath.trim();
|
|
15270
|
-
const normalizedPath2 =
|
|
15271
|
-
|
|
16284
|
+
const normalizedPath2 = path21.resolve(
|
|
16285
|
+
path21.isAbsolute(inputPath) ? inputPath : resolveKnowledgeBasePath(inputPath, root)
|
|
15272
16286
|
);
|
|
15273
|
-
if (!
|
|
16287
|
+
if (!existsSync13(normalizedPath2)) {
|
|
15274
16288
|
return `Error: Directory does not exist: ${normalizedPath2}`;
|
|
15275
16289
|
}
|
|
15276
16290
|
let realPath;
|
|
15277
16291
|
try {
|
|
15278
|
-
realPath =
|
|
16292
|
+
realPath = realpathSync6(normalizedPath2);
|
|
15279
16293
|
} catch {
|
|
15280
16294
|
return `Error: Cannot resolve path: ${normalizedPath2}`;
|
|
15281
16295
|
}
|
|
@@ -15304,7 +16318,7 @@ function addKnowledgeBase(projectRoot, host, knowledgeBasePath) {
|
|
|
15304
16318
|
}
|
|
15305
16319
|
}
|
|
15306
16320
|
for (const dotDir of sensitiveDotDirs) {
|
|
15307
|
-
const sensitiveDir =
|
|
16321
|
+
const sensitiveDir = path21.join(homeDir, dotDir);
|
|
15308
16322
|
if (sensitiveDir && (realPath === sensitiveDir || realPath.startsWith(`${sensitiveDir}/`))) {
|
|
15309
16323
|
return `Error: Adding sensitive directory as knowledge base is not allowed: ${normalizedPath2}`;
|
|
15310
16324
|
}
|
|
@@ -15350,7 +16364,7 @@ function listKnowledgeBases(projectRoot, host) {
|
|
|
15350
16364
|
for (let i = 0; i < knowledgeBases.length; i++) {
|
|
15351
16365
|
const kb = knowledgeBases[i];
|
|
15352
16366
|
const resolvedPath = resolveKnowledgeBasePath(kb, root);
|
|
15353
|
-
const exists =
|
|
16367
|
+
const exists = existsSync13(resolvedPath);
|
|
15354
16368
|
result += `[${i + 1}] ${kb}
|
|
15355
16369
|
`;
|
|
15356
16370
|
result += ` Resolved: ${resolvedPath}
|
|
@@ -15367,7 +16381,7 @@ function listKnowledgeBases(projectRoot, host) {
|
|
|
15367
16381
|
}
|
|
15368
16382
|
result += "\n";
|
|
15369
16383
|
}
|
|
15370
|
-
const hasHostConfig =
|
|
16384
|
+
const hasHostConfig = existsSync13(path21.join(root, getHostProjectConfigRelativePath(host)));
|
|
15371
16385
|
if (hasHostConfig) {
|
|
15372
16386
|
result += `
|
|
15373
16387
|
Config sources: 1 file(s).`;
|
|
@@ -15401,7 +16415,7 @@ Run /index to rebuild the index without the removed knowledge base.`;
|
|
|
15401
16415
|
}
|
|
15402
16416
|
|
|
15403
16417
|
// src/watcher/file-watcher.ts
|
|
15404
|
-
import { existsSync as
|
|
16418
|
+
import { existsSync as existsSync14, statSync as statSync6 } from "fs";
|
|
15405
16419
|
|
|
15406
16420
|
// node_modules/chokidar/index.js
|
|
15407
16421
|
import { EventEmitter as EventEmitter2 } from "events";
|
|
@@ -15493,7 +16507,7 @@ var ReaddirpStream = class extends Readable {
|
|
|
15493
16507
|
this._directoryFilter = normalizeFilter(opts.directoryFilter);
|
|
15494
16508
|
const statMethod = opts.lstat ? lstat : stat;
|
|
15495
16509
|
if (wantBigintFsStats) {
|
|
15496
|
-
this._stat = (
|
|
16510
|
+
this._stat = (path31) => statMethod(path31, { bigint: true });
|
|
15497
16511
|
} else {
|
|
15498
16512
|
this._stat = statMethod;
|
|
15499
16513
|
}
|
|
@@ -15518,8 +16532,8 @@ var ReaddirpStream = class extends Readable {
|
|
|
15518
16532
|
const par = this.parent;
|
|
15519
16533
|
const fil = par && par.files;
|
|
15520
16534
|
if (fil && fil.length > 0) {
|
|
15521
|
-
const { path:
|
|
15522
|
-
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent,
|
|
16535
|
+
const { path: path31, depth } = par;
|
|
16536
|
+
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path31));
|
|
15523
16537
|
const awaited = await Promise.all(slice);
|
|
15524
16538
|
for (const entry of awaited) {
|
|
15525
16539
|
if (!entry)
|
|
@@ -15559,21 +16573,21 @@ var ReaddirpStream = class extends Readable {
|
|
|
15559
16573
|
this.reading = false;
|
|
15560
16574
|
}
|
|
15561
16575
|
}
|
|
15562
|
-
async _exploreDir(
|
|
16576
|
+
async _exploreDir(path31, depth) {
|
|
15563
16577
|
let files;
|
|
15564
16578
|
try {
|
|
15565
|
-
files = await readdir(
|
|
16579
|
+
files = await readdir(path31, this._rdOptions);
|
|
15566
16580
|
} catch (error) {
|
|
15567
16581
|
this._onError(error);
|
|
15568
16582
|
}
|
|
15569
|
-
return { files, depth, path:
|
|
16583
|
+
return { files, depth, path: path31 };
|
|
15570
16584
|
}
|
|
15571
|
-
async _formatEntry(dirent,
|
|
16585
|
+
async _formatEntry(dirent, path31) {
|
|
15572
16586
|
let entry;
|
|
15573
|
-
const
|
|
16587
|
+
const basename10 = this._isDirent ? dirent.name : dirent;
|
|
15574
16588
|
try {
|
|
15575
|
-
const fullPath = presolve(pjoin(
|
|
15576
|
-
entry = { path: prelative(this._root, fullPath), fullPath, basename:
|
|
16589
|
+
const fullPath = presolve(pjoin(path31, basename10));
|
|
16590
|
+
entry = { path: prelative(this._root, fullPath), fullPath, basename: basename10 };
|
|
15577
16591
|
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
15578
16592
|
} catch (err) {
|
|
15579
16593
|
this._onError(err);
|
|
@@ -15972,16 +16986,16 @@ var delFromSet = (main, prop, item) => {
|
|
|
15972
16986
|
};
|
|
15973
16987
|
var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
|
|
15974
16988
|
var FsWatchInstances = /* @__PURE__ */ new Map();
|
|
15975
|
-
function createFsWatchInstance(
|
|
16989
|
+
function createFsWatchInstance(path31, options, listener, errHandler, emitRaw) {
|
|
15976
16990
|
const handleEvent = (rawEvent, evPath) => {
|
|
15977
|
-
listener(
|
|
15978
|
-
emitRaw(rawEvent, evPath, { watchedPath:
|
|
15979
|
-
if (evPath &&
|
|
15980
|
-
fsWatchBroadcast(sp.resolve(
|
|
16991
|
+
listener(path31);
|
|
16992
|
+
emitRaw(rawEvent, evPath, { watchedPath: path31 });
|
|
16993
|
+
if (evPath && path31 !== evPath) {
|
|
16994
|
+
fsWatchBroadcast(sp.resolve(path31, evPath), KEY_LISTENERS, sp.join(path31, evPath));
|
|
15981
16995
|
}
|
|
15982
16996
|
};
|
|
15983
16997
|
try {
|
|
15984
|
-
return fs_watch(
|
|
16998
|
+
return fs_watch(path31, {
|
|
15985
16999
|
persistent: options.persistent
|
|
15986
17000
|
}, handleEvent);
|
|
15987
17001
|
} catch (error) {
|
|
@@ -15997,12 +17011,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
|
|
|
15997
17011
|
listener(val1, val2, val3);
|
|
15998
17012
|
});
|
|
15999
17013
|
};
|
|
16000
|
-
var setFsWatchListener = (
|
|
17014
|
+
var setFsWatchListener = (path31, fullPath, options, handlers) => {
|
|
16001
17015
|
const { listener, errHandler, rawEmitter } = handlers;
|
|
16002
17016
|
let cont = FsWatchInstances.get(fullPath);
|
|
16003
17017
|
let watcher;
|
|
16004
17018
|
if (!options.persistent) {
|
|
16005
|
-
watcher = createFsWatchInstance(
|
|
17019
|
+
watcher = createFsWatchInstance(path31, options, listener, errHandler, rawEmitter);
|
|
16006
17020
|
if (!watcher)
|
|
16007
17021
|
return;
|
|
16008
17022
|
return watcher.close.bind(watcher);
|
|
@@ -16013,7 +17027,7 @@ var setFsWatchListener = (path30, fullPath, options, handlers) => {
|
|
|
16013
17027
|
addAndConvert(cont, KEY_RAW, rawEmitter);
|
|
16014
17028
|
} else {
|
|
16015
17029
|
watcher = createFsWatchInstance(
|
|
16016
|
-
|
|
17030
|
+
path31,
|
|
16017
17031
|
options,
|
|
16018
17032
|
fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
|
|
16019
17033
|
errHandler,
|
|
@@ -16028,7 +17042,7 @@ var setFsWatchListener = (path30, fullPath, options, handlers) => {
|
|
|
16028
17042
|
cont.watcherUnusable = true;
|
|
16029
17043
|
if (isWindows && error.code === "EPERM") {
|
|
16030
17044
|
try {
|
|
16031
|
-
const fd = await open(
|
|
17045
|
+
const fd = await open(path31, "r");
|
|
16032
17046
|
await fd.close();
|
|
16033
17047
|
broadcastErr(error);
|
|
16034
17048
|
} catch (err) {
|
|
@@ -16059,7 +17073,7 @@ var setFsWatchListener = (path30, fullPath, options, handlers) => {
|
|
|
16059
17073
|
};
|
|
16060
17074
|
};
|
|
16061
17075
|
var FsWatchFileInstances = /* @__PURE__ */ new Map();
|
|
16062
|
-
var setFsWatchFileListener = (
|
|
17076
|
+
var setFsWatchFileListener = (path31, fullPath, options, handlers) => {
|
|
16063
17077
|
const { listener, rawEmitter } = handlers;
|
|
16064
17078
|
let cont = FsWatchFileInstances.get(fullPath);
|
|
16065
17079
|
const copts = cont && cont.options;
|
|
@@ -16081,7 +17095,7 @@ var setFsWatchFileListener = (path30, fullPath, options, handlers) => {
|
|
|
16081
17095
|
});
|
|
16082
17096
|
const currmtime = curr.mtimeMs;
|
|
16083
17097
|
if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
|
|
16084
|
-
foreach(cont.listeners, (listener2) => listener2(
|
|
17098
|
+
foreach(cont.listeners, (listener2) => listener2(path31, curr));
|
|
16085
17099
|
}
|
|
16086
17100
|
})
|
|
16087
17101
|
};
|
|
@@ -16111,13 +17125,13 @@ var NodeFsHandler = class {
|
|
|
16111
17125
|
* @param listener on fs change
|
|
16112
17126
|
* @returns closer for the watcher instance
|
|
16113
17127
|
*/
|
|
16114
|
-
_watchWithNodeFs(
|
|
17128
|
+
_watchWithNodeFs(path31, listener) {
|
|
16115
17129
|
const opts = this.fsw.options;
|
|
16116
|
-
const directory = sp.dirname(
|
|
16117
|
-
const
|
|
17130
|
+
const directory = sp.dirname(path31);
|
|
17131
|
+
const basename10 = sp.basename(path31);
|
|
16118
17132
|
const parent = this.fsw._getWatchedDir(directory);
|
|
16119
|
-
parent.add(
|
|
16120
|
-
const absolutePath = sp.resolve(
|
|
17133
|
+
parent.add(basename10);
|
|
17134
|
+
const absolutePath = sp.resolve(path31);
|
|
16121
17135
|
const options = {
|
|
16122
17136
|
persistent: opts.persistent
|
|
16123
17137
|
};
|
|
@@ -16126,13 +17140,13 @@ var NodeFsHandler = class {
|
|
|
16126
17140
|
let closer;
|
|
16127
17141
|
if (opts.usePolling) {
|
|
16128
17142
|
const enableBin = opts.interval !== opts.binaryInterval;
|
|
16129
|
-
options.interval = enableBin && isBinaryPath(
|
|
16130
|
-
closer = setFsWatchFileListener(
|
|
17143
|
+
options.interval = enableBin && isBinaryPath(basename10) ? opts.binaryInterval : opts.interval;
|
|
17144
|
+
closer = setFsWatchFileListener(path31, absolutePath, options, {
|
|
16131
17145
|
listener,
|
|
16132
17146
|
rawEmitter: this.fsw._emitRaw
|
|
16133
17147
|
});
|
|
16134
17148
|
} else {
|
|
16135
|
-
closer = setFsWatchListener(
|
|
17149
|
+
closer = setFsWatchListener(path31, absolutePath, options, {
|
|
16136
17150
|
listener,
|
|
16137
17151
|
errHandler: this._boundHandleError,
|
|
16138
17152
|
rawEmitter: this.fsw._emitRaw
|
|
@@ -16148,13 +17162,13 @@ var NodeFsHandler = class {
|
|
|
16148
17162
|
if (this.fsw.closed) {
|
|
16149
17163
|
return;
|
|
16150
17164
|
}
|
|
16151
|
-
const
|
|
16152
|
-
const
|
|
16153
|
-
const parent = this.fsw._getWatchedDir(
|
|
17165
|
+
const dirname16 = sp.dirname(file);
|
|
17166
|
+
const basename10 = sp.basename(file);
|
|
17167
|
+
const parent = this.fsw._getWatchedDir(dirname16);
|
|
16154
17168
|
let prevStats = stats;
|
|
16155
|
-
if (parent.has(
|
|
17169
|
+
if (parent.has(basename10))
|
|
16156
17170
|
return;
|
|
16157
|
-
const listener = async (
|
|
17171
|
+
const listener = async (path31, newStats) => {
|
|
16158
17172
|
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
|
|
16159
17173
|
return;
|
|
16160
17174
|
if (!newStats || newStats.mtimeMs === 0) {
|
|
@@ -16168,18 +17182,18 @@ var NodeFsHandler = class {
|
|
|
16168
17182
|
this.fsw._emit(EV.CHANGE, file, newStats2);
|
|
16169
17183
|
}
|
|
16170
17184
|
if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
|
|
16171
|
-
this.fsw._closeFile(
|
|
17185
|
+
this.fsw._closeFile(path31);
|
|
16172
17186
|
prevStats = newStats2;
|
|
16173
17187
|
const closer2 = this._watchWithNodeFs(file, listener);
|
|
16174
17188
|
if (closer2)
|
|
16175
|
-
this.fsw._addPathCloser(
|
|
17189
|
+
this.fsw._addPathCloser(path31, closer2);
|
|
16176
17190
|
} else {
|
|
16177
17191
|
prevStats = newStats2;
|
|
16178
17192
|
}
|
|
16179
17193
|
} catch (error) {
|
|
16180
|
-
this.fsw._remove(
|
|
17194
|
+
this.fsw._remove(dirname16, basename10);
|
|
16181
17195
|
}
|
|
16182
|
-
} else if (parent.has(
|
|
17196
|
+
} else if (parent.has(basename10)) {
|
|
16183
17197
|
const at = newStats.atimeMs;
|
|
16184
17198
|
const mt = newStats.mtimeMs;
|
|
16185
17199
|
if (!at || at <= mt || mt !== prevStats.mtimeMs) {
|
|
@@ -16204,7 +17218,7 @@ var NodeFsHandler = class {
|
|
|
16204
17218
|
* @param item basename of this item
|
|
16205
17219
|
* @returns true if no more processing is needed for this entry.
|
|
16206
17220
|
*/
|
|
16207
|
-
async _handleSymlink(entry, directory,
|
|
17221
|
+
async _handleSymlink(entry, directory, path31, item) {
|
|
16208
17222
|
if (this.fsw.closed) {
|
|
16209
17223
|
return;
|
|
16210
17224
|
}
|
|
@@ -16214,7 +17228,7 @@ var NodeFsHandler = class {
|
|
|
16214
17228
|
this.fsw._incrReadyCount();
|
|
16215
17229
|
let linkPath;
|
|
16216
17230
|
try {
|
|
16217
|
-
linkPath = await fsrealpath(
|
|
17231
|
+
linkPath = await fsrealpath(path31);
|
|
16218
17232
|
} catch (e) {
|
|
16219
17233
|
this.fsw._emitReady();
|
|
16220
17234
|
return true;
|
|
@@ -16224,12 +17238,12 @@ var NodeFsHandler = class {
|
|
|
16224
17238
|
if (dir.has(item)) {
|
|
16225
17239
|
if (this.fsw._symlinkPaths.get(full) !== linkPath) {
|
|
16226
17240
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
16227
|
-
this.fsw._emit(EV.CHANGE,
|
|
17241
|
+
this.fsw._emit(EV.CHANGE, path31, entry.stats);
|
|
16228
17242
|
}
|
|
16229
17243
|
} else {
|
|
16230
17244
|
dir.add(item);
|
|
16231
17245
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
16232
|
-
this.fsw._emit(EV.ADD,
|
|
17246
|
+
this.fsw._emit(EV.ADD, path31, entry.stats);
|
|
16233
17247
|
}
|
|
16234
17248
|
this.fsw._emitReady();
|
|
16235
17249
|
return true;
|
|
@@ -16259,9 +17273,9 @@ var NodeFsHandler = class {
|
|
|
16259
17273
|
return;
|
|
16260
17274
|
}
|
|
16261
17275
|
const item = entry.path;
|
|
16262
|
-
let
|
|
17276
|
+
let path31 = sp.join(directory, item);
|
|
16263
17277
|
current.add(item);
|
|
16264
|
-
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory,
|
|
17278
|
+
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path31, item)) {
|
|
16265
17279
|
return;
|
|
16266
17280
|
}
|
|
16267
17281
|
if (this.fsw.closed) {
|
|
@@ -16270,11 +17284,11 @@ var NodeFsHandler = class {
|
|
|
16270
17284
|
}
|
|
16271
17285
|
if (item === target || !target && !previous.has(item)) {
|
|
16272
17286
|
this.fsw._incrReadyCount();
|
|
16273
|
-
|
|
16274
|
-
this._addToNodeFs(
|
|
17287
|
+
path31 = sp.join(dir, sp.relative(dir, path31));
|
|
17288
|
+
this._addToNodeFs(path31, initialAdd, wh, depth + 1);
|
|
16275
17289
|
}
|
|
16276
17290
|
}).on(EV.ERROR, this._boundHandleError);
|
|
16277
|
-
return new Promise((
|
|
17291
|
+
return new Promise((resolve18, reject) => {
|
|
16278
17292
|
if (!stream)
|
|
16279
17293
|
return reject();
|
|
16280
17294
|
stream.once(STR_END, () => {
|
|
@@ -16283,7 +17297,7 @@ var NodeFsHandler = class {
|
|
|
16283
17297
|
return;
|
|
16284
17298
|
}
|
|
16285
17299
|
const wasThrottled = throttler ? throttler.clear() : false;
|
|
16286
|
-
|
|
17300
|
+
resolve18(void 0);
|
|
16287
17301
|
previous.getChildren().filter((item) => {
|
|
16288
17302
|
return item !== directory && !current.has(item);
|
|
16289
17303
|
}).forEach((item) => {
|
|
@@ -16340,13 +17354,13 @@ var NodeFsHandler = class {
|
|
|
16340
17354
|
* @param depth Child path actually targeted for watch
|
|
16341
17355
|
* @param target Child path actually targeted for watch
|
|
16342
17356
|
*/
|
|
16343
|
-
async _addToNodeFs(
|
|
17357
|
+
async _addToNodeFs(path31, initialAdd, priorWh, depth, target) {
|
|
16344
17358
|
const ready = this.fsw._emitReady;
|
|
16345
|
-
if (this.fsw._isIgnored(
|
|
17359
|
+
if (this.fsw._isIgnored(path31) || this.fsw.closed) {
|
|
16346
17360
|
ready();
|
|
16347
17361
|
return false;
|
|
16348
17362
|
}
|
|
16349
|
-
const wh = this.fsw._getWatchHelpers(
|
|
17363
|
+
const wh = this.fsw._getWatchHelpers(path31);
|
|
16350
17364
|
if (priorWh) {
|
|
16351
17365
|
wh.filterPath = (entry) => priorWh.filterPath(entry);
|
|
16352
17366
|
wh.filterDir = (entry) => priorWh.filterDir(entry);
|
|
@@ -16362,8 +17376,8 @@ var NodeFsHandler = class {
|
|
|
16362
17376
|
const follow = this.fsw.options.followSymlinks;
|
|
16363
17377
|
let closer;
|
|
16364
17378
|
if (stats.isDirectory()) {
|
|
16365
|
-
const absPath = sp.resolve(
|
|
16366
|
-
const targetPath = follow ? await fsrealpath(
|
|
17379
|
+
const absPath = sp.resolve(path31);
|
|
17380
|
+
const targetPath = follow ? await fsrealpath(path31) : path31;
|
|
16367
17381
|
if (this.fsw.closed)
|
|
16368
17382
|
return;
|
|
16369
17383
|
closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
|
|
@@ -16373,29 +17387,29 @@ var NodeFsHandler = class {
|
|
|
16373
17387
|
this.fsw._symlinkPaths.set(absPath, targetPath);
|
|
16374
17388
|
}
|
|
16375
17389
|
} else if (stats.isSymbolicLink()) {
|
|
16376
|
-
const targetPath = follow ? await fsrealpath(
|
|
17390
|
+
const targetPath = follow ? await fsrealpath(path31) : path31;
|
|
16377
17391
|
if (this.fsw.closed)
|
|
16378
17392
|
return;
|
|
16379
17393
|
const parent = sp.dirname(wh.watchPath);
|
|
16380
17394
|
this.fsw._getWatchedDir(parent).add(wh.watchPath);
|
|
16381
17395
|
this.fsw._emit(EV.ADD, wh.watchPath, stats);
|
|
16382
|
-
closer = await this._handleDir(parent, stats, initialAdd, depth,
|
|
17396
|
+
closer = await this._handleDir(parent, stats, initialAdd, depth, path31, wh, targetPath);
|
|
16383
17397
|
if (this.fsw.closed)
|
|
16384
17398
|
return;
|
|
16385
17399
|
if (targetPath !== void 0) {
|
|
16386
|
-
this.fsw._symlinkPaths.set(sp.resolve(
|
|
17400
|
+
this.fsw._symlinkPaths.set(sp.resolve(path31), targetPath);
|
|
16387
17401
|
}
|
|
16388
17402
|
} else {
|
|
16389
17403
|
closer = this._handleFile(wh.watchPath, stats, initialAdd);
|
|
16390
17404
|
}
|
|
16391
17405
|
ready();
|
|
16392
17406
|
if (closer)
|
|
16393
|
-
this.fsw._addPathCloser(
|
|
17407
|
+
this.fsw._addPathCloser(path31, closer);
|
|
16394
17408
|
return false;
|
|
16395
17409
|
} catch (error) {
|
|
16396
17410
|
if (this.fsw._handleError(error)) {
|
|
16397
17411
|
ready();
|
|
16398
|
-
return
|
|
17412
|
+
return path31;
|
|
16399
17413
|
}
|
|
16400
17414
|
}
|
|
16401
17415
|
}
|
|
@@ -16438,24 +17452,24 @@ function createPattern(matcher) {
|
|
|
16438
17452
|
}
|
|
16439
17453
|
return () => false;
|
|
16440
17454
|
}
|
|
16441
|
-
function normalizePath2(
|
|
16442
|
-
if (typeof
|
|
17455
|
+
function normalizePath2(path31) {
|
|
17456
|
+
if (typeof path31 !== "string")
|
|
16443
17457
|
throw new Error("string expected");
|
|
16444
|
-
|
|
16445
|
-
|
|
17458
|
+
path31 = sp2.normalize(path31);
|
|
17459
|
+
path31 = path31.replace(/\\/g, "/");
|
|
16446
17460
|
let prepend = false;
|
|
16447
|
-
if (
|
|
17461
|
+
if (path31.startsWith("//"))
|
|
16448
17462
|
prepend = true;
|
|
16449
|
-
|
|
17463
|
+
path31 = path31.replace(DOUBLE_SLASH_RE, "/");
|
|
16450
17464
|
if (prepend)
|
|
16451
|
-
|
|
16452
|
-
return
|
|
17465
|
+
path31 = "/" + path31;
|
|
17466
|
+
return path31;
|
|
16453
17467
|
}
|
|
16454
17468
|
function matchPatterns(patterns, testString, stats) {
|
|
16455
|
-
const
|
|
17469
|
+
const path31 = normalizePath2(testString);
|
|
16456
17470
|
for (let index = 0; index < patterns.length; index++) {
|
|
16457
17471
|
const pattern = patterns[index];
|
|
16458
|
-
if (pattern(
|
|
17472
|
+
if (pattern(path31, stats)) {
|
|
16459
17473
|
return true;
|
|
16460
17474
|
}
|
|
16461
17475
|
}
|
|
@@ -16493,19 +17507,19 @@ var toUnix = (string) => {
|
|
|
16493
17507
|
}
|
|
16494
17508
|
return str;
|
|
16495
17509
|
};
|
|
16496
|
-
var normalizePathToUnix = (
|
|
16497
|
-
var normalizeIgnored = (cwd = "") => (
|
|
16498
|
-
if (typeof
|
|
16499
|
-
return normalizePathToUnix(sp2.isAbsolute(
|
|
17510
|
+
var normalizePathToUnix = (path31) => toUnix(sp2.normalize(toUnix(path31)));
|
|
17511
|
+
var normalizeIgnored = (cwd = "") => (path31) => {
|
|
17512
|
+
if (typeof path31 === "string") {
|
|
17513
|
+
return normalizePathToUnix(sp2.isAbsolute(path31) ? path31 : sp2.join(cwd, path31));
|
|
16500
17514
|
} else {
|
|
16501
|
-
return
|
|
17515
|
+
return path31;
|
|
16502
17516
|
}
|
|
16503
17517
|
};
|
|
16504
|
-
var getAbsolutePath = (
|
|
16505
|
-
if (sp2.isAbsolute(
|
|
16506
|
-
return
|
|
17518
|
+
var getAbsolutePath = (path31, cwd) => {
|
|
17519
|
+
if (sp2.isAbsolute(path31)) {
|
|
17520
|
+
return path31;
|
|
16507
17521
|
}
|
|
16508
|
-
return sp2.join(cwd,
|
|
17522
|
+
return sp2.join(cwd, path31);
|
|
16509
17523
|
};
|
|
16510
17524
|
var EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
|
|
16511
17525
|
var DirEntry = class {
|
|
@@ -16570,10 +17584,10 @@ var WatchHelper = class {
|
|
|
16570
17584
|
dirParts;
|
|
16571
17585
|
followSymlinks;
|
|
16572
17586
|
statMethod;
|
|
16573
|
-
constructor(
|
|
17587
|
+
constructor(path31, follow, fsw) {
|
|
16574
17588
|
this.fsw = fsw;
|
|
16575
|
-
const watchPath =
|
|
16576
|
-
this.path =
|
|
17589
|
+
const watchPath = path31;
|
|
17590
|
+
this.path = path31 = path31.replace(REPLACER_RE, "");
|
|
16577
17591
|
this.watchPath = watchPath;
|
|
16578
17592
|
this.fullWatchPath = sp2.resolve(watchPath);
|
|
16579
17593
|
this.dirParts = [];
|
|
@@ -16713,20 +17727,20 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
16713
17727
|
this._closePromise = void 0;
|
|
16714
17728
|
let paths = unifyPaths(paths_);
|
|
16715
17729
|
if (cwd) {
|
|
16716
|
-
paths = paths.map((
|
|
16717
|
-
const absPath = getAbsolutePath(
|
|
17730
|
+
paths = paths.map((path31) => {
|
|
17731
|
+
const absPath = getAbsolutePath(path31, cwd);
|
|
16718
17732
|
return absPath;
|
|
16719
17733
|
});
|
|
16720
17734
|
}
|
|
16721
|
-
paths.forEach((
|
|
16722
|
-
this._removeIgnoredPath(
|
|
17735
|
+
paths.forEach((path31) => {
|
|
17736
|
+
this._removeIgnoredPath(path31);
|
|
16723
17737
|
});
|
|
16724
17738
|
this._userIgnored = void 0;
|
|
16725
17739
|
if (!this._readyCount)
|
|
16726
17740
|
this._readyCount = 0;
|
|
16727
17741
|
this._readyCount += paths.length;
|
|
16728
|
-
Promise.all(paths.map(async (
|
|
16729
|
-
const res = await this._nodeFsHandler._addToNodeFs(
|
|
17742
|
+
Promise.all(paths.map(async (path31) => {
|
|
17743
|
+
const res = await this._nodeFsHandler._addToNodeFs(path31, !_internal, void 0, 0, _origAdd);
|
|
16730
17744
|
if (res)
|
|
16731
17745
|
this._emitReady();
|
|
16732
17746
|
return res;
|
|
@@ -16748,17 +17762,17 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
16748
17762
|
return this;
|
|
16749
17763
|
const paths = unifyPaths(paths_);
|
|
16750
17764
|
const { cwd } = this.options;
|
|
16751
|
-
paths.forEach((
|
|
16752
|
-
if (!sp2.isAbsolute(
|
|
17765
|
+
paths.forEach((path31) => {
|
|
17766
|
+
if (!sp2.isAbsolute(path31) && !this._closers.has(path31)) {
|
|
16753
17767
|
if (cwd)
|
|
16754
|
-
|
|
16755
|
-
|
|
17768
|
+
path31 = sp2.join(cwd, path31);
|
|
17769
|
+
path31 = sp2.resolve(path31);
|
|
16756
17770
|
}
|
|
16757
|
-
this._closePath(
|
|
16758
|
-
this._addIgnoredPath(
|
|
16759
|
-
if (this._watched.has(
|
|
17771
|
+
this._closePath(path31);
|
|
17772
|
+
this._addIgnoredPath(path31);
|
|
17773
|
+
if (this._watched.has(path31)) {
|
|
16760
17774
|
this._addIgnoredPath({
|
|
16761
|
-
path:
|
|
17775
|
+
path: path31,
|
|
16762
17776
|
recursive: true
|
|
16763
17777
|
});
|
|
16764
17778
|
}
|
|
@@ -16822,38 +17836,38 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
16822
17836
|
* @param stats arguments to be passed with event
|
|
16823
17837
|
* @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
|
|
16824
17838
|
*/
|
|
16825
|
-
async _emit(event,
|
|
17839
|
+
async _emit(event, path31, stats) {
|
|
16826
17840
|
if (this.closed)
|
|
16827
17841
|
return;
|
|
16828
17842
|
const opts = this.options;
|
|
16829
17843
|
if (isWindows)
|
|
16830
|
-
|
|
17844
|
+
path31 = sp2.normalize(path31);
|
|
16831
17845
|
if (opts.cwd)
|
|
16832
|
-
|
|
16833
|
-
const args = [
|
|
17846
|
+
path31 = sp2.relative(opts.cwd, path31);
|
|
17847
|
+
const args = [path31];
|
|
16834
17848
|
if (stats != null)
|
|
16835
17849
|
args.push(stats);
|
|
16836
17850
|
const awf = opts.awaitWriteFinish;
|
|
16837
17851
|
let pw;
|
|
16838
|
-
if (awf && (pw = this._pendingWrites.get(
|
|
17852
|
+
if (awf && (pw = this._pendingWrites.get(path31))) {
|
|
16839
17853
|
pw.lastChange = /* @__PURE__ */ new Date();
|
|
16840
17854
|
return this;
|
|
16841
17855
|
}
|
|
16842
17856
|
if (opts.atomic) {
|
|
16843
17857
|
if (event === EVENTS.UNLINK) {
|
|
16844
|
-
this._pendingUnlinks.set(
|
|
17858
|
+
this._pendingUnlinks.set(path31, [event, ...args]);
|
|
16845
17859
|
setTimeout(() => {
|
|
16846
|
-
this._pendingUnlinks.forEach((entry,
|
|
17860
|
+
this._pendingUnlinks.forEach((entry, path32) => {
|
|
16847
17861
|
this.emit(...entry);
|
|
16848
17862
|
this.emit(EVENTS.ALL, ...entry);
|
|
16849
|
-
this._pendingUnlinks.delete(
|
|
17863
|
+
this._pendingUnlinks.delete(path32);
|
|
16850
17864
|
});
|
|
16851
17865
|
}, typeof opts.atomic === "number" ? opts.atomic : 100);
|
|
16852
17866
|
return this;
|
|
16853
17867
|
}
|
|
16854
|
-
if (event === EVENTS.ADD && this._pendingUnlinks.has(
|
|
17868
|
+
if (event === EVENTS.ADD && this._pendingUnlinks.has(path31)) {
|
|
16855
17869
|
event = EVENTS.CHANGE;
|
|
16856
|
-
this._pendingUnlinks.delete(
|
|
17870
|
+
this._pendingUnlinks.delete(path31);
|
|
16857
17871
|
}
|
|
16858
17872
|
}
|
|
16859
17873
|
if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
|
|
@@ -16871,16 +17885,16 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
16871
17885
|
this.emitWithAll(event, args);
|
|
16872
17886
|
}
|
|
16873
17887
|
};
|
|
16874
|
-
this._awaitWriteFinish(
|
|
17888
|
+
this._awaitWriteFinish(path31, awf.stabilityThreshold, event, awfEmit);
|
|
16875
17889
|
return this;
|
|
16876
17890
|
}
|
|
16877
17891
|
if (event === EVENTS.CHANGE) {
|
|
16878
|
-
const isThrottled = !this._throttle(EVENTS.CHANGE,
|
|
17892
|
+
const isThrottled = !this._throttle(EVENTS.CHANGE, path31, 50);
|
|
16879
17893
|
if (isThrottled)
|
|
16880
17894
|
return this;
|
|
16881
17895
|
}
|
|
16882
17896
|
if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
|
|
16883
|
-
const fullPath = opts.cwd ? sp2.join(opts.cwd,
|
|
17897
|
+
const fullPath = opts.cwd ? sp2.join(opts.cwd, path31) : path31;
|
|
16884
17898
|
let stats2;
|
|
16885
17899
|
try {
|
|
16886
17900
|
stats2 = await stat3(fullPath);
|
|
@@ -16911,23 +17925,23 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
16911
17925
|
* @param timeout duration of time to suppress duplicate actions
|
|
16912
17926
|
* @returns tracking object or false if action should be suppressed
|
|
16913
17927
|
*/
|
|
16914
|
-
_throttle(actionType,
|
|
17928
|
+
_throttle(actionType, path31, timeout) {
|
|
16915
17929
|
if (!this._throttled.has(actionType)) {
|
|
16916
17930
|
this._throttled.set(actionType, /* @__PURE__ */ new Map());
|
|
16917
17931
|
}
|
|
16918
17932
|
const action = this._throttled.get(actionType);
|
|
16919
17933
|
if (!action)
|
|
16920
17934
|
throw new Error("invalid throttle");
|
|
16921
|
-
const actionPath = action.get(
|
|
17935
|
+
const actionPath = action.get(path31);
|
|
16922
17936
|
if (actionPath) {
|
|
16923
17937
|
actionPath.count++;
|
|
16924
17938
|
return false;
|
|
16925
17939
|
}
|
|
16926
17940
|
let timeoutObject;
|
|
16927
17941
|
const clear = () => {
|
|
16928
|
-
const item = action.get(
|
|
17942
|
+
const item = action.get(path31);
|
|
16929
17943
|
const count = item ? item.count : 0;
|
|
16930
|
-
action.delete(
|
|
17944
|
+
action.delete(path31);
|
|
16931
17945
|
clearTimeout(timeoutObject);
|
|
16932
17946
|
if (item)
|
|
16933
17947
|
clearTimeout(item.timeoutObject);
|
|
@@ -16935,7 +17949,7 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
16935
17949
|
};
|
|
16936
17950
|
timeoutObject = setTimeout(clear, timeout);
|
|
16937
17951
|
const thr = { timeoutObject, clear, count: 0 };
|
|
16938
|
-
action.set(
|
|
17952
|
+
action.set(path31, thr);
|
|
16939
17953
|
return thr;
|
|
16940
17954
|
}
|
|
16941
17955
|
_incrReadyCount() {
|
|
@@ -16949,44 +17963,44 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
16949
17963
|
* @param event
|
|
16950
17964
|
* @param awfEmit Callback to be called when ready for event to be emitted.
|
|
16951
17965
|
*/
|
|
16952
|
-
_awaitWriteFinish(
|
|
17966
|
+
_awaitWriteFinish(path31, threshold, event, awfEmit) {
|
|
16953
17967
|
const awf = this.options.awaitWriteFinish;
|
|
16954
17968
|
if (typeof awf !== "object")
|
|
16955
17969
|
return;
|
|
16956
17970
|
const pollInterval = awf.pollInterval;
|
|
16957
17971
|
let timeoutHandler;
|
|
16958
|
-
let fullPath =
|
|
16959
|
-
if (this.options.cwd && !sp2.isAbsolute(
|
|
16960
|
-
fullPath = sp2.join(this.options.cwd,
|
|
17972
|
+
let fullPath = path31;
|
|
17973
|
+
if (this.options.cwd && !sp2.isAbsolute(path31)) {
|
|
17974
|
+
fullPath = sp2.join(this.options.cwd, path31);
|
|
16961
17975
|
}
|
|
16962
17976
|
const now2 = /* @__PURE__ */ new Date();
|
|
16963
17977
|
const writes = this._pendingWrites;
|
|
16964
17978
|
function awaitWriteFinishFn(prevStat) {
|
|
16965
17979
|
statcb(fullPath, (err, curStat) => {
|
|
16966
|
-
if (err || !writes.has(
|
|
17980
|
+
if (err || !writes.has(path31)) {
|
|
16967
17981
|
if (err && err.code !== "ENOENT")
|
|
16968
17982
|
awfEmit(err);
|
|
16969
17983
|
return;
|
|
16970
17984
|
}
|
|
16971
17985
|
const now3 = Number(/* @__PURE__ */ new Date());
|
|
16972
17986
|
if (prevStat && curStat.size !== prevStat.size) {
|
|
16973
|
-
writes.get(
|
|
17987
|
+
writes.get(path31).lastChange = now3;
|
|
16974
17988
|
}
|
|
16975
|
-
const pw = writes.get(
|
|
17989
|
+
const pw = writes.get(path31);
|
|
16976
17990
|
const df = now3 - pw.lastChange;
|
|
16977
17991
|
if (df >= threshold) {
|
|
16978
|
-
writes.delete(
|
|
17992
|
+
writes.delete(path31);
|
|
16979
17993
|
awfEmit(void 0, curStat);
|
|
16980
17994
|
} else {
|
|
16981
17995
|
timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
|
|
16982
17996
|
}
|
|
16983
17997
|
});
|
|
16984
17998
|
}
|
|
16985
|
-
if (!writes.has(
|
|
16986
|
-
writes.set(
|
|
17999
|
+
if (!writes.has(path31)) {
|
|
18000
|
+
writes.set(path31, {
|
|
16987
18001
|
lastChange: now2,
|
|
16988
18002
|
cancelWait: () => {
|
|
16989
|
-
writes.delete(
|
|
18003
|
+
writes.delete(path31);
|
|
16990
18004
|
clearTimeout(timeoutHandler);
|
|
16991
18005
|
return event;
|
|
16992
18006
|
}
|
|
@@ -16997,8 +18011,8 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
16997
18011
|
/**
|
|
16998
18012
|
* Determines whether user has asked to ignore this path.
|
|
16999
18013
|
*/
|
|
17000
|
-
_isIgnored(
|
|
17001
|
-
if (this.options.atomic && DOT_RE.test(
|
|
18014
|
+
_isIgnored(path31, stats) {
|
|
18015
|
+
if (this.options.atomic && DOT_RE.test(path31))
|
|
17002
18016
|
return true;
|
|
17003
18017
|
if (!this._userIgnored) {
|
|
17004
18018
|
const { cwd } = this.options;
|
|
@@ -17008,17 +18022,17 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
17008
18022
|
const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
|
|
17009
18023
|
this._userIgnored = anymatch(list, void 0);
|
|
17010
18024
|
}
|
|
17011
|
-
return this._userIgnored(
|
|
18025
|
+
return this._userIgnored(path31, stats);
|
|
17012
18026
|
}
|
|
17013
|
-
_isntIgnored(
|
|
17014
|
-
return !this._isIgnored(
|
|
18027
|
+
_isntIgnored(path31, stat5) {
|
|
18028
|
+
return !this._isIgnored(path31, stat5);
|
|
17015
18029
|
}
|
|
17016
18030
|
/**
|
|
17017
18031
|
* Provides a set of common helpers and properties relating to symlink handling.
|
|
17018
18032
|
* @param path file or directory pattern being watched
|
|
17019
18033
|
*/
|
|
17020
|
-
_getWatchHelpers(
|
|
17021
|
-
return new WatchHelper(
|
|
18034
|
+
_getWatchHelpers(path31) {
|
|
18035
|
+
return new WatchHelper(path31, this.options.followSymlinks, this);
|
|
17022
18036
|
}
|
|
17023
18037
|
// Directory helpers
|
|
17024
18038
|
// -----------------
|
|
@@ -17050,63 +18064,63 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
17050
18064
|
* @param item base path of item/directory
|
|
17051
18065
|
*/
|
|
17052
18066
|
_remove(directory, item, isDirectory) {
|
|
17053
|
-
const
|
|
17054
|
-
const fullPath = sp2.resolve(
|
|
17055
|
-
isDirectory = isDirectory != null ? isDirectory : this._watched.has(
|
|
17056
|
-
if (!this._throttle("remove",
|
|
18067
|
+
const path31 = sp2.join(directory, item);
|
|
18068
|
+
const fullPath = sp2.resolve(path31);
|
|
18069
|
+
isDirectory = isDirectory != null ? isDirectory : this._watched.has(path31) || this._watched.has(fullPath);
|
|
18070
|
+
if (!this._throttle("remove", path31, 100))
|
|
17057
18071
|
return;
|
|
17058
18072
|
if (!isDirectory && this._watched.size === 1) {
|
|
17059
18073
|
this.add(directory, item, true);
|
|
17060
18074
|
}
|
|
17061
|
-
const wp = this._getWatchedDir(
|
|
18075
|
+
const wp = this._getWatchedDir(path31);
|
|
17062
18076
|
const nestedDirectoryChildren = wp.getChildren();
|
|
17063
|
-
nestedDirectoryChildren.forEach((nested) => this._remove(
|
|
18077
|
+
nestedDirectoryChildren.forEach((nested) => this._remove(path31, nested));
|
|
17064
18078
|
const parent = this._getWatchedDir(directory);
|
|
17065
18079
|
const wasTracked = parent.has(item);
|
|
17066
18080
|
parent.remove(item);
|
|
17067
18081
|
if (this._symlinkPaths.has(fullPath)) {
|
|
17068
18082
|
this._symlinkPaths.delete(fullPath);
|
|
17069
18083
|
}
|
|
17070
|
-
let relPath =
|
|
18084
|
+
let relPath = path31;
|
|
17071
18085
|
if (this.options.cwd)
|
|
17072
|
-
relPath = sp2.relative(this.options.cwd,
|
|
18086
|
+
relPath = sp2.relative(this.options.cwd, path31);
|
|
17073
18087
|
if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
|
|
17074
18088
|
const event = this._pendingWrites.get(relPath).cancelWait();
|
|
17075
18089
|
if (event === EVENTS.ADD)
|
|
17076
18090
|
return;
|
|
17077
18091
|
}
|
|
17078
|
-
this._watched.delete(
|
|
18092
|
+
this._watched.delete(path31);
|
|
17079
18093
|
this._watched.delete(fullPath);
|
|
17080
18094
|
const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
|
|
17081
|
-
if (wasTracked && !this._isIgnored(
|
|
17082
|
-
this._emit(eventName,
|
|
17083
|
-
this._closePath(
|
|
18095
|
+
if (wasTracked && !this._isIgnored(path31))
|
|
18096
|
+
this._emit(eventName, path31);
|
|
18097
|
+
this._closePath(path31);
|
|
17084
18098
|
}
|
|
17085
18099
|
/**
|
|
17086
18100
|
* Closes all watchers for a path
|
|
17087
18101
|
*/
|
|
17088
|
-
_closePath(
|
|
17089
|
-
this._closeFile(
|
|
17090
|
-
const dir = sp2.dirname(
|
|
17091
|
-
this._getWatchedDir(dir).remove(sp2.basename(
|
|
18102
|
+
_closePath(path31) {
|
|
18103
|
+
this._closeFile(path31);
|
|
18104
|
+
const dir = sp2.dirname(path31);
|
|
18105
|
+
this._getWatchedDir(dir).remove(sp2.basename(path31));
|
|
17092
18106
|
}
|
|
17093
18107
|
/**
|
|
17094
18108
|
* Closes only file-specific watchers
|
|
17095
18109
|
*/
|
|
17096
|
-
_closeFile(
|
|
17097
|
-
const closers = this._closers.get(
|
|
18110
|
+
_closeFile(path31) {
|
|
18111
|
+
const closers = this._closers.get(path31);
|
|
17098
18112
|
if (!closers)
|
|
17099
18113
|
return;
|
|
17100
18114
|
closers.forEach((closer) => closer());
|
|
17101
|
-
this._closers.delete(
|
|
18115
|
+
this._closers.delete(path31);
|
|
17102
18116
|
}
|
|
17103
|
-
_addPathCloser(
|
|
18117
|
+
_addPathCloser(path31, closer) {
|
|
17104
18118
|
if (!closer)
|
|
17105
18119
|
return;
|
|
17106
|
-
let list = this._closers.get(
|
|
18120
|
+
let list = this._closers.get(path31);
|
|
17107
18121
|
if (!list) {
|
|
17108
18122
|
list = [];
|
|
17109
|
-
this._closers.set(
|
|
18123
|
+
this._closers.set(path31, list);
|
|
17110
18124
|
}
|
|
17111
18125
|
list.push(closer);
|
|
17112
18126
|
}
|
|
@@ -17136,11 +18150,11 @@ function watch(paths, options = {}) {
|
|
|
17136
18150
|
var chokidar_default = { watch, FSWatcher };
|
|
17137
18151
|
|
|
17138
18152
|
// src/watcher/file-watcher.ts
|
|
17139
|
-
import * as
|
|
18153
|
+
import * as path24 from "path";
|
|
17140
18154
|
|
|
17141
18155
|
// src/watcher/native-recursive-watcher.ts
|
|
17142
18156
|
import { watch as watch2 } from "fs";
|
|
17143
|
-
import * as
|
|
18157
|
+
import * as path22 from "path";
|
|
17144
18158
|
var NativeRecursiveWatcher = class {
|
|
17145
18159
|
constructor(root, onChange, options = {}) {
|
|
17146
18160
|
this.root = root;
|
|
@@ -17188,9 +18202,9 @@ var NativeRecursiveWatcher = class {
|
|
|
17188
18202
|
toAbsolutePath(filename) {
|
|
17189
18203
|
if (filename == null) return null;
|
|
17190
18204
|
const normalizedFilename = typeof filename === "string" ? filename : filename.toString();
|
|
17191
|
-
const absolutePath =
|
|
17192
|
-
const relativePath =
|
|
17193
|
-
const outsideRoot = relativePath === ".." || relativePath.startsWith(`..${
|
|
18205
|
+
const absolutePath = path22.resolve(this.root, normalizedFilename);
|
|
18206
|
+
const relativePath = path22.relative(this.root, absolutePath);
|
|
18207
|
+
const outsideRoot = relativePath === ".." || relativePath.startsWith(`..${path22.sep}`) || path22.isAbsolute(relativePath);
|
|
17194
18208
|
return outsideRoot ? null : absolutePath;
|
|
17195
18209
|
}
|
|
17196
18210
|
defaultWatchFactory = (root, listener, options) => watch2(root, options, listener);
|
|
@@ -17198,16 +18212,16 @@ var NativeRecursiveWatcher = class {
|
|
|
17198
18212
|
|
|
17199
18213
|
// src/watcher/snapshot.ts
|
|
17200
18214
|
import * as fsPromises4 from "fs/promises";
|
|
17201
|
-
import * as
|
|
18215
|
+
import * as path23 from "path";
|
|
17202
18216
|
async function buildFileSnapshotScan(projectRoot, config, configPaths = []) {
|
|
17203
|
-
const normalizedProjectRoot =
|
|
18217
|
+
const normalizedProjectRoot = path23.resolve(projectRoot);
|
|
17204
18218
|
const ignoreFilter = createIgnoreFilter(normalizedProjectRoot);
|
|
17205
18219
|
const includePatterns = [...config.include, ...config.additionalInclude ?? []];
|
|
17206
18220
|
const maxDepth = config.indexing?.maxDepth ?? -1;
|
|
17207
18221
|
const snapshot = /* @__PURE__ */ new Map();
|
|
17208
18222
|
const unreadablePrefixes = /* @__PURE__ */ new Set();
|
|
17209
18223
|
const includeFile = async (filePath) => {
|
|
17210
|
-
const normalizedPath2 =
|
|
18224
|
+
const normalizedPath2 = path23.resolve(filePath);
|
|
17211
18225
|
if (!shouldIncludeFile(normalizedPath2, normalizedProjectRoot, includePatterns, config.exclude, ignoreFilter)) return;
|
|
17212
18226
|
const stat5 = await readStatIfFile(normalizedPath2, unreadablePrefixes);
|
|
17213
18227
|
if (stat5) snapshot.set(normalizedPath2, { size: stat5.size, mtimeMs: stat5.mtimeMs });
|
|
@@ -17219,16 +18233,16 @@ async function buildFileSnapshotScan(projectRoot, config, configPaths = []) {
|
|
|
17219
18233
|
} catch (error) {
|
|
17220
18234
|
if (isMissingFsError(error)) return;
|
|
17221
18235
|
if (isPermissionFsError(error)) {
|
|
17222
|
-
unreadablePrefixes.add(
|
|
18236
|
+
unreadablePrefixes.add(path23.resolve(directoryPath));
|
|
17223
18237
|
return;
|
|
17224
18238
|
}
|
|
17225
18239
|
throw error;
|
|
17226
18240
|
}
|
|
17227
18241
|
for (const entry of entries) {
|
|
17228
|
-
const fullPath =
|
|
17229
|
-
const relativePath =
|
|
18242
|
+
const fullPath = path23.join(directoryPath, entry.name);
|
|
18243
|
+
const relativePath = path23.relative(normalizedProjectRoot, fullPath);
|
|
17230
18244
|
if (entry.isDirectory()) {
|
|
17231
|
-
if (hasFilteredPathSegment(relativePath,
|
|
18245
|
+
if (hasFilteredPathSegment(relativePath, path23.sep) || isRestrictedDirectory(relativePath, path23.sep)) continue;
|
|
17232
18246
|
if (ignoreFilter.ignores(relativePath)) continue;
|
|
17233
18247
|
if (maxDepth === -1 || depth < maxDepth) await walk(fullPath, depth + 1);
|
|
17234
18248
|
} else if (entry.isFile()) {
|
|
@@ -17241,19 +18255,19 @@ async function buildFileSnapshotScan(projectRoot, config, configPaths = []) {
|
|
|
17241
18255
|
return { entries: snapshot, unreadablePrefixes };
|
|
17242
18256
|
}
|
|
17243
18257
|
async function buildFileSnapshotForPathScan(projectRoot, config, configPaths, targetPath) {
|
|
17244
|
-
const normalizedProjectRoot =
|
|
17245
|
-
const normalizedTargetPath =
|
|
18258
|
+
const normalizedProjectRoot = path23.resolve(projectRoot);
|
|
18259
|
+
const normalizedTargetPath = path23.resolve(targetPath);
|
|
17246
18260
|
if (!isWithinPath(normalizedProjectRoot, normalizedTargetPath)) {
|
|
17247
18261
|
return { entries: /* @__PURE__ */ new Map(), unreadablePrefixes: /* @__PURE__ */ new Set() };
|
|
17248
18262
|
}
|
|
17249
18263
|
const ignoreFilter = createIgnoreFilter(normalizedProjectRoot);
|
|
17250
18264
|
const includePatterns = [...config.include, ...config.additionalInclude ?? []];
|
|
17251
18265
|
const maxDepth = config.indexing?.maxDepth ?? -1;
|
|
17252
|
-
const explicitConfigPaths = new Set(configPaths.map((configPath) =>
|
|
18266
|
+
const explicitConfigPaths = new Set(configPaths.map((configPath) => path23.resolve(configPath)));
|
|
17253
18267
|
const snapshot = /* @__PURE__ */ new Map();
|
|
17254
18268
|
const unreadablePrefixes = /* @__PURE__ */ new Set();
|
|
17255
18269
|
const includeFile = async (filePath) => {
|
|
17256
|
-
const normalizedPath2 =
|
|
18270
|
+
const normalizedPath2 = path23.resolve(filePath);
|
|
17257
18271
|
if (!explicitConfigPaths.has(normalizedPath2) && !shouldIncludeFile(
|
|
17258
18272
|
normalizedPath2,
|
|
17259
18273
|
normalizedProjectRoot,
|
|
@@ -17271,16 +18285,16 @@ async function buildFileSnapshotForPathScan(projectRoot, config, configPaths, ta
|
|
|
17271
18285
|
} catch (error) {
|
|
17272
18286
|
if (isMissingFsError(error)) return;
|
|
17273
18287
|
if (isPermissionFsError(error)) {
|
|
17274
|
-
unreadablePrefixes.add(
|
|
18288
|
+
unreadablePrefixes.add(path23.resolve(directoryPath));
|
|
17275
18289
|
return;
|
|
17276
18290
|
}
|
|
17277
18291
|
throw error;
|
|
17278
18292
|
}
|
|
17279
18293
|
for (const entry of entries) {
|
|
17280
|
-
const fullPath =
|
|
17281
|
-
const relativePath =
|
|
18294
|
+
const fullPath = path23.join(directoryPath, entry.name);
|
|
18295
|
+
const relativePath = path23.relative(normalizedProjectRoot, fullPath);
|
|
17282
18296
|
if (entry.isDirectory()) {
|
|
17283
|
-
if (hasFilteredPathSegment(relativePath,
|
|
18297
|
+
if (hasFilteredPathSegment(relativePath, path23.sep) || isRestrictedDirectory(relativePath, path23.sep)) continue;
|
|
17284
18298
|
if (ignoreFilter.ignores(relativePath)) continue;
|
|
17285
18299
|
if (maxDepth === -1 || depth < maxDepth) await walk(fullPath, depth + 1);
|
|
17286
18300
|
} else if (entry.isFile()) {
|
|
@@ -17304,7 +18318,7 @@ function completeFileSnapshot(previous, scan) {
|
|
|
17304
18318
|
return completed;
|
|
17305
18319
|
}
|
|
17306
18320
|
async function includeExplicitConfigPaths(snapshot, unreadablePrefixes, configPaths) {
|
|
17307
|
-
for (const configPath of [...new Set(configPaths.map((value) =>
|
|
18321
|
+
for (const configPath of [...new Set(configPaths.map((value) => path23.resolve(value)))]) {
|
|
17308
18322
|
if (snapshot.has(configPath)) continue;
|
|
17309
18323
|
const stat5 = await readStatIfFile(configPath, unreadablePrefixes);
|
|
17310
18324
|
if (stat5) snapshot.set(configPath, { size: stat5.size, mtimeMs: stat5.mtimeMs });
|
|
@@ -17314,12 +18328,12 @@ async function includeExplicitConfigPathsInPath(snapshot, unreadablePrefixes, co
|
|
|
17314
18328
|
await includeExplicitConfigPaths(
|
|
17315
18329
|
snapshot,
|
|
17316
18330
|
unreadablePrefixes,
|
|
17317
|
-
configPaths.filter((configPath) => isWithinPath(targetPath,
|
|
18331
|
+
configPaths.filter((configPath) => isWithinPath(targetPath, path23.resolve(configPath)))
|
|
17318
18332
|
);
|
|
17319
18333
|
}
|
|
17320
18334
|
function isWithinPath(parentPath, childPath) {
|
|
17321
|
-
const relativePath =
|
|
17322
|
-
return relativePath === "" || !relativePath.startsWith(`..${
|
|
18335
|
+
const relativePath = path23.relative(parentPath, childPath);
|
|
18336
|
+
return relativePath === "" || !relativePath.startsWith(`..${path23.sep}`) && relativePath !== ".." && !path23.isAbsolute(relativePath);
|
|
17323
18337
|
}
|
|
17324
18338
|
async function readStatIfFile(filePath, unreadablePrefixes) {
|
|
17325
18339
|
try {
|
|
@@ -17328,7 +18342,7 @@ async function readStatIfFile(filePath, unreadablePrefixes) {
|
|
|
17328
18342
|
} catch (error) {
|
|
17329
18343
|
if (isMissingFsError(error)) return null;
|
|
17330
18344
|
if (isPermissionFsError(error)) {
|
|
17331
|
-
unreadablePrefixes.add(
|
|
18345
|
+
unreadablePrefixes.add(path23.resolve(filePath));
|
|
17332
18346
|
return null;
|
|
17333
18347
|
}
|
|
17334
18348
|
throw error;
|
|
@@ -17465,8 +18479,8 @@ var FileWatcher = class {
|
|
|
17465
18479
|
this.createWatcher();
|
|
17466
18480
|
}
|
|
17467
18481
|
resetReady() {
|
|
17468
|
-
this.readyPromise = new Promise((
|
|
17469
|
-
this.resolveReady =
|
|
18482
|
+
this.readyPromise = new Promise((resolve18) => {
|
|
18483
|
+
this.resolveReady = resolve18;
|
|
17470
18484
|
});
|
|
17471
18485
|
this.startupReadySignals = 1;
|
|
17472
18486
|
}
|
|
@@ -17497,7 +18511,7 @@ var FileWatcher = class {
|
|
|
17497
18511
|
const resolvedWatchTargets = watchTargets ?? this.getFullChokidarWatchTargets();
|
|
17498
18512
|
const watcherOptions = {
|
|
17499
18513
|
ignored: (filePath) => {
|
|
17500
|
-
const relativePath =
|
|
18514
|
+
const relativePath = path24.relative(this.projectRoot, filePath);
|
|
17501
18515
|
if (!relativePath) return false;
|
|
17502
18516
|
if (this.isProjectConfigPathOrAncestor(relativePath)) {
|
|
17503
18517
|
return false;
|
|
@@ -17505,10 +18519,10 @@ var FileWatcher = class {
|
|
|
17505
18519
|
if (this.isOutsideProjectPath(relativePath)) {
|
|
17506
18520
|
return true;
|
|
17507
18521
|
}
|
|
17508
|
-
if (hasFilteredPathSegment(relativePath,
|
|
18522
|
+
if (hasFilteredPathSegment(relativePath, path24.sep)) {
|
|
17509
18523
|
return true;
|
|
17510
18524
|
}
|
|
17511
|
-
if (isRestrictedDirectory(relativePath,
|
|
18525
|
+
if (isRestrictedDirectory(relativePath, path24.sep)) {
|
|
17512
18526
|
return true;
|
|
17513
18527
|
}
|
|
17514
18528
|
if (ignoreFilter.ignores(relativePath)) {
|
|
@@ -17599,13 +18613,13 @@ var FileWatcher = class {
|
|
|
17599
18613
|
getExternalConfigWatchTargets() {
|
|
17600
18614
|
return [...new Set(
|
|
17601
18615
|
this.projectConfigPaths.filter((projectConfigPath) => {
|
|
17602
|
-
const relativeConfigPath =
|
|
18616
|
+
const relativeConfigPath = path24.relative(this.projectRoot, projectConfigPath);
|
|
17603
18617
|
return this.isOutsideProjectPath(relativeConfigPath);
|
|
17604
18618
|
}).map((projectConfigPath) => {
|
|
17605
|
-
if (
|
|
18619
|
+
if (existsSync14(projectConfigPath)) {
|
|
17606
18620
|
return projectConfigPath;
|
|
17607
18621
|
}
|
|
17608
|
-
return this.getNearestExistingDirectory(
|
|
18622
|
+
return this.getNearestExistingDirectory(path24.dirname(projectConfigPath));
|
|
17609
18623
|
})
|
|
17610
18624
|
)];
|
|
17611
18625
|
}
|
|
@@ -17667,7 +18681,7 @@ var FileWatcher = class {
|
|
|
17667
18681
|
}
|
|
17668
18682
|
scheduleNativeReconciliation(generation, filePath) {
|
|
17669
18683
|
if (!this.isCurrentNativeSetup(generation)) return;
|
|
17670
|
-
const requiresFullReconciliation = filePath ===
|
|
18684
|
+
const requiresFullReconciliation = filePath === path24.join(this.projectRoot, ".gitignore");
|
|
17671
18685
|
const invalidatedPath = requiresFullReconciliation ? null : filePath;
|
|
17672
18686
|
this.nativeInvalidatedPaths.set(invalidatedPath, invalidatedPath !== null);
|
|
17673
18687
|
if (this.nativeReconcileTimer) {
|
|
@@ -17762,23 +18776,23 @@ var FileWatcher = class {
|
|
|
17762
18776
|
this.scheduleFlush();
|
|
17763
18777
|
}
|
|
17764
18778
|
isProjectConfigPath(filePath) {
|
|
17765
|
-
const relativePath =
|
|
17766
|
-
const normalizedRelativePath =
|
|
18779
|
+
const relativePath = path24.relative(this.projectRoot, filePath);
|
|
18780
|
+
const normalizedRelativePath = path24.normalize(relativePath);
|
|
17767
18781
|
return this.getProjectConfigRelativePaths().some((configPath) => configPath === normalizedRelativePath);
|
|
17768
18782
|
}
|
|
17769
18783
|
isProjectConfigPathOrAncestor(relativePath) {
|
|
17770
|
-
const normalizedRelativePath =
|
|
18784
|
+
const normalizedRelativePath = path24.normalize(relativePath);
|
|
17771
18785
|
return this.getProjectConfigRelativePaths().some(
|
|
17772
|
-
(configPath) => configPath === normalizedRelativePath || configPath.startsWith(`${normalizedRelativePath}${
|
|
18786
|
+
(configPath) => configPath === normalizedRelativePath || configPath.startsWith(`${normalizedRelativePath}${path24.sep}`)
|
|
17773
18787
|
);
|
|
17774
18788
|
}
|
|
17775
18789
|
isOutsideProjectPath(relativePath) {
|
|
17776
|
-
return relativePath === ".." || relativePath.startsWith(`..${
|
|
18790
|
+
return relativePath === ".." || relativePath.startsWith(`..${path24.sep}`) || path24.isAbsolute(relativePath);
|
|
17777
18791
|
}
|
|
17778
18792
|
getNearestExistingDirectory(directoryPath) {
|
|
17779
18793
|
let candidate = directoryPath;
|
|
17780
|
-
while (!
|
|
17781
|
-
const parent =
|
|
18794
|
+
while (!existsSync14(candidate)) {
|
|
18795
|
+
const parent = path24.dirname(candidate);
|
|
17782
18796
|
if (parent === candidate) break;
|
|
17783
18797
|
candidate = parent;
|
|
17784
18798
|
}
|
|
@@ -17786,7 +18800,7 @@ var FileWatcher = class {
|
|
|
17786
18800
|
}
|
|
17787
18801
|
getProjectConfigRelativePaths() {
|
|
17788
18802
|
return this.projectConfigPaths.map(
|
|
17789
|
-
(configPath) =>
|
|
18803
|
+
(configPath) => path24.normalize(path24.relative(this.projectRoot, configPath))
|
|
17790
18804
|
);
|
|
17791
18805
|
}
|
|
17792
18806
|
getConfigPathStates() {
|
|
@@ -17844,7 +18858,7 @@ var FileWatcher = class {
|
|
|
17844
18858
|
return;
|
|
17845
18859
|
}
|
|
17846
18860
|
const changes = Array.from(this.pendingChanges.entries()).map(
|
|
17847
|
-
([
|
|
18861
|
+
([path31, type]) => ({ path: path31, type })
|
|
17848
18862
|
);
|
|
17849
18863
|
this.pendingChanges.clear();
|
|
17850
18864
|
try {
|
|
@@ -17890,7 +18904,7 @@ var FileWatcher = class {
|
|
|
17890
18904
|
};
|
|
17891
18905
|
|
|
17892
18906
|
// src/watcher/git-head-watcher.ts
|
|
17893
|
-
import * as
|
|
18907
|
+
import * as path25 from "path";
|
|
17894
18908
|
var GitHeadWatcher = class {
|
|
17895
18909
|
watcher = null;
|
|
17896
18910
|
projectRoot;
|
|
@@ -17912,13 +18926,13 @@ var GitHeadWatcher = class {
|
|
|
17912
18926
|
this.readyPromise = Promise.resolve();
|
|
17913
18927
|
return;
|
|
17914
18928
|
}
|
|
17915
|
-
this.readyPromise = new Promise((
|
|
17916
|
-
this.resolveReady =
|
|
18929
|
+
this.readyPromise = new Promise((resolve18) => {
|
|
18930
|
+
this.resolveReady = resolve18;
|
|
17917
18931
|
});
|
|
17918
18932
|
this.onBranchChange = handler;
|
|
17919
18933
|
this.currentBranch = getCurrentBranch(this.projectRoot);
|
|
17920
18934
|
const headPath = getHeadPath(this.projectRoot);
|
|
17921
|
-
const refsPath =
|
|
18935
|
+
const refsPath = path25.join(this.projectRoot, ".git", "refs", "heads");
|
|
17922
18936
|
this.watcher = chokidar_default.watch([headPath, refsPath], {
|
|
17923
18937
|
persistent: true,
|
|
17924
18938
|
ignoreInitial: true,
|
|
@@ -17986,7 +19000,9 @@ var GitHeadWatcher = class {
|
|
|
17986
19000
|
function createWatcherWithIndexer(getIndexer, projectRoot, config, host, options = {}) {
|
|
17987
19001
|
const fileWatcher = new FileWatcher(projectRoot, config, host, options);
|
|
17988
19002
|
const configPaths = getConfigPaths(projectRoot, host, options);
|
|
17989
|
-
configureAutoIndex(projectRoot, host, parseConfig(config), getIndexer
|
|
19003
|
+
configureAutoIndex(projectRoot, host, parseConfig(config), getIndexer, {
|
|
19004
|
+
synchronizeBackgroundWorker: false
|
|
19005
|
+
});
|
|
17990
19006
|
let stopped = false;
|
|
17991
19007
|
const requestReindex = () => {
|
|
17992
19008
|
if (stopped) return;
|
|
@@ -18006,7 +19022,9 @@ function createWatcherWithIndexer(getIndexer, projectRoot, config, host, options
|
|
|
18006
19022
|
const parsedConfig = options.configPath ? parseConfig(loadConfigFile(options.configPath)) : void 0;
|
|
18007
19023
|
const refreshedConfig = refreshIndexerForDirectory(projectRoot, host, parsedConfig);
|
|
18008
19024
|
if (refreshedConfig) {
|
|
18009
|
-
configureAutoIndex(projectRoot, host, refreshedConfig, getIndexer
|
|
19025
|
+
configureAutoIndex(projectRoot, host, refreshedConfig, getIndexer, {
|
|
19026
|
+
synchronizeBackgroundWorker: false
|
|
19027
|
+
});
|
|
18010
19028
|
}
|
|
18011
19029
|
}
|
|
18012
19030
|
requestReindex();
|
|
@@ -18782,7 +19800,7 @@ async function resolveCodebaseContextUnmeasured(projectRoot, host, input) {
|
|
|
18782
19800
|
const directory = input.directory ?? void 0;
|
|
18783
19801
|
const tokenBudget = input.tokenBudget ?? void 0;
|
|
18784
19802
|
if (from && to) {
|
|
18785
|
-
const
|
|
19803
|
+
const path31 = await getCallGraphPath(
|
|
18786
19804
|
projectRoot,
|
|
18787
19805
|
host,
|
|
18788
19806
|
from,
|
|
@@ -18791,25 +19809,25 @@ async function resolveCodebaseContextUnmeasured(projectRoot, host, input) {
|
|
|
18791
19809
|
fromFilePath,
|
|
18792
19810
|
toFilePath
|
|
18793
19811
|
);
|
|
18794
|
-
const pathText = formatCallGraphPathResult(
|
|
18795
|
-
if (
|
|
19812
|
+
const pathText = formatCallGraphPathResult(path31);
|
|
19813
|
+
if (path31.path.length > 0) {
|
|
18796
19814
|
const fitted2 = fitTextToContextBudget(
|
|
18797
19815
|
pathText,
|
|
18798
19816
|
tokenBudget
|
|
18799
19817
|
);
|
|
18800
19818
|
return {
|
|
18801
19819
|
text: fitted2.text,
|
|
18802
|
-
details: fittedDetails("path", fitted2,
|
|
19820
|
+
details: fittedDetails("path", fitted2, path31.path.length)
|
|
18803
19821
|
};
|
|
18804
19822
|
}
|
|
18805
|
-
if (
|
|
19823
|
+
if (path31.from.status !== "resolved" || path31.to.status !== "resolved") {
|
|
18806
19824
|
const fitted2 = fitTextToContextBudget(pathText, tokenBudget);
|
|
18807
19825
|
return {
|
|
18808
19826
|
text: fitted2.text,
|
|
18809
19827
|
details: fittedDetails("path", fitted2, 0)
|
|
18810
19828
|
};
|
|
18811
19829
|
}
|
|
18812
|
-
const resolvedFrom =
|
|
19830
|
+
const resolvedFrom = path31.from;
|
|
18813
19831
|
const { callers } = await getCallGraphData(projectRoot, host, {
|
|
18814
19832
|
name: to,
|
|
18815
19833
|
direction: "callers",
|
|
@@ -18970,7 +19988,7 @@ async function executeCallGraph(projectRoot, host, args) {
|
|
|
18970
19988
|
return { text: formatCallGraphResult(await getCallGraphData(projectRoot, host, args)) };
|
|
18971
19989
|
}
|
|
18972
19990
|
async function executeCallGraphPath(projectRoot, host, args) {
|
|
18973
|
-
const
|
|
19991
|
+
const path31 = await getCallGraphPath(
|
|
18974
19992
|
projectRoot,
|
|
18975
19993
|
host,
|
|
18976
19994
|
args.from,
|
|
@@ -18979,7 +19997,7 @@ async function executeCallGraphPath(projectRoot, host, args) {
|
|
|
18979
19997
|
args.fromFilePath,
|
|
18980
19998
|
args.toFilePath
|
|
18981
19999
|
);
|
|
18982
|
-
return { text: formatCallGraphPathResult(
|
|
20000
|
+
return { text: formatCallGraphPathResult(path31) };
|
|
18983
20001
|
}
|
|
18984
20002
|
async function executeCodeCommunities(projectRoot, host, args) {
|
|
18985
20003
|
const result = await getCodeCommunities(projectRoot, host, args);
|
|
@@ -18987,13 +20005,13 @@ async function executeCodeCommunities(projectRoot, host, args) {
|
|
|
18987
20005
|
}
|
|
18988
20006
|
|
|
18989
20007
|
// src/adapters/opencode/tools.ts
|
|
18990
|
-
import { writeFileSync as
|
|
18991
|
-
import * as
|
|
18992
|
-
import * as
|
|
20008
|
+
import { writeFileSync as writeFileSync5 } from "fs";
|
|
20009
|
+
import * as os8 from "os";
|
|
20010
|
+
import * as path28 from "path";
|
|
18993
20011
|
|
|
18994
20012
|
// src/tools/visualize/activity.ts
|
|
18995
20013
|
import { execFileSync } from "child_process";
|
|
18996
|
-
import * as
|
|
20014
|
+
import * as path26 from "path";
|
|
18997
20015
|
function attachRecentActivity(data, projectRoot) {
|
|
18998
20016
|
const activity = readGitActivity(projectRoot);
|
|
18999
20017
|
const changes = activity.size > 0 ? buildGitChanges(data, activity, projectRoot) : buildGraphChanges(data);
|
|
@@ -19155,7 +20173,7 @@ function normalizePath3(filePath) {
|
|
|
19155
20173
|
return filePath.replace(/\\/g, "/");
|
|
19156
20174
|
}
|
|
19157
20175
|
function toGitRelativePath(projectRoot, filePath) {
|
|
19158
|
-
const relativePath =
|
|
20176
|
+
const relativePath = path26.isAbsolute(filePath) ? path26.relative(projectRoot, filePath) : filePath;
|
|
19159
20177
|
return normalizePath3(relativePath);
|
|
19160
20178
|
}
|
|
19161
20179
|
|
|
@@ -19413,7 +20431,7 @@ render();
|
|
|
19413
20431
|
}
|
|
19414
20432
|
|
|
19415
20433
|
// src/tools/visualize/transform.ts
|
|
19416
|
-
import * as
|
|
20434
|
+
import * as path27 from "path";
|
|
19417
20435
|
|
|
19418
20436
|
// src/tools/visualize/modules.ts
|
|
19419
20437
|
var MAX_MODULES = 18;
|
|
@@ -19673,7 +20691,7 @@ function transformForVisualization(symbols, edges, options = {}) {
|
|
|
19673
20691
|
filePath: s.filePath,
|
|
19674
20692
|
kind: s.kind,
|
|
19675
20693
|
line: s.startLine,
|
|
19676
|
-
directory:
|
|
20694
|
+
directory: path27.dirname(s.filePath),
|
|
19677
20695
|
moduleId: "",
|
|
19678
20696
|
moduleLabel: ""
|
|
19679
20697
|
}));
|
|
@@ -20002,8 +21020,8 @@ var index_visualize = tool({
|
|
|
20002
21020
|
return "No connected symbols found for visualization. Try including orphans with includeOrphans=true, or check that the call graph has resolved edges.";
|
|
20003
21021
|
}
|
|
20004
21022
|
const html = generateVisualizationHtml(vizData);
|
|
20005
|
-
const outputPath =
|
|
20006
|
-
|
|
21023
|
+
const outputPath = path28.join(os8.tmpdir(), `call-graph-${Date.now()}.html`);
|
|
21024
|
+
writeFileSync5(outputPath, html, "utf-8");
|
|
20007
21025
|
let result = `Temporal call graph visualization generated: ${outputPath}
|
|
20008
21026
|
|
|
20009
21027
|
`;
|
|
@@ -20114,8 +21132,8 @@ var MCP_TOOL_NAMES = [
|
|
|
20114
21132
|
];
|
|
20115
21133
|
|
|
20116
21134
|
// src/commands/loader.ts
|
|
20117
|
-
import { existsSync as
|
|
20118
|
-
import * as
|
|
21135
|
+
import { existsSync as existsSync15, readdirSync as readdirSync3, readFileSync as readFileSync10 } from "fs";
|
|
21136
|
+
import * as path29 from "path";
|
|
20119
21137
|
function parseFrontmatter(content) {
|
|
20120
21138
|
const frontmatterRegex = /^---\s*\n([\s\S]*?)\n---\s*\n([\s\S]*)$/;
|
|
20121
21139
|
const match = content.match(frontmatterRegex);
|
|
@@ -20136,21 +21154,21 @@ function parseFrontmatter(content) {
|
|
|
20136
21154
|
}
|
|
20137
21155
|
function loadCommandsFromDirectory(commandsDir) {
|
|
20138
21156
|
const commands = /* @__PURE__ */ new Map();
|
|
20139
|
-
if (!
|
|
21157
|
+
if (!existsSync15(commandsDir)) {
|
|
20140
21158
|
return commands;
|
|
20141
21159
|
}
|
|
20142
21160
|
const files = readdirSync3(commandsDir).filter((f) => f.endsWith(".md"));
|
|
20143
21161
|
for (const file of files) {
|
|
20144
|
-
const filePath =
|
|
21162
|
+
const filePath = path29.join(commandsDir, file);
|
|
20145
21163
|
let content;
|
|
20146
21164
|
try {
|
|
20147
|
-
content =
|
|
21165
|
+
content = readFileSync10(filePath, "utf-8");
|
|
20148
21166
|
} catch (error) {
|
|
20149
21167
|
const message = error instanceof Error ? error.message : String(error);
|
|
20150
21168
|
throw new Error(`Failed to load command file ${filePath}: ${message}`);
|
|
20151
21169
|
}
|
|
20152
21170
|
const { frontmatter, body } = parseFrontmatter(content);
|
|
20153
|
-
const name =
|
|
21171
|
+
const name = path29.basename(file, ".md");
|
|
20154
21172
|
const description = frontmatter.description || `Run the ${name} command`;
|
|
20155
21173
|
commands.set(name, {
|
|
20156
21174
|
description,
|
|
@@ -20485,42 +21503,13 @@ var RoutingHintController = class {
|
|
|
20485
21503
|
};
|
|
20486
21504
|
|
|
20487
21505
|
// src/adapters/opencode.ts
|
|
20488
|
-
var activeWatchers = /* @__PURE__ */ new Map();
|
|
20489
|
-
var watcherReplacementChains = /* @__PURE__ */ new Map();
|
|
20490
|
-
async function replaceActiveWatcher(projectRoot, createNextWatcher) {
|
|
20491
|
-
const chain = (watcherReplacementChains.get(projectRoot) ?? Promise.resolve()).catch(() => void 0).then(async () => {
|
|
20492
|
-
const existing = activeWatchers.get(projectRoot);
|
|
20493
|
-
if (existing) {
|
|
20494
|
-
try {
|
|
20495
|
-
await existing.stop();
|
|
20496
|
-
} catch (error) {
|
|
20497
|
-
console.error("[codebase-index] Failed to stop replaced watcher:", error);
|
|
20498
|
-
throw error;
|
|
20499
|
-
}
|
|
20500
|
-
if (activeWatchers.get(projectRoot) === existing) {
|
|
20501
|
-
activeWatchers.delete(projectRoot);
|
|
20502
|
-
}
|
|
20503
|
-
}
|
|
20504
|
-
if (createNextWatcher) {
|
|
20505
|
-
activeWatchers.set(projectRoot, createNextWatcher());
|
|
20506
|
-
}
|
|
20507
|
-
});
|
|
20508
|
-
watcherReplacementChains.set(projectRoot, chain);
|
|
20509
|
-
try {
|
|
20510
|
-
await chain;
|
|
20511
|
-
} finally {
|
|
20512
|
-
if (watcherReplacementChains.get(projectRoot) === chain) {
|
|
20513
|
-
watcherReplacementChains.delete(projectRoot);
|
|
20514
|
-
}
|
|
20515
|
-
}
|
|
20516
|
-
}
|
|
20517
21506
|
function getCommandsDir() {
|
|
20518
21507
|
let currentDir = process.cwd();
|
|
20519
21508
|
if (typeof import.meta !== "undefined" && import.meta.url) {
|
|
20520
|
-
currentDir =
|
|
21509
|
+
currentDir = path30.dirname(fileURLToPath2(import.meta.url));
|
|
20521
21510
|
}
|
|
20522
|
-
const packageRoot =
|
|
20523
|
-
return
|
|
21511
|
+
const packageRoot = path30.basename(currentDir) === "adapters" ? path30.join(currentDir, "..", "..") : path30.join(currentDir, "..");
|
|
21512
|
+
return path30.join(packageRoot, "commands");
|
|
20524
21513
|
}
|
|
20525
21514
|
function appendRoutingHints(output, hints, preferredRole) {
|
|
20526
21515
|
const preferredBucket = preferredRole === "developer" ? output.developer : output.system;
|
|
@@ -20546,8 +21535,9 @@ var plugin = async ({ directory, worktree }) => {
|
|
|
20546
21535
|
initializeTools2(projectRoot, config);
|
|
20547
21536
|
const getProjectIndexer = () => getIndexerForProject2(projectRoot);
|
|
20548
21537
|
const routingHints = config.search.routingHints ? new RoutingHintController(() => getProjectIndexer().getStatus(), 200, config.search.routingGraphHandoffHints) : null;
|
|
20549
|
-
const
|
|
20550
|
-
const
|
|
21538
|
+
const projectSafety = getProjectSafety(projectRoot, config);
|
|
21539
|
+
const isHomeDir = projectSafety.blockedReason === "home-directory";
|
|
21540
|
+
const isValidProject = projectSafety.safeToRun;
|
|
20551
21541
|
if (isHomeDir) {
|
|
20552
21542
|
console.warn(
|
|
20553
21543
|
`[codebase-index] Refusing to watch or index home directory "${projectRoot}". Open a specific project directory instead.`
|
|
@@ -20557,16 +21547,24 @@ var plugin = async ({ directory, worktree }) => {
|
|
|
20557
21547
|
`[codebase-index] Skipping file watching and auto-indexing: no project marker found in "${projectRoot}". Set "indexing.requireProjectMarker": false in config to override.`
|
|
20558
21548
|
);
|
|
20559
21549
|
}
|
|
20560
|
-
if (
|
|
20561
|
-
|
|
20562
|
-
|
|
20563
|
-
|
|
20564
|
-
await replaceActiveWatcher(
|
|
20565
|
-
projectRoot,
|
|
20566
|
-
() => createWatcherWithIndexer(getProjectIndexer, projectRoot, config, "opencode")
|
|
20567
|
-
);
|
|
21550
|
+
if (!isValidProject) {
|
|
21551
|
+
await stopBackgroundWorker(projectRoot, "opencode").catch((error) => {
|
|
21552
|
+
console.error("[codebase-index] Failed to stop unsafe OpenCode background worker:", error);
|
|
21553
|
+
});
|
|
20568
21554
|
} else {
|
|
20569
|
-
|
|
21555
|
+
const watcherFactoryForConfig = (refreshedConfig) => refreshedConfig.indexing.watchFiles ? () => createWatcherWithIndexer(getProjectIndexer, projectRoot, refreshedConfig, "opencode") : null;
|
|
21556
|
+
configureBackgroundWorker(projectRoot, "opencode", config, {
|
|
21557
|
+
startAutoIndex: (source, allowDisabledAutoIndex) => {
|
|
21558
|
+
startAutoIndexForBackgroundWorker(projectRoot, "opencode", source, allowDisabledAutoIndex);
|
|
21559
|
+
},
|
|
21560
|
+
stopAutoIndex: () => stopAutoIndexForBackgroundWorker(projectRoot, "opencode"),
|
|
21561
|
+
watcherFactory: watcherFactoryForConfig(config),
|
|
21562
|
+
watcherFactoryForConfig,
|
|
21563
|
+
replaceWatcher: true
|
|
21564
|
+
}, {
|
|
21565
|
+
restartAutoIndex: true
|
|
21566
|
+
});
|
|
21567
|
+
await waitForBackgroundWorkerStart(projectRoot, "opencode");
|
|
20570
21568
|
}
|
|
20571
21569
|
return {
|
|
20572
21570
|
tool: {
|