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/pi-extension.cjs
CHANGED
|
@@ -333,7 +333,7 @@ var require_ignore = __commonJS({
|
|
|
333
333
|
// path matching.
|
|
334
334
|
// - check `string` either `MODE_IGNORE` or `MODE_CHECK_IGNORE`
|
|
335
335
|
// @returns {TestResult} true if a file is ignored
|
|
336
|
-
test(
|
|
336
|
+
test(path26, checkUnignored, mode) {
|
|
337
337
|
let ignored = false;
|
|
338
338
|
let unignored = false;
|
|
339
339
|
let matchedRule;
|
|
@@ -342,7 +342,7 @@ var require_ignore = __commonJS({
|
|
|
342
342
|
if (unignored === negative && ignored !== unignored || negative && !ignored && !unignored && !checkUnignored) {
|
|
343
343
|
return;
|
|
344
344
|
}
|
|
345
|
-
const matched = rule[mode].test(
|
|
345
|
+
const matched = rule[mode].test(path26);
|
|
346
346
|
if (!matched) {
|
|
347
347
|
return;
|
|
348
348
|
}
|
|
@@ -363,17 +363,17 @@ var require_ignore = __commonJS({
|
|
|
363
363
|
var throwError = (message, Ctor) => {
|
|
364
364
|
throw new Ctor(message);
|
|
365
365
|
};
|
|
366
|
-
var checkPath = (
|
|
367
|
-
if (!isString(
|
|
366
|
+
var checkPath = (path26, originalPath, doThrow) => {
|
|
367
|
+
if (!isString(path26)) {
|
|
368
368
|
return doThrow(
|
|
369
369
|
`path must be a string, but got \`${originalPath}\``,
|
|
370
370
|
TypeError
|
|
371
371
|
);
|
|
372
372
|
}
|
|
373
|
-
if (!
|
|
373
|
+
if (!path26) {
|
|
374
374
|
return doThrow(`path must not be empty`, TypeError);
|
|
375
375
|
}
|
|
376
|
-
if (checkPath.isNotRelative(
|
|
376
|
+
if (checkPath.isNotRelative(path26)) {
|
|
377
377
|
const r = "`path.relative()`d";
|
|
378
378
|
return doThrow(
|
|
379
379
|
`path should be a ${r} string, but got "${originalPath}"`,
|
|
@@ -382,7 +382,7 @@ var require_ignore = __commonJS({
|
|
|
382
382
|
}
|
|
383
383
|
return true;
|
|
384
384
|
};
|
|
385
|
-
var isNotRelative = (
|
|
385
|
+
var isNotRelative = (path26) => REGEX_TEST_INVALID_PATH.test(path26);
|
|
386
386
|
checkPath.isNotRelative = isNotRelative;
|
|
387
387
|
checkPath.convert = (p) => p;
|
|
388
388
|
var Ignore2 = class {
|
|
@@ -412,19 +412,19 @@ var require_ignore = __commonJS({
|
|
|
412
412
|
}
|
|
413
413
|
// @returns {TestResult}
|
|
414
414
|
_test(originalPath, cache, checkUnignored, slices) {
|
|
415
|
-
const
|
|
415
|
+
const path26 = originalPath && checkPath.convert(originalPath);
|
|
416
416
|
checkPath(
|
|
417
|
-
|
|
417
|
+
path26,
|
|
418
418
|
originalPath,
|
|
419
419
|
this._strictPathCheck ? throwError : RETURN_FALSE
|
|
420
420
|
);
|
|
421
|
-
return this._t(
|
|
421
|
+
return this._t(path26, cache, checkUnignored, slices);
|
|
422
422
|
}
|
|
423
|
-
checkIgnore(
|
|
424
|
-
if (!REGEX_TEST_TRAILING_SLASH.test(
|
|
425
|
-
return this.test(
|
|
423
|
+
checkIgnore(path26) {
|
|
424
|
+
if (!REGEX_TEST_TRAILING_SLASH.test(path26)) {
|
|
425
|
+
return this.test(path26);
|
|
426
426
|
}
|
|
427
|
-
const slices =
|
|
427
|
+
const slices = path26.split(SLASH2).filter(Boolean);
|
|
428
428
|
slices.pop();
|
|
429
429
|
if (slices.length) {
|
|
430
430
|
const parent = this._t(
|
|
@@ -437,18 +437,18 @@ var require_ignore = __commonJS({
|
|
|
437
437
|
return parent;
|
|
438
438
|
}
|
|
439
439
|
}
|
|
440
|
-
return this._rules.test(
|
|
440
|
+
return this._rules.test(path26, false, MODE_CHECK_IGNORE);
|
|
441
441
|
}
|
|
442
|
-
_t(
|
|
443
|
-
if (
|
|
444
|
-
return cache[
|
|
442
|
+
_t(path26, cache, checkUnignored, slices) {
|
|
443
|
+
if (path26 in cache) {
|
|
444
|
+
return cache[path26];
|
|
445
445
|
}
|
|
446
446
|
if (!slices) {
|
|
447
|
-
slices =
|
|
447
|
+
slices = path26.split(SLASH2).filter(Boolean);
|
|
448
448
|
}
|
|
449
449
|
slices.pop();
|
|
450
450
|
if (!slices.length) {
|
|
451
|
-
return cache[
|
|
451
|
+
return cache[path26] = this._rules.test(path26, checkUnignored, MODE_IGNORE);
|
|
452
452
|
}
|
|
453
453
|
const parent = this._t(
|
|
454
454
|
slices.join(SLASH2) + SLASH2,
|
|
@@ -456,29 +456,29 @@ var require_ignore = __commonJS({
|
|
|
456
456
|
checkUnignored,
|
|
457
457
|
slices
|
|
458
458
|
);
|
|
459
|
-
return cache[
|
|
459
|
+
return cache[path26] = parent.ignored ? parent : this._rules.test(path26, checkUnignored, MODE_IGNORE);
|
|
460
460
|
}
|
|
461
|
-
ignores(
|
|
462
|
-
return this._test(
|
|
461
|
+
ignores(path26) {
|
|
462
|
+
return this._test(path26, this._ignoreCache, false).ignored;
|
|
463
463
|
}
|
|
464
464
|
createFilter() {
|
|
465
|
-
return (
|
|
465
|
+
return (path26) => !this.ignores(path26);
|
|
466
466
|
}
|
|
467
467
|
filter(paths) {
|
|
468
468
|
return makeArray(paths).filter(this.createFilter());
|
|
469
469
|
}
|
|
470
470
|
// @returns {TestResult}
|
|
471
|
-
test(
|
|
472
|
-
return this._test(
|
|
471
|
+
test(path26) {
|
|
472
|
+
return this._test(path26, this._testCache, true);
|
|
473
473
|
}
|
|
474
474
|
};
|
|
475
475
|
var factory = (options) => new Ignore2(options);
|
|
476
|
-
var isPathValid = (
|
|
476
|
+
var isPathValid = (path26) => checkPath(path26 && checkPath.convert(path26), path26, RETURN_FALSE);
|
|
477
477
|
var setupWindows = () => {
|
|
478
478
|
const makePosix = (str) => /^\\\\\?\\/.test(str) || /["<>|\u0000-\u001F]+/u.test(str) ? str : str.replace(/\\/g, "/");
|
|
479
479
|
checkPath.convert = makePosix;
|
|
480
480
|
const REGEX_TEST_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i;
|
|
481
|
-
checkPath.isNotRelative = (
|
|
481
|
+
checkPath.isNotRelative = (path26) => REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path26) || isNotRelative(path26);
|
|
482
482
|
};
|
|
483
483
|
if (
|
|
484
484
|
// Detect `process` so that it can run in browsers.
|
|
@@ -2254,7 +2254,7 @@ function formatCodeCommunities(result) {
|
|
|
2254
2254
|
|
|
2255
2255
|
// src/tools/operations.ts
|
|
2256
2256
|
var import_fs13 = require("fs");
|
|
2257
|
-
var
|
|
2257
|
+
var path21 = __toESM(require("path"), 1);
|
|
2258
2258
|
|
|
2259
2259
|
// src/tools/knowledge-base-paths.ts
|
|
2260
2260
|
var path9 = __toESM(require("path"), 1);
|
|
@@ -2966,8 +2966,8 @@ function formatExactSearchHandoff(results) {
|
|
|
2966
2966
|
}
|
|
2967
2967
|
function formatContextEvidence(result, index) {
|
|
2968
2968
|
const symbol = result.name ? ` ${JSON.stringify(compactEvidenceValue(result.name, 80))}` : "";
|
|
2969
|
-
const
|
|
2970
|
-
return `[${index}] ${result.chunkType}${symbol} in ${
|
|
2969
|
+
const path26 = compactEvidenceValue(result.filePath, 120);
|
|
2970
|
+
return `[${index}] ${result.chunkType}${symbol} in ${path26}:${result.startLine}-${result.endLine} (score ${result.score.toFixed(2)})`;
|
|
2971
2971
|
}
|
|
2972
2972
|
function formatContextPack(heading, selected, candidateCount, duplicateCount, limitOmittedCount, budgetOmittedCount, includeExactSearchHandoff) {
|
|
2973
2973
|
const lines = selected.map((result, index) => formatContextEvidence(result, index + 1));
|
|
@@ -3610,8 +3610,8 @@ function formatEffectivenessMetrics(snapshot) {
|
|
|
3610
3610
|
|
|
3611
3611
|
// src/utils/auto-index.ts
|
|
3612
3612
|
var import_fs8 = require("fs");
|
|
3613
|
-
var
|
|
3614
|
-
var
|
|
3613
|
+
var os5 = __toESM(require("os"), 1);
|
|
3614
|
+
var path13 = __toESM(require("path"), 1);
|
|
3615
3615
|
|
|
3616
3616
|
// src/indexer/index-lock.ts
|
|
3617
3617
|
var import_crypto = require("crypto");
|
|
@@ -3858,7 +3858,7 @@ function removeDeadReclaimMarker(lockPath, expectedOwner) {
|
|
|
3858
3858
|
return true;
|
|
3859
3859
|
}
|
|
3860
3860
|
function reclaimDeadOwner(indexPath, lockPath, expectedOwner) {
|
|
3861
|
-
const
|
|
3861
|
+
const reclaimPath2 = path10.join(lockPath, RECLAIM_DIRECTORY_NAME);
|
|
3862
3862
|
const reclaimOwner = {
|
|
3863
3863
|
pid: process.pid,
|
|
3864
3864
|
hostname: os3.hostname(),
|
|
@@ -3867,19 +3867,19 @@ function reclaimDeadOwner(indexPath, lockPath, expectedOwner) {
|
|
|
3867
3867
|
expectedOwnerToken: expectedOwner.token
|
|
3868
3868
|
};
|
|
3869
3869
|
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
3870
|
-
if (publishJsonDirectory(
|
|
3870
|
+
if (publishJsonDirectory(reclaimPath2, reclaimOwner)) break;
|
|
3871
3871
|
if (attempt === 0 && removeDeadReclaimMarker(lockPath, expectedOwner)) continue;
|
|
3872
3872
|
return false;
|
|
3873
3873
|
}
|
|
3874
3874
|
try {
|
|
3875
|
-
const currentReclaimer = readReclaimOwner(
|
|
3875
|
+
const currentReclaimer = readReclaimOwner(reclaimPath2);
|
|
3876
3876
|
const currentOwner = readDirectoryOwner(lockPath);
|
|
3877
3877
|
if (!currentReclaimer || !sameReclaimOwner(currentReclaimer, reclaimOwner) || !currentOwner || !sameOwner(currentOwner, expectedOwner) || getOwnerLiveness(currentOwner) !== "dead") {
|
|
3878
3878
|
return false;
|
|
3879
3879
|
}
|
|
3880
3880
|
publishRecoveryMarker(indexPath, expectedOwner);
|
|
3881
3881
|
const ownerBeforeQuarantine = readDirectoryOwner(lockPath);
|
|
3882
|
-
const reclaimerBeforeQuarantine = readReclaimOwner(
|
|
3882
|
+
const reclaimerBeforeQuarantine = readReclaimOwner(reclaimPath2);
|
|
3883
3883
|
if (!ownerBeforeQuarantine || !sameOwner(ownerBeforeQuarantine, expectedOwner) || getOwnerLiveness(ownerBeforeQuarantine) !== "dead" || !reclaimerBeforeQuarantine || !sameReclaimOwner(reclaimerBeforeQuarantine, reclaimOwner)) {
|
|
3884
3884
|
return false;
|
|
3885
3885
|
}
|
|
@@ -4049,10 +4049,884 @@ function completeLeaseRecovery(lease) {
|
|
|
4049
4049
|
}
|
|
4050
4050
|
}
|
|
4051
4051
|
|
|
4052
|
+
// src/utils/background-worker.ts
|
|
4053
|
+
var import_node_crypto = require("crypto");
|
|
4054
|
+
var import_node_fs = require("fs");
|
|
4055
|
+
var os4 = __toESM(require("os"), 1);
|
|
4056
|
+
var path11 = __toESM(require("path"), 1);
|
|
4057
|
+
var OWNER_FILE_NAME2 = "owner.json";
|
|
4058
|
+
var HEARTBEAT_FILE_PREFIX = "heartbeat.";
|
|
4059
|
+
var RECLAIM_DIRECTORY_NAME2 = "reclaim";
|
|
4060
|
+
var REFRESH_REQUEST_FILE_NAME = "refresh-request.json";
|
|
4061
|
+
var HEARTBEAT_INTERVAL_MS = 5e3;
|
|
4062
|
+
var STALE_LEASE_MS = 3e4;
|
|
4063
|
+
var RETRY_DELAY_MS = 5e3;
|
|
4064
|
+
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;
|
|
4065
|
+
var BackgroundWorkerStopError = class extends Error {
|
|
4066
|
+
constructor(watcherError, autoIndexError) {
|
|
4067
|
+
super("Failed to stop background worker");
|
|
4068
|
+
this.watcherError = watcherError;
|
|
4069
|
+
this.autoIndexError = autoIndexError;
|
|
4070
|
+
this.name = "BackgroundWorkerStopError";
|
|
4071
|
+
}
|
|
4072
|
+
watcherError;
|
|
4073
|
+
autoIndexError;
|
|
4074
|
+
};
|
|
4075
|
+
var workers = /* @__PURE__ */ new Map();
|
|
4076
|
+
var workerKeysByProject = /* @__PURE__ */ new Map();
|
|
4077
|
+
var workerReplacementBarriers = /* @__PURE__ */ new Map();
|
|
4078
|
+
function getErrorCode2(error) {
|
|
4079
|
+
return typeof error === "object" && error !== null && "code" in error ? String(error.code) : void 0;
|
|
4080
|
+
}
|
|
4081
|
+
function canonicalizePath(targetPath) {
|
|
4082
|
+
const resolved = path11.resolve(targetPath);
|
|
4083
|
+
if ((0, import_node_fs.existsSync)(resolved)) {
|
|
4084
|
+
try {
|
|
4085
|
+
return import_node_fs.realpathSync.native(resolved);
|
|
4086
|
+
} catch {
|
|
4087
|
+
return resolved;
|
|
4088
|
+
}
|
|
4089
|
+
}
|
|
4090
|
+
const parent = path11.dirname(resolved);
|
|
4091
|
+
if (parent === resolved) return resolved;
|
|
4092
|
+
return path11.join(canonicalizePath(parent), path11.basename(resolved));
|
|
4093
|
+
}
|
|
4094
|
+
function projectLookupKey(projectRoot3, host) {
|
|
4095
|
+
return `${host}::${canonicalizePath(projectRoot3)}`;
|
|
4096
|
+
}
|
|
4097
|
+
function resolveIdentity(projectRoot3, config, host) {
|
|
4098
|
+
const canonicalProjectRoot = canonicalizePath(projectRoot3);
|
|
4099
|
+
const canonicalIndexPath = canonicalizePath(resolveProjectIndexPath(projectRoot3, config.scope, host));
|
|
4100
|
+
return {
|
|
4101
|
+
canonicalIndexPath,
|
|
4102
|
+
canonicalProjectRoot,
|
|
4103
|
+
key: `${canonicalIndexPath}::${canonicalProjectRoot}`
|
|
4104
|
+
};
|
|
4105
|
+
}
|
|
4106
|
+
function controllerKey(identity, host) {
|
|
4107
|
+
return `${identity.key}::${host}`;
|
|
4108
|
+
}
|
|
4109
|
+
function leaseDirectoryName(identity) {
|
|
4110
|
+
const hash = (0, import_node_crypto.createHash)("sha256").update(identity.key).digest("hex").slice(0, 32);
|
|
4111
|
+
return `background-worker.${hash}.lease`;
|
|
4112
|
+
}
|
|
4113
|
+
function leasePathFor(identity) {
|
|
4114
|
+
return path11.join(identity.canonicalIndexPath, leaseDirectoryName(identity));
|
|
4115
|
+
}
|
|
4116
|
+
function parseOwner2(value) {
|
|
4117
|
+
if (typeof value !== "object" || value === null) return null;
|
|
4118
|
+
const candidate = value;
|
|
4119
|
+
if (candidate.version !== 1) return null;
|
|
4120
|
+
if (!Number.isInteger(candidate.pid) || (candidate.pid ?? 0) <= 0) return null;
|
|
4121
|
+
if (typeof candidate.hostname !== "string" || candidate.hostname.length === 0) return null;
|
|
4122
|
+
if (typeof candidate.startedAt !== "string" || Number.isNaN(Date.parse(candidate.startedAt))) return null;
|
|
4123
|
+
if (typeof candidate.heartbeatAt !== "string" || Number.isNaN(Date.parse(candidate.heartbeatAt))) return null;
|
|
4124
|
+
if (typeof candidate.projectRoot !== "string" || candidate.projectRoot.length === 0) return null;
|
|
4125
|
+
if (typeof candidate.indexPath !== "string" || candidate.indexPath.length === 0) return null;
|
|
4126
|
+
if (typeof candidate.token !== "string" || !UUID_PATTERN2.test(candidate.token)) return null;
|
|
4127
|
+
return candidate;
|
|
4128
|
+
}
|
|
4129
|
+
function parseHeartbeat(value, expectedToken) {
|
|
4130
|
+
if (typeof value !== "object" || value === null) return null;
|
|
4131
|
+
const candidate = value;
|
|
4132
|
+
if (candidate.version !== 1 || candidate.token !== expectedToken) return null;
|
|
4133
|
+
if (typeof candidate.heartbeatAt !== "string" || Number.isNaN(Date.parse(candidate.heartbeatAt))) return null;
|
|
4134
|
+
return candidate;
|
|
4135
|
+
}
|
|
4136
|
+
function parseReclaimOwner2(value) {
|
|
4137
|
+
if (typeof value !== "object" || value === null) return null;
|
|
4138
|
+
const candidate = value;
|
|
4139
|
+
if (candidate.version !== 1) return null;
|
|
4140
|
+
if (!Number.isInteger(candidate.pid) || (candidate.pid ?? 0) <= 0) return null;
|
|
4141
|
+
if (typeof candidate.hostname !== "string" || candidate.hostname.length === 0) return null;
|
|
4142
|
+
if (typeof candidate.startedAt !== "string" || Number.isNaN(Date.parse(candidate.startedAt))) return null;
|
|
4143
|
+
if (typeof candidate.token !== "string" || !UUID_PATTERN2.test(candidate.token)) return null;
|
|
4144
|
+
if (candidate.expectedOwnerToken !== null && (typeof candidate.expectedOwnerToken !== "string" || !UUID_PATTERN2.test(candidate.expectedOwnerToken))) return null;
|
|
4145
|
+
return candidate;
|
|
4146
|
+
}
|
|
4147
|
+
function heartbeatPath(leasePath, token) {
|
|
4148
|
+
return path11.join(leasePath, `${HEARTBEAT_FILE_PREFIX}${token}.json`);
|
|
4149
|
+
}
|
|
4150
|
+
function reclaimPath(leasePath) {
|
|
4151
|
+
return path11.join(leasePath, RECLAIM_DIRECTORY_NAME2);
|
|
4152
|
+
}
|
|
4153
|
+
function refreshRequestPath(leasePath) {
|
|
4154
|
+
return path11.join(leasePath, REFRESH_REQUEST_FILE_NAME);
|
|
4155
|
+
}
|
|
4156
|
+
function readLeaseOwner(leasePath) {
|
|
4157
|
+
try {
|
|
4158
|
+
return parseOwner2(JSON.parse((0, import_node_fs.readFileSync)(path11.join(leasePath, OWNER_FILE_NAME2), "utf-8")));
|
|
4159
|
+
} catch {
|
|
4160
|
+
return null;
|
|
4161
|
+
}
|
|
4162
|
+
}
|
|
4163
|
+
function readOwner(leasePath) {
|
|
4164
|
+
const owner = readLeaseOwner(leasePath);
|
|
4165
|
+
if (!owner) return null;
|
|
4166
|
+
try {
|
|
4167
|
+
const heartbeat = parseHeartbeat(
|
|
4168
|
+
JSON.parse((0, import_node_fs.readFileSync)(heartbeatPath(leasePath, owner.token), "utf-8")),
|
|
4169
|
+
owner.token
|
|
4170
|
+
);
|
|
4171
|
+
return heartbeat ? { ...owner, heartbeatAt: heartbeat.heartbeatAt } : owner;
|
|
4172
|
+
} catch {
|
|
4173
|
+
return owner;
|
|
4174
|
+
}
|
|
4175
|
+
}
|
|
4176
|
+
function readReclaimOwner2(leasePath) {
|
|
4177
|
+
try {
|
|
4178
|
+
return parseReclaimOwner2(JSON.parse((0, import_node_fs.readFileSync)(path11.join(reclaimPath(leasePath), OWNER_FILE_NAME2), "utf-8")));
|
|
4179
|
+
} catch {
|
|
4180
|
+
return null;
|
|
4181
|
+
}
|
|
4182
|
+
}
|
|
4183
|
+
function ownerLiveness(owner) {
|
|
4184
|
+
if (owner.hostname !== os4.hostname()) return "unknown";
|
|
4185
|
+
try {
|
|
4186
|
+
process.kill(owner.pid, 0);
|
|
4187
|
+
return "alive";
|
|
4188
|
+
} catch (error) {
|
|
4189
|
+
const code = getErrorCode2(error);
|
|
4190
|
+
if (code === "ESRCH") return "dead";
|
|
4191
|
+
if (code === "EPERM") return "alive";
|
|
4192
|
+
return "unknown";
|
|
4193
|
+
}
|
|
4194
|
+
}
|
|
4195
|
+
function isHeartbeatExpired(owner) {
|
|
4196
|
+
return Date.now() - Date.parse(owner.heartbeatAt) >= STALE_LEASE_MS;
|
|
4197
|
+
}
|
|
4198
|
+
function sameOwner2(left, right) {
|
|
4199
|
+
return left.pid === right.pid && left.hostname === right.hostname && left.token === right.token;
|
|
4200
|
+
}
|
|
4201
|
+
function writeHeartbeat(leasePath, owner) {
|
|
4202
|
+
const targetPath = heartbeatPath(leasePath, owner.token);
|
|
4203
|
+
const temporaryPath = `${targetPath}.tmp.${process.pid}.${owner.token}.${(0, import_node_crypto.randomUUID)()}`;
|
|
4204
|
+
const heartbeat = {
|
|
4205
|
+
version: 1,
|
|
4206
|
+
token: owner.token,
|
|
4207
|
+
heartbeatAt: owner.heartbeatAt
|
|
4208
|
+
};
|
|
4209
|
+
try {
|
|
4210
|
+
(0, import_node_fs.writeFileSync)(temporaryPath, JSON.stringify(heartbeat), {
|
|
4211
|
+
encoding: "utf-8",
|
|
4212
|
+
flag: "wx",
|
|
4213
|
+
mode: 384
|
|
4214
|
+
});
|
|
4215
|
+
(0, import_node_fs.renameSync)(temporaryPath, targetPath);
|
|
4216
|
+
const currentOwner = readLeaseOwner(leasePath);
|
|
4217
|
+
return currentOwner !== null && sameOwner2(currentOwner, owner);
|
|
4218
|
+
} finally {
|
|
4219
|
+
if ((0, import_node_fs.existsSync)(temporaryPath)) (0, import_node_fs.rmSync)(temporaryPath, { force: true });
|
|
4220
|
+
}
|
|
4221
|
+
}
|
|
4222
|
+
function requestRefreshFromLeader(leasePath, allowDisabledAutoIndex) {
|
|
4223
|
+
const requestPath = refreshRequestPath(leasePath);
|
|
4224
|
+
const temporaryPath = `${requestPath}.tmp.${process.pid}.${(0, import_node_crypto.randomUUID)()}`;
|
|
4225
|
+
try {
|
|
4226
|
+
const request = {
|
|
4227
|
+
allowDisabledAutoIndex,
|
|
4228
|
+
requestedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4229
|
+
version: 1
|
|
4230
|
+
};
|
|
4231
|
+
(0, import_node_fs.writeFileSync)(temporaryPath, JSON.stringify(request), {
|
|
4232
|
+
encoding: "utf-8",
|
|
4233
|
+
flag: "wx",
|
|
4234
|
+
mode: 384
|
|
4235
|
+
});
|
|
4236
|
+
(0, import_node_fs.renameSync)(temporaryPath, requestPath);
|
|
4237
|
+
} catch (error) {
|
|
4238
|
+
if (getErrorCode2(error) !== "ENOENT") {
|
|
4239
|
+
console.error("[codebase-index] Failed to request background index refresh from the project worker:", error);
|
|
4240
|
+
}
|
|
4241
|
+
} finally {
|
|
4242
|
+
if ((0, import_node_fs.existsSync)(temporaryPath)) (0, import_node_fs.rmSync)(temporaryPath, { force: true });
|
|
4243
|
+
}
|
|
4244
|
+
}
|
|
4245
|
+
function consumeRefreshRequest(leasePath) {
|
|
4246
|
+
const requestPath = refreshRequestPath(leasePath);
|
|
4247
|
+
const claimedPath = `${requestPath}.handling.${process.pid}.${(0, import_node_crypto.randomUUID)()}`;
|
|
4248
|
+
try {
|
|
4249
|
+
(0, import_node_fs.renameSync)(requestPath, claimedPath);
|
|
4250
|
+
} catch (error) {
|
|
4251
|
+
if (getErrorCode2(error) === "ENOENT") return null;
|
|
4252
|
+
throw error;
|
|
4253
|
+
}
|
|
4254
|
+
try {
|
|
4255
|
+
const value = JSON.parse((0, import_node_fs.readFileSync)(claimedPath, "utf-8"));
|
|
4256
|
+
return {
|
|
4257
|
+
allowDisabledAutoIndex: value.version === 1 && value.allowDisabledAutoIndex === true,
|
|
4258
|
+
requestedAt: typeof value.requestedAt === "string" ? value.requestedAt : (/* @__PURE__ */ new Date()).toISOString(),
|
|
4259
|
+
version: 1
|
|
4260
|
+
};
|
|
4261
|
+
} catch {
|
|
4262
|
+
return { allowDisabledAutoIndex: false, requestedAt: (/* @__PURE__ */ new Date()).toISOString(), version: 1 };
|
|
4263
|
+
} finally {
|
|
4264
|
+
(0, import_node_fs.rmSync)(claimedPath, { force: true });
|
|
4265
|
+
}
|
|
4266
|
+
}
|
|
4267
|
+
function publishLease(leasePath, owner) {
|
|
4268
|
+
const candidatePath = `${leasePath}.candidate.${process.pid}.${owner.token}`;
|
|
4269
|
+
try {
|
|
4270
|
+
(0, import_node_fs.mkdirSync)(candidatePath, { mode: 448 });
|
|
4271
|
+
} catch (error) {
|
|
4272
|
+
if (getErrorCode2(error) === "ENOENT") return false;
|
|
4273
|
+
throw error;
|
|
4274
|
+
}
|
|
4275
|
+
try {
|
|
4276
|
+
(0, import_node_fs.writeFileSync)(path11.join(candidatePath, OWNER_FILE_NAME2), JSON.stringify(owner), {
|
|
4277
|
+
encoding: "utf-8",
|
|
4278
|
+
flag: "wx",
|
|
4279
|
+
mode: 384
|
|
4280
|
+
});
|
|
4281
|
+
if ((0, import_node_fs.existsSync)(leasePath)) return false;
|
|
4282
|
+
try {
|
|
4283
|
+
(0, import_node_fs.renameSync)(candidatePath, leasePath);
|
|
4284
|
+
return true;
|
|
4285
|
+
} catch (error) {
|
|
4286
|
+
if ((0, import_node_fs.existsSync)(leasePath) || getErrorCode2(error) === "ENOENT") return false;
|
|
4287
|
+
throw error;
|
|
4288
|
+
}
|
|
4289
|
+
} finally {
|
|
4290
|
+
if ((0, import_node_fs.existsSync)(candidatePath)) (0, import_node_fs.rmSync)(candidatePath, { recursive: true, force: true });
|
|
4291
|
+
}
|
|
4292
|
+
}
|
|
4293
|
+
function sameReclaimOwner2(left, right) {
|
|
4294
|
+
return left.pid === right.pid && left.hostname === right.hostname && left.token === right.token && left.expectedOwnerToken === right.expectedOwnerToken;
|
|
4295
|
+
}
|
|
4296
|
+
function reclaimerLiveness(owner) {
|
|
4297
|
+
return ownerLiveness(owner);
|
|
4298
|
+
}
|
|
4299
|
+
function isReclaimMarkerExpired(leasePath, owner) {
|
|
4300
|
+
const startedAt = owner ? Date.parse(owner.startedAt) : (() => {
|
|
4301
|
+
try {
|
|
4302
|
+
return (0, import_node_fs.lstatSync)(reclaimPath(leasePath)).mtimeMs;
|
|
4303
|
+
} catch {
|
|
4304
|
+
return Date.now();
|
|
4305
|
+
}
|
|
4306
|
+
})();
|
|
4307
|
+
return Date.now() - startedAt >= STALE_LEASE_MS;
|
|
4308
|
+
}
|
|
4309
|
+
function hasActiveReclaimMarker(leasePath, owner) {
|
|
4310
|
+
const marker = readReclaimOwner2(leasePath);
|
|
4311
|
+
return marker !== null && marker.expectedOwnerToken === owner.token && (marker.hostname !== os4.hostname() || ownerLiveness(owner) !== "alive");
|
|
4312
|
+
}
|
|
4313
|
+
function publishReclaimMarker(leasePath, expectedOwner) {
|
|
4314
|
+
const markerPath = reclaimPath(leasePath);
|
|
4315
|
+
const owner = {
|
|
4316
|
+
version: 1,
|
|
4317
|
+
pid: process.pid,
|
|
4318
|
+
hostname: os4.hostname(),
|
|
4319
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4320
|
+
token: (0, import_node_crypto.randomUUID)(),
|
|
4321
|
+
expectedOwnerToken: expectedOwner?.token ?? null
|
|
4322
|
+
};
|
|
4323
|
+
try {
|
|
4324
|
+
(0, import_node_fs.mkdirSync)(markerPath, { mode: 448 });
|
|
4325
|
+
} catch (error) {
|
|
4326
|
+
if (getErrorCode2(error) === "EEXIST" || getErrorCode2(error) === "ENOENT") return null;
|
|
4327
|
+
throw error;
|
|
4328
|
+
}
|
|
4329
|
+
try {
|
|
4330
|
+
(0, import_node_fs.writeFileSync)(path11.join(markerPath, OWNER_FILE_NAME2), JSON.stringify(owner), {
|
|
4331
|
+
encoding: "utf-8",
|
|
4332
|
+
flag: "wx",
|
|
4333
|
+
mode: 384
|
|
4334
|
+
});
|
|
4335
|
+
return owner;
|
|
4336
|
+
} catch (error) {
|
|
4337
|
+
(0, import_node_fs.rmSync)(markerPath, { recursive: true, force: true });
|
|
4338
|
+
throw error;
|
|
4339
|
+
}
|
|
4340
|
+
}
|
|
4341
|
+
function removeExpiredReclaimMarker(leasePath, expectedOwner) {
|
|
4342
|
+
const marker = readReclaimOwner2(leasePath);
|
|
4343
|
+
const markerPath = reclaimPath(leasePath);
|
|
4344
|
+
if (!(0, import_node_fs.existsSync)(markerPath)) return false;
|
|
4345
|
+
if (marker && marker.expectedOwnerToken !== (expectedOwner?.token ?? null)) return false;
|
|
4346
|
+
if (marker && (reclaimerLiveness(marker) === "alive" || !isReclaimMarkerExpired(leasePath, marker))) return false;
|
|
4347
|
+
if (!marker && !isReclaimMarkerExpired(leasePath, null)) return false;
|
|
4348
|
+
const staleMarkerPath = `${markerPath}.stale.${marker?.pid ?? process.pid}.${marker?.token ?? (0, import_node_crypto.randomUUID)()}.${(0, import_node_crypto.randomUUID)()}`;
|
|
4349
|
+
try {
|
|
4350
|
+
(0, import_node_fs.renameSync)(markerPath, staleMarkerPath);
|
|
4351
|
+
} catch (error) {
|
|
4352
|
+
if (getErrorCode2(error) === "ENOENT") return false;
|
|
4353
|
+
throw error;
|
|
4354
|
+
}
|
|
4355
|
+
try {
|
|
4356
|
+
let claimedMarker = null;
|
|
4357
|
+
try {
|
|
4358
|
+
claimedMarker = parseReclaimOwner2(
|
|
4359
|
+
JSON.parse((0, import_node_fs.readFileSync)(path11.join(staleMarkerPath, OWNER_FILE_NAME2), "utf-8"))
|
|
4360
|
+
);
|
|
4361
|
+
} catch {
|
|
4362
|
+
claimedMarker = null;
|
|
4363
|
+
}
|
|
4364
|
+
const markerMatches = marker ? claimedMarker !== null && sameReclaimOwner2(claimedMarker, marker) : claimedMarker === null;
|
|
4365
|
+
if (!markerMatches || !canReclaimLease(leasePath, expectedOwner)) {
|
|
4366
|
+
if (!(0, import_node_fs.existsSync)(markerPath) && (0, import_node_fs.existsSync)(staleMarkerPath)) (0, import_node_fs.renameSync)(staleMarkerPath, markerPath);
|
|
4367
|
+
return false;
|
|
4368
|
+
}
|
|
4369
|
+
(0, import_node_fs.rmSync)(staleMarkerPath, { recursive: true, force: true });
|
|
4370
|
+
return true;
|
|
4371
|
+
} catch (error) {
|
|
4372
|
+
if (getErrorCode2(error) === "ENOENT") return false;
|
|
4373
|
+
throw error;
|
|
4374
|
+
}
|
|
4375
|
+
}
|
|
4376
|
+
function canReclaimLease(leasePath, expectedOwner) {
|
|
4377
|
+
if (!(0, import_node_fs.existsSync)(leasePath)) return false;
|
|
4378
|
+
if (!expectedOwner) return false;
|
|
4379
|
+
const currentOwner = readOwner(leasePath);
|
|
4380
|
+
if (!currentOwner || !sameOwner2(currentOwner, expectedOwner)) return false;
|
|
4381
|
+
if (currentOwner.hostname === os4.hostname()) {
|
|
4382
|
+
return ownerLiveness(currentOwner) === "dead";
|
|
4383
|
+
}
|
|
4384
|
+
return isHeartbeatExpired(currentOwner);
|
|
4385
|
+
}
|
|
4386
|
+
function reclaimLease(leasePath, expectedOwner) {
|
|
4387
|
+
let marker = null;
|
|
4388
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
4389
|
+
marker = publishReclaimMarker(leasePath, expectedOwner);
|
|
4390
|
+
if (marker) break;
|
|
4391
|
+
if (attempt === 0 && removeExpiredReclaimMarker(leasePath, expectedOwner)) continue;
|
|
4392
|
+
return false;
|
|
4393
|
+
}
|
|
4394
|
+
if (!marker) return false;
|
|
4395
|
+
const markerPath = reclaimPath(leasePath);
|
|
4396
|
+
try {
|
|
4397
|
+
const currentMarker = readReclaimOwner2(leasePath);
|
|
4398
|
+
if (!currentMarker || !sameReclaimOwner2(currentMarker, marker) || !canReclaimLease(leasePath, expectedOwner)) {
|
|
4399
|
+
return false;
|
|
4400
|
+
}
|
|
4401
|
+
const stalePath = `${leasePath}.stale.${process.pid}.${marker.token}`;
|
|
4402
|
+
(0, import_node_fs.renameSync)(leasePath, stalePath);
|
|
4403
|
+
const quarantinedOwner = readOwner(stalePath);
|
|
4404
|
+
const quarantinedMarker = readReclaimOwner2(stalePath);
|
|
4405
|
+
if (!quarantinedMarker || !sameReclaimOwner2(quarantinedMarker, marker) || expectedOwner !== null && (!quarantinedOwner || !sameOwner2(quarantinedOwner, expectedOwner))) {
|
|
4406
|
+
if (!(0, import_node_fs.existsSync)(leasePath) && (0, import_node_fs.existsSync)(stalePath)) (0, import_node_fs.renameSync)(stalePath, leasePath);
|
|
4407
|
+
return false;
|
|
4408
|
+
}
|
|
4409
|
+
(0, import_node_fs.rmSync)(stalePath, { recursive: true, force: true });
|
|
4410
|
+
return true;
|
|
4411
|
+
} catch (error) {
|
|
4412
|
+
if (getErrorCode2(error) === "ENOENT") return false;
|
|
4413
|
+
throw error;
|
|
4414
|
+
} finally {
|
|
4415
|
+
const currentMarker = readReclaimOwner2(leasePath);
|
|
4416
|
+
if (currentMarker && sameReclaimOwner2(currentMarker, marker)) {
|
|
4417
|
+
(0, import_node_fs.rmSync)(markerPath, { recursive: true, force: true });
|
|
4418
|
+
}
|
|
4419
|
+
}
|
|
4420
|
+
}
|
|
4421
|
+
function acquireLease(identity) {
|
|
4422
|
+
(0, import_node_fs.mkdirSync)(identity.canonicalIndexPath, { recursive: true, mode: 448 });
|
|
4423
|
+
const canonicalIndexPath = import_node_fs.realpathSync.native(identity.canonicalIndexPath);
|
|
4424
|
+
const leasePath = path11.join(canonicalIndexPath, leaseDirectoryName({ ...identity, canonicalIndexPath }));
|
|
4425
|
+
for (let attempt = 0; attempt < 4; attempt += 1) {
|
|
4426
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
4427
|
+
const owner = {
|
|
4428
|
+
version: 1,
|
|
4429
|
+
pid: process.pid,
|
|
4430
|
+
hostname: os4.hostname(),
|
|
4431
|
+
startedAt: timestamp,
|
|
4432
|
+
heartbeatAt: timestamp,
|
|
4433
|
+
projectRoot: identity.canonicalProjectRoot,
|
|
4434
|
+
indexPath: canonicalIndexPath,
|
|
4435
|
+
token: (0, import_node_crypto.randomUUID)()
|
|
4436
|
+
};
|
|
4437
|
+
if (publishLease(leasePath, owner)) {
|
|
4438
|
+
return { leasePath, owner };
|
|
4439
|
+
}
|
|
4440
|
+
const existingOwner = readOwner(leasePath);
|
|
4441
|
+
if (existingOwner) {
|
|
4442
|
+
if (canReclaimLease(leasePath, existingOwner) && reclaimLease(leasePath, existingOwner)) continue;
|
|
4443
|
+
return null;
|
|
4444
|
+
}
|
|
4445
|
+
return null;
|
|
4446
|
+
}
|
|
4447
|
+
return null;
|
|
4448
|
+
}
|
|
4449
|
+
function releaseLease(lease) {
|
|
4450
|
+
const currentOwner = readOwner(lease.leasePath);
|
|
4451
|
+
if (!currentOwner || !sameOwner2(currentOwner, lease.owner)) return false;
|
|
4452
|
+
const releasePath = `${lease.leasePath}.release.${lease.owner.pid}.${lease.owner.token}`;
|
|
4453
|
+
try {
|
|
4454
|
+
(0, import_node_fs.renameSync)(lease.leasePath, releasePath);
|
|
4455
|
+
} catch (error) {
|
|
4456
|
+
if (getErrorCode2(error) === "ENOENT") return false;
|
|
4457
|
+
throw error;
|
|
4458
|
+
}
|
|
4459
|
+
const claimedOwner = readOwner(releasePath);
|
|
4460
|
+
if (!claimedOwner || !sameOwner2(claimedOwner, lease.owner)) {
|
|
4461
|
+
if (!(0, import_node_fs.existsSync)(lease.leasePath) && (0, import_node_fs.existsSync)(releasePath)) {
|
|
4462
|
+
(0, import_node_fs.renameSync)(releasePath, lease.leasePath);
|
|
4463
|
+
}
|
|
4464
|
+
return false;
|
|
4465
|
+
}
|
|
4466
|
+
(0, import_node_fs.rmSync)(releasePath, { recursive: true, force: true });
|
|
4467
|
+
return true;
|
|
4468
|
+
}
|
|
4469
|
+
var BackgroundWorkerController = class {
|
|
4470
|
+
constructor(projectRoot3, host, config, hooks, identity) {
|
|
4471
|
+
this.projectRoot = projectRoot3;
|
|
4472
|
+
this.host = host;
|
|
4473
|
+
this.config = config;
|
|
4474
|
+
this.hooks = hooks;
|
|
4475
|
+
this.identity = identity;
|
|
4476
|
+
}
|
|
4477
|
+
projectRoot;
|
|
4478
|
+
host;
|
|
4479
|
+
config;
|
|
4480
|
+
hooks;
|
|
4481
|
+
identity;
|
|
4482
|
+
lease = null;
|
|
4483
|
+
watcher = null;
|
|
4484
|
+
leaderReady = Promise.resolve();
|
|
4485
|
+
heartbeatTimer = null;
|
|
4486
|
+
retryTimer = null;
|
|
4487
|
+
teardownRetryTimer = null;
|
|
4488
|
+
transition = Promise.resolve();
|
|
4489
|
+
stopPromise = null;
|
|
4490
|
+
stopped = false;
|
|
4491
|
+
stopping = false;
|
|
4492
|
+
losingLeadership = false;
|
|
4493
|
+
restartAfterStop = false;
|
|
4494
|
+
leaderWorkStopped = false;
|
|
4495
|
+
startingLeaderWork = false;
|
|
4496
|
+
stopAutoIndexOnTeardown = true;
|
|
4497
|
+
autoIndexStarted = false;
|
|
4498
|
+
reportedError = null;
|
|
4499
|
+
update(config, hooks, options) {
|
|
4500
|
+
const autoIndexWasEnabled = this.config.indexing.autoIndex;
|
|
4501
|
+
const shouldReplaceWatcher = this.watcher !== null && hooks.watcherFactory !== void 0 && (hooks.watcherFactory === null || hooks.replaceWatcher === true);
|
|
4502
|
+
this.config = config;
|
|
4503
|
+
this.hooks = {
|
|
4504
|
+
...this.hooks,
|
|
4505
|
+
...hooks,
|
|
4506
|
+
watcherFactory: hooks.watcherFactory === void 0 ? this.hooks.watcherFactory : hooks.watcherFactory,
|
|
4507
|
+
watcherFactoryForConfig: hooks.watcherFactoryForConfig === void 0 ? this.hooks.watcherFactoryForConfig : hooks.watcherFactoryForConfig
|
|
4508
|
+
};
|
|
4509
|
+
if (autoIndexWasEnabled && !config.indexing.autoIndex || options.restartAutoIndex === true && config.indexing.autoIndex && !this.startingLeaderWork) {
|
|
4510
|
+
this.autoIndexStarted = false;
|
|
4511
|
+
}
|
|
4512
|
+
if (!this.canRun()) {
|
|
4513
|
+
void this.stop().catch((error) => {
|
|
4514
|
+
console.error("[codebase-index] Failed to stop background worker after disabling automatic work:", error);
|
|
4515
|
+
});
|
|
4516
|
+
return;
|
|
4517
|
+
}
|
|
4518
|
+
if (shouldReplaceWatcher) {
|
|
4519
|
+
void this.enqueue(async () => {
|
|
4520
|
+
const watcher = this.watcher;
|
|
4521
|
+
if (watcher) {
|
|
4522
|
+
await watcher.stop();
|
|
4523
|
+
if (this.watcher === watcher) this.watcher = null;
|
|
4524
|
+
}
|
|
4525
|
+
if (this.lease && !this.stopped) this.startLeaderWork();
|
|
4526
|
+
}).catch((error) => {
|
|
4527
|
+
console.error("[codebase-index] Failed to replace background file watcher:", error);
|
|
4528
|
+
});
|
|
4529
|
+
}
|
|
4530
|
+
this.start();
|
|
4531
|
+
}
|
|
4532
|
+
startAfter(activation) {
|
|
4533
|
+
this.transition = activation.catch(() => void 0);
|
|
4534
|
+
this.start();
|
|
4535
|
+
}
|
|
4536
|
+
start() {
|
|
4537
|
+
if (!this.canRun() || this.losingLeadership) return;
|
|
4538
|
+
if (this.stopping) {
|
|
4539
|
+
this.restartAfterStop = true;
|
|
4540
|
+
return;
|
|
4541
|
+
}
|
|
4542
|
+
this.stopped = false;
|
|
4543
|
+
void this.enqueue(async () => {
|
|
4544
|
+
if (this.stopped || this.stopping || this.losingLeadership || !this.canRun()) return;
|
|
4545
|
+
if (!this.lease) {
|
|
4546
|
+
try {
|
|
4547
|
+
this.lease = acquireLease(this.identity);
|
|
4548
|
+
this.reportedError = null;
|
|
4549
|
+
} catch (error) {
|
|
4550
|
+
this.reportAcquireError(error);
|
|
4551
|
+
this.scheduleRetry();
|
|
4552
|
+
return;
|
|
4553
|
+
}
|
|
4554
|
+
}
|
|
4555
|
+
if (!this.lease) {
|
|
4556
|
+
this.scheduleRetry();
|
|
4557
|
+
return;
|
|
4558
|
+
}
|
|
4559
|
+
this.startHeartbeat();
|
|
4560
|
+
this.startLeaderWork();
|
|
4561
|
+
});
|
|
4562
|
+
}
|
|
4563
|
+
waitForStart() {
|
|
4564
|
+
return this.transition.catch(() => void 0).then(() => this.leaderReady);
|
|
4565
|
+
}
|
|
4566
|
+
requestRefresh(allowDisabledAutoIndex = false) {
|
|
4567
|
+
this.start();
|
|
4568
|
+
if (!this.isLeader()) {
|
|
4569
|
+
requestRefreshFromLeader(leasePathFor(this.identity), allowDisabledAutoIndex);
|
|
4570
|
+
return;
|
|
4571
|
+
}
|
|
4572
|
+
void this.enqueue(async () => {
|
|
4573
|
+
if (this.stopped || !this.lease) return;
|
|
4574
|
+
this.hooks.startAutoIndex("retrieval", allowDisabledAutoIndex);
|
|
4575
|
+
});
|
|
4576
|
+
}
|
|
4577
|
+
isLeader() {
|
|
4578
|
+
return this.lease !== null && !this.stopping && !this.losingLeadership;
|
|
4579
|
+
}
|
|
4580
|
+
isStopping() {
|
|
4581
|
+
return this.stopping;
|
|
4582
|
+
}
|
|
4583
|
+
getHooksForConfig(config) {
|
|
4584
|
+
const watcherFactoryForConfig = this.hooks.watcherFactoryForConfig;
|
|
4585
|
+
if (!watcherFactoryForConfig) return this.hooks;
|
|
4586
|
+
return {
|
|
4587
|
+
...this.hooks,
|
|
4588
|
+
watcherFactory: watcherFactoryForConfig(config),
|
|
4589
|
+
replaceWatcher: true
|
|
4590
|
+
};
|
|
4591
|
+
}
|
|
4592
|
+
attachWatcher(watcherFactory, watcherFactoryForConfig) {
|
|
4593
|
+
if (this.hooks.watcherFactory !== void 0) return;
|
|
4594
|
+
this.hooks = {
|
|
4595
|
+
...this.hooks,
|
|
4596
|
+
watcherFactory,
|
|
4597
|
+
watcherFactoryForConfig: watcherFactoryForConfig ?? this.hooks.watcherFactoryForConfig
|
|
4598
|
+
};
|
|
4599
|
+
this.start();
|
|
4600
|
+
}
|
|
4601
|
+
async stop(stopAutoIndex = true) {
|
|
4602
|
+
if (this.stopPromise) return this.stopPromise;
|
|
4603
|
+
this.stopped = true;
|
|
4604
|
+
this.stopping = true;
|
|
4605
|
+
this.stopAutoIndexOnTeardown &&= stopAutoIndex;
|
|
4606
|
+
this.clearRetryTimer();
|
|
4607
|
+
const attempt = this.enqueue(async () => {
|
|
4608
|
+
try {
|
|
4609
|
+
const lease = this.lease;
|
|
4610
|
+
if (this.leaderWorkStopped) {
|
|
4611
|
+
if (lease) {
|
|
4612
|
+
this.releaseStoppedLease(lease);
|
|
4613
|
+
} else {
|
|
4614
|
+
this.finishStoppedLease();
|
|
4615
|
+
}
|
|
4616
|
+
return;
|
|
4617
|
+
}
|
|
4618
|
+
const hadLeaderWork = lease !== null || this.watcher !== null || this.autoIndexStarted;
|
|
4619
|
+
const stopped = await this.stopLeaderWork(hadLeaderWork && this.stopAutoIndexOnTeardown);
|
|
4620
|
+
if (!lease) {
|
|
4621
|
+
this.finishStoppedLease();
|
|
4622
|
+
return;
|
|
4623
|
+
}
|
|
4624
|
+
if (!stopped.completed) {
|
|
4625
|
+
this.releaseLeaseWhenAutoIndexStops(lease, stopped.completion);
|
|
4626
|
+
return;
|
|
4627
|
+
}
|
|
4628
|
+
this.leaderWorkStopped = true;
|
|
4629
|
+
this.releaseStoppedLease(lease);
|
|
4630
|
+
} catch (error) {
|
|
4631
|
+
this.scheduleTeardownRetry();
|
|
4632
|
+
throw error;
|
|
4633
|
+
}
|
|
4634
|
+
});
|
|
4635
|
+
const completion = attempt.finally(() => {
|
|
4636
|
+
if (this.stopPromise === completion) this.stopPromise = null;
|
|
4637
|
+
});
|
|
4638
|
+
this.stopPromise = completion;
|
|
4639
|
+
return completion;
|
|
4640
|
+
}
|
|
4641
|
+
canRun() {
|
|
4642
|
+
return this.config.indexing.autoIndex || this.hooks.watcherFactory != null;
|
|
4643
|
+
}
|
|
4644
|
+
enqueue(operation) {
|
|
4645
|
+
const next = this.transition.catch(() => void 0).then(operation);
|
|
4646
|
+
this.transition = next;
|
|
4647
|
+
return next;
|
|
4648
|
+
}
|
|
4649
|
+
startLeaderWork() {
|
|
4650
|
+
if (this.stopped || this.stopping || this.losingLeadership) return;
|
|
4651
|
+
this.startingLeaderWork = true;
|
|
4652
|
+
try {
|
|
4653
|
+
if (this.config.indexing.autoIndex && !this.autoIndexStarted) {
|
|
4654
|
+
this.autoIndexStarted = true;
|
|
4655
|
+
this.hooks.startAutoIndex("startup");
|
|
4656
|
+
}
|
|
4657
|
+
if (!this.watcher && this.hooks.watcherFactory) {
|
|
4658
|
+
try {
|
|
4659
|
+
const watcher = this.hooks.watcherFactory();
|
|
4660
|
+
this.watcher = watcher;
|
|
4661
|
+
this.leaderReady = watcher.whenReady?.().catch((error) => {
|
|
4662
|
+
console.error("[codebase-index] Failed while waiting for background file watcher startup:", error);
|
|
4663
|
+
}) ?? Promise.resolve();
|
|
4664
|
+
} catch (error) {
|
|
4665
|
+
console.error("[codebase-index] Failed to start background file watcher:", error);
|
|
4666
|
+
this.leaderReady = Promise.resolve();
|
|
4667
|
+
}
|
|
4668
|
+
}
|
|
4669
|
+
} finally {
|
|
4670
|
+
this.startingLeaderWork = false;
|
|
4671
|
+
}
|
|
4672
|
+
}
|
|
4673
|
+
async stopLeaderWork(stopAutoIndex) {
|
|
4674
|
+
const watcher = this.watcher;
|
|
4675
|
+
let watcherError;
|
|
4676
|
+
if (watcher) {
|
|
4677
|
+
try {
|
|
4678
|
+
await watcher.stop();
|
|
4679
|
+
if (this.watcher === watcher) this.watcher = null;
|
|
4680
|
+
} catch (error) {
|
|
4681
|
+
watcherError = error;
|
|
4682
|
+
}
|
|
4683
|
+
}
|
|
4684
|
+
let autoIndexError;
|
|
4685
|
+
let autoIndexStop = {
|
|
4686
|
+
completed: true,
|
|
4687
|
+
completion: Promise.resolve()
|
|
4688
|
+
};
|
|
4689
|
+
if (stopAutoIndex) {
|
|
4690
|
+
try {
|
|
4691
|
+
autoIndexStop = await this.hooks.stopAutoIndex();
|
|
4692
|
+
this.autoIndexStarted = false;
|
|
4693
|
+
} catch (error) {
|
|
4694
|
+
autoIndexError = error;
|
|
4695
|
+
}
|
|
4696
|
+
}
|
|
4697
|
+
if (watcherError !== void 0 || autoIndexError !== void 0) {
|
|
4698
|
+
throw new BackgroundWorkerStopError(watcherError, autoIndexError);
|
|
4699
|
+
}
|
|
4700
|
+
return autoIndexStop;
|
|
4701
|
+
}
|
|
4702
|
+
releaseLeaseWhenAutoIndexStops(lease, completion) {
|
|
4703
|
+
void completion.then(
|
|
4704
|
+
() => {
|
|
4705
|
+
void this.enqueue(async () => {
|
|
4706
|
+
if (this.lease !== lease || !this.stopping) return;
|
|
4707
|
+
this.leaderWorkStopped = true;
|
|
4708
|
+
this.releaseStoppedLease(lease);
|
|
4709
|
+
}).catch((error) => {
|
|
4710
|
+
console.error("[codebase-index] Failed to release background worker lease after automatic indexing stopped:", error);
|
|
4711
|
+
this.scheduleTeardownRetry();
|
|
4712
|
+
});
|
|
4713
|
+
},
|
|
4714
|
+
(error) => {
|
|
4715
|
+
console.error("[codebase-index] Failed while waiting for automatic indexing to stop:", error);
|
|
4716
|
+
this.scheduleTeardownRetry();
|
|
4717
|
+
}
|
|
4718
|
+
);
|
|
4719
|
+
}
|
|
4720
|
+
releaseStoppedLease(lease) {
|
|
4721
|
+
if (this.lease !== lease) {
|
|
4722
|
+
this.finishStoppedLease();
|
|
4723
|
+
return;
|
|
4724
|
+
}
|
|
4725
|
+
releaseLease(lease);
|
|
4726
|
+
this.lease = null;
|
|
4727
|
+
this.finishStoppedLease();
|
|
4728
|
+
}
|
|
4729
|
+
finishStoppedLease() {
|
|
4730
|
+
this.leaderWorkStopped = false;
|
|
4731
|
+
this.stopAutoIndexOnTeardown = true;
|
|
4732
|
+
this.stopping = false;
|
|
4733
|
+
this.clearTimers();
|
|
4734
|
+
this.restartAfterTeardown();
|
|
4735
|
+
if (!this.stopped || this.stopping) return;
|
|
4736
|
+
const projectKey = projectLookupKey(this.projectRoot, this.host);
|
|
4737
|
+
const key = controllerKey(this.identity, this.host);
|
|
4738
|
+
if (workers.get(key) === this) workers.delete(key);
|
|
4739
|
+
if (workerKeysByProject.get(projectKey) === key) workerKeysByProject.delete(projectKey);
|
|
4740
|
+
}
|
|
4741
|
+
startHeartbeat() {
|
|
4742
|
+
if (this.heartbeatTimer) return;
|
|
4743
|
+
const heartbeat = () => {
|
|
4744
|
+
void this.heartbeat();
|
|
4745
|
+
};
|
|
4746
|
+
this.heartbeatTimer = setInterval(heartbeat, HEARTBEAT_INTERVAL_MS);
|
|
4747
|
+
this.heartbeatTimer.unref?.();
|
|
4748
|
+
}
|
|
4749
|
+
async heartbeat() {
|
|
4750
|
+
const lease = this.lease;
|
|
4751
|
+
if (!lease || this.losingLeadership || this.stopped && !this.stopping) return;
|
|
4752
|
+
if (hasActiveReclaimMarker(lease.leasePath, lease.owner)) {
|
|
4753
|
+
await this.loseLeadership();
|
|
4754
|
+
return;
|
|
4755
|
+
}
|
|
4756
|
+
const currentOwner = readOwner(lease.leasePath);
|
|
4757
|
+
if (!currentOwner || !sameOwner2(currentOwner, lease.owner)) {
|
|
4758
|
+
await this.loseLeadership();
|
|
4759
|
+
return;
|
|
4760
|
+
}
|
|
4761
|
+
try {
|
|
4762
|
+
const nextOwner = { ...lease.owner, heartbeatAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
4763
|
+
if (!writeHeartbeat(lease.leasePath, nextOwner)) {
|
|
4764
|
+
await this.loseLeadership();
|
|
4765
|
+
return;
|
|
4766
|
+
}
|
|
4767
|
+
lease.owner = nextOwner;
|
|
4768
|
+
const refreshRequest = !this.stopping ? consumeRefreshRequest(lease.leasePath) : null;
|
|
4769
|
+
if (refreshRequest) {
|
|
4770
|
+
this.hooks.startAutoIndex("retrieval", refreshRequest.allowDisabledAutoIndex);
|
|
4771
|
+
}
|
|
4772
|
+
} catch (error) {
|
|
4773
|
+
const ownerAfterError = readOwner(lease.leasePath);
|
|
4774
|
+
if (hasActiveReclaimMarker(lease.leasePath, lease.owner) || !ownerAfterError || !sameOwner2(ownerAfterError, lease.owner)) {
|
|
4775
|
+
await this.loseLeadership();
|
|
4776
|
+
return;
|
|
4777
|
+
}
|
|
4778
|
+
console.error("[codebase-index] Failed to renew background worker lease:", error);
|
|
4779
|
+
}
|
|
4780
|
+
}
|
|
4781
|
+
async loseLeadership() {
|
|
4782
|
+
if (this.losingLeadership) return;
|
|
4783
|
+
this.losingLeadership = true;
|
|
4784
|
+
this.clearHeartbeat();
|
|
4785
|
+
await this.enqueue(async () => this.stopAfterLeadershipLoss());
|
|
4786
|
+
}
|
|
4787
|
+
async stopAfterLeadershipLoss() {
|
|
4788
|
+
const lease = this.lease;
|
|
4789
|
+
if (!lease) {
|
|
4790
|
+
this.losingLeadership = false;
|
|
4791
|
+
return;
|
|
4792
|
+
}
|
|
4793
|
+
try {
|
|
4794
|
+
const stopped = await this.stopLeaderWork(true);
|
|
4795
|
+
this.lease = null;
|
|
4796
|
+
this.losingLeadership = false;
|
|
4797
|
+
if (stopped.completed) {
|
|
4798
|
+
this.scheduleRetry();
|
|
4799
|
+
} else {
|
|
4800
|
+
void stopped.completion.then(() => this.scheduleRetry());
|
|
4801
|
+
}
|
|
4802
|
+
} catch (error) {
|
|
4803
|
+
console.error("[codebase-index] Failed to stop background work after losing its lease:", error);
|
|
4804
|
+
this.scheduleLostLeadershipTeardownRetry();
|
|
4805
|
+
}
|
|
4806
|
+
}
|
|
4807
|
+
scheduleRetry() {
|
|
4808
|
+
if (this.stopped || !this.canRun() || this.retryTimer) return;
|
|
4809
|
+
this.retryTimer = setTimeout(() => {
|
|
4810
|
+
this.retryTimer = null;
|
|
4811
|
+
this.start();
|
|
4812
|
+
}, RETRY_DELAY_MS);
|
|
4813
|
+
this.retryTimer.unref?.();
|
|
4814
|
+
}
|
|
4815
|
+
scheduleTeardownRetry() {
|
|
4816
|
+
if (!this.stopping || this.teardownRetryTimer) return;
|
|
4817
|
+
this.teardownRetryTimer = setTimeout(() => {
|
|
4818
|
+
this.teardownRetryTimer = null;
|
|
4819
|
+
void this.stop(this.stopAutoIndexOnTeardown).catch((error) => {
|
|
4820
|
+
console.error("[codebase-index] Failed to retry background worker teardown:", error);
|
|
4821
|
+
});
|
|
4822
|
+
}, RETRY_DELAY_MS);
|
|
4823
|
+
this.teardownRetryTimer.unref?.();
|
|
4824
|
+
}
|
|
4825
|
+
restartAfterTeardown() {
|
|
4826
|
+
if (!this.restartAfterStop || !this.canRun() || this.losingLeadership) return;
|
|
4827
|
+
this.restartAfterStop = false;
|
|
4828
|
+
this.stopped = false;
|
|
4829
|
+
this.start();
|
|
4830
|
+
}
|
|
4831
|
+
scheduleLostLeadershipTeardownRetry() {
|
|
4832
|
+
if (this.stopped || !this.losingLeadership || this.retryTimer) return;
|
|
4833
|
+
this.retryTimer = setTimeout(() => {
|
|
4834
|
+
this.retryTimer = null;
|
|
4835
|
+
void this.enqueue(async () => this.stopAfterLeadershipLoss());
|
|
4836
|
+
}, RETRY_DELAY_MS);
|
|
4837
|
+
this.retryTimer.unref?.();
|
|
4838
|
+
}
|
|
4839
|
+
clearHeartbeat() {
|
|
4840
|
+
if (!this.heartbeatTimer) return;
|
|
4841
|
+
clearInterval(this.heartbeatTimer);
|
|
4842
|
+
this.heartbeatTimer = null;
|
|
4843
|
+
}
|
|
4844
|
+
clearTimers() {
|
|
4845
|
+
this.clearHeartbeat();
|
|
4846
|
+
this.clearRetryTimer();
|
|
4847
|
+
if (this.teardownRetryTimer) {
|
|
4848
|
+
clearTimeout(this.teardownRetryTimer);
|
|
4849
|
+
this.teardownRetryTimer = null;
|
|
4850
|
+
}
|
|
4851
|
+
}
|
|
4852
|
+
clearRetryTimer() {
|
|
4853
|
+
if (!this.retryTimer) return;
|
|
4854
|
+
clearTimeout(this.retryTimer);
|
|
4855
|
+
this.retryTimer = null;
|
|
4856
|
+
}
|
|
4857
|
+
reportAcquireError(error) {
|
|
4858
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
4859
|
+
if (this.reportedError === message) return;
|
|
4860
|
+
this.reportedError = message;
|
|
4861
|
+
console.error("[codebase-index] Failed to acquire background worker lease:", error);
|
|
4862
|
+
}
|
|
4863
|
+
};
|
|
4864
|
+
function configureBackgroundWorker(projectRoot3, host, config, hooks, options = {}) {
|
|
4865
|
+
const projectKey = projectLookupKey(projectRoot3, host);
|
|
4866
|
+
const identity = resolveIdentity(projectRoot3, config, host);
|
|
4867
|
+
const key = controllerKey(identity, host);
|
|
4868
|
+
const previousKey = workerKeysByProject.get(projectKey);
|
|
4869
|
+
if (previousKey && previousKey !== key) {
|
|
4870
|
+
const previous = workers.get(previousKey);
|
|
4871
|
+
const previousBarrier = workerReplacementBarriers.get(projectKey) ?? Promise.resolve();
|
|
4872
|
+
const stopPrevious = previous?.stop(options.stopPreviousAutoIndex ?? true) ?? Promise.resolve();
|
|
4873
|
+
const activation = Promise.all([previousBarrier, stopPrevious]).then(() => void 0);
|
|
4874
|
+
workerReplacementBarriers.set(projectKey, activation);
|
|
4875
|
+
workers.delete(previousKey);
|
|
4876
|
+
const worker2 = new BackgroundWorkerController(projectRoot3, host, config, hooks, identity);
|
|
4877
|
+
worker2.startAfter(activation);
|
|
4878
|
+
workers.set(key, worker2);
|
|
4879
|
+
workerKeysByProject.set(projectKey, key);
|
|
4880
|
+
return;
|
|
4881
|
+
}
|
|
4882
|
+
let worker = workers.get(key);
|
|
4883
|
+
if (!worker) {
|
|
4884
|
+
worker = new BackgroundWorkerController(projectRoot3, host, config, hooks, identity);
|
|
4885
|
+
workers.set(key, worker);
|
|
4886
|
+
} else {
|
|
4887
|
+
worker.update(config, hooks, options);
|
|
4888
|
+
}
|
|
4889
|
+
workerKeysByProject.set(projectKey, key);
|
|
4890
|
+
worker.start();
|
|
4891
|
+
}
|
|
4892
|
+
function updateBackgroundWorkerConfig(projectRoot3, host, config) {
|
|
4893
|
+
const projectKey = projectLookupKey(projectRoot3, host);
|
|
4894
|
+
const key = workerKeysByProject.get(projectKey);
|
|
4895
|
+
const worker = key ? workers.get(key) : void 0;
|
|
4896
|
+
if (!worker) return;
|
|
4897
|
+
configureBackgroundWorker(projectRoot3, host, config, worker.getHooksForConfig(config), {
|
|
4898
|
+
stopPreviousAutoIndex: false,
|
|
4899
|
+
restartAutoIndex: true
|
|
4900
|
+
});
|
|
4901
|
+
}
|
|
4902
|
+
function waitForBackgroundWorkerStart(projectRoot3, host) {
|
|
4903
|
+
const key = workerKeysByProject.get(projectLookupKey(projectRoot3, host));
|
|
4904
|
+
return workers.get(key ?? "")?.waitForStart() ?? Promise.resolve();
|
|
4905
|
+
}
|
|
4906
|
+
function requestBackgroundWorkerRefresh(projectRoot3, host, allowDisabledAutoIndex = false) {
|
|
4907
|
+
const key = workerKeysByProject.get(projectLookupKey(projectRoot3, host));
|
|
4908
|
+
workers.get(key ?? "")?.requestRefresh(allowDisabledAutoIndex);
|
|
4909
|
+
}
|
|
4910
|
+
function isBackgroundWorkerManaged(projectRoot3, host) {
|
|
4911
|
+
const key = workerKeysByProject.get(projectLookupKey(projectRoot3, host));
|
|
4912
|
+
return key !== void 0 && workers.has(key);
|
|
4913
|
+
}
|
|
4914
|
+
function isBackgroundWorkerLeader(projectRoot3, host) {
|
|
4915
|
+
const key = workerKeysByProject.get(projectLookupKey(projectRoot3, host));
|
|
4916
|
+
return key !== void 0 && workers.get(key)?.isLeader() === true;
|
|
4917
|
+
}
|
|
4918
|
+
async function stopBackgroundWorker(projectRoot3, host) {
|
|
4919
|
+
const projectKey = projectLookupKey(projectRoot3, host);
|
|
4920
|
+
const key = workerKeysByProject.get(projectKey);
|
|
4921
|
+
const worker = key ? workers.get(key) : void 0;
|
|
4922
|
+
if (!worker) return;
|
|
4923
|
+
await worker.stop();
|
|
4924
|
+
}
|
|
4925
|
+
|
|
4052
4926
|
// src/utils/files.ts
|
|
4053
4927
|
var import_ignore = __toESM(require_ignore(), 1);
|
|
4054
4928
|
var import_fs7 = require("fs");
|
|
4055
|
-
var
|
|
4929
|
+
var path12 = __toESM(require("path"), 1);
|
|
4056
4930
|
var PROJECT_MARKERS = [
|
|
4057
4931
|
".git",
|
|
4058
4932
|
"package.json",
|
|
@@ -4070,7 +4944,7 @@ var PROJECT_MARKERS = [
|
|
|
4070
4944
|
];
|
|
4071
4945
|
function hasProjectMarker(projectRoot3) {
|
|
4072
4946
|
for (const marker of PROJECT_MARKERS) {
|
|
4073
|
-
if ((0, import_fs7.existsSync)(
|
|
4947
|
+
if ((0, import_fs7.existsSync)(path12.join(projectRoot3, marker))) {
|
|
4074
4948
|
return true;
|
|
4075
4949
|
}
|
|
4076
4950
|
}
|
|
@@ -4097,33 +4971,53 @@ function createIgnoreFilter(projectRoot3) {
|
|
|
4097
4971
|
"**/*build*/**"
|
|
4098
4972
|
];
|
|
4099
4973
|
ig.add(defaultIgnores);
|
|
4100
|
-
const gitignorePath =
|
|
4974
|
+
const gitignorePath = path12.join(projectRoot3, ".gitignore");
|
|
4101
4975
|
if ((0, import_fs7.existsSync)(gitignorePath)) {
|
|
4102
4976
|
const gitignoreContent = (0, import_fs7.readFileSync)(gitignorePath, "utf-8");
|
|
4103
4977
|
ig.add(gitignoreContent);
|
|
4104
4978
|
}
|
|
4105
4979
|
return ig;
|
|
4106
4980
|
}
|
|
4107
|
-
function
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4981
|
+
function toPosixRelativePath(relativePath) {
|
|
4982
|
+
return relativePath.split(path12.sep).join("/");
|
|
4983
|
+
}
|
|
4984
|
+
function matchesAnyGlob(filePath, patterns) {
|
|
4985
|
+
const normalized = toPosixRelativePath(filePath);
|
|
4986
|
+
return patterns.some((pattern) => matchGlob(normalized, pattern));
|
|
4987
|
+
}
|
|
4988
|
+
function isExcludedByPatterns(relativePath, excludePatterns) {
|
|
4989
|
+
return matchesAnyGlob(relativePath, excludePatterns);
|
|
4990
|
+
}
|
|
4991
|
+
function isExcludedDirectory(relativePath, excludePatterns) {
|
|
4992
|
+
const normalized = toPosixRelativePath(relativePath);
|
|
4993
|
+
if (matchesAnyGlob(normalized, excludePatterns)) {
|
|
4994
|
+
return true;
|
|
4114
4995
|
}
|
|
4115
4996
|
for (const pattern of excludePatterns) {
|
|
4116
|
-
|
|
4117
|
-
|
|
4997
|
+
const posixPattern = toPosixRelativePath(pattern).replace(/\/+$/, "");
|
|
4998
|
+
if (!posixPattern.endsWith("/**")) {
|
|
4999
|
+
continue;
|
|
4118
5000
|
}
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
if (matchGlob(relativePath, pattern)) {
|
|
5001
|
+
const directoryPattern = posixPattern.slice(0, -3);
|
|
5002
|
+
if (directoryPattern && matchesAnyGlob(normalized, [directoryPattern])) {
|
|
4122
5003
|
return true;
|
|
4123
5004
|
}
|
|
4124
5005
|
}
|
|
4125
5006
|
return false;
|
|
4126
5007
|
}
|
|
5008
|
+
function shouldIncludeFile(filePath, projectRoot3, includePatterns, excludePatterns, ignoreFilter) {
|
|
5009
|
+
const relativePath = toPosixRelativePath(path12.relative(projectRoot3, filePath));
|
|
5010
|
+
if (hasFilteredPathSegment(relativePath, "/")) {
|
|
5011
|
+
return false;
|
|
5012
|
+
}
|
|
5013
|
+
if (ignoreFilter.ignores(relativePath)) {
|
|
5014
|
+
return false;
|
|
5015
|
+
}
|
|
5016
|
+
if (isExcludedByPatterns(relativePath, excludePatterns)) {
|
|
5017
|
+
return false;
|
|
5018
|
+
}
|
|
5019
|
+
return matchesAnyGlob(relativePath, includePatterns);
|
|
5020
|
+
}
|
|
4127
5021
|
function matchGlob(filePath, pattern) {
|
|
4128
5022
|
if (pattern.startsWith("**/")) {
|
|
4129
5023
|
const withoutPrefix = pattern.slice(3);
|
|
@@ -4144,8 +5038,8 @@ async function* walkDirectory(dir, projectRoot3, includePatterns, excludePattern
|
|
|
4144
5038
|
const filesInDir = [];
|
|
4145
5039
|
const subdirs = [];
|
|
4146
5040
|
for (const entry of entries) {
|
|
4147
|
-
const fullPath =
|
|
4148
|
-
const relativePath =
|
|
5041
|
+
const fullPath = path12.join(dir, entry.name);
|
|
5042
|
+
const relativePath = toPosixRelativePath(path12.relative(projectRoot3, fullPath));
|
|
4149
5043
|
if (isHiddenPathSegment(entry.name)) {
|
|
4150
5044
|
if (entry.isDirectory()) {
|
|
4151
5045
|
skipped.push({ path: relativePath, reason: "excluded" });
|
|
@@ -4163,6 +5057,10 @@ async function* walkDirectory(dir, projectRoot3, includePatterns, excludePattern
|
|
|
4163
5057
|
continue;
|
|
4164
5058
|
}
|
|
4165
5059
|
if (entry.isDirectory()) {
|
|
5060
|
+
if (isExcludedDirectory(relativePath, excludePatterns)) {
|
|
5061
|
+
skipped.push({ path: relativePath, reason: "excluded" });
|
|
5062
|
+
continue;
|
|
5063
|
+
}
|
|
4166
5064
|
subdirs.push({ fullPath, relativePath });
|
|
4167
5065
|
} else if (entry.isFile()) {
|
|
4168
5066
|
const stat5 = await import_fs7.promises.stat(fullPath);
|
|
@@ -4170,20 +5068,11 @@ async function* walkDirectory(dir, projectRoot3, includePatterns, excludePattern
|
|
|
4170
5068
|
skipped.push({ path: relativePath, reason: "too_large" });
|
|
4171
5069
|
continue;
|
|
4172
5070
|
}
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
continue;
|
|
4177
|
-
}
|
|
4178
|
-
}
|
|
4179
|
-
let matched = false;
|
|
4180
|
-
for (const pattern of includePatterns) {
|
|
4181
|
-
if (matchGlob(relativePath, pattern)) {
|
|
4182
|
-
matched = true;
|
|
4183
|
-
break;
|
|
4184
|
-
}
|
|
5071
|
+
if (isExcludedByPatterns(relativePath, excludePatterns)) {
|
|
5072
|
+
skipped.push({ path: relativePath, reason: "excluded" });
|
|
5073
|
+
continue;
|
|
4185
5074
|
}
|
|
4186
|
-
if (
|
|
5075
|
+
if (matchesAnyGlob(relativePath, includePatterns)) {
|
|
4187
5076
|
filesInDir.push({ path: fullPath, size: stat5.size });
|
|
4188
5077
|
}
|
|
4189
5078
|
}
|
|
@@ -4194,7 +5083,7 @@ async function* walkDirectory(dir, projectRoot3, includePatterns, excludePattern
|
|
|
4194
5083
|
yield f;
|
|
4195
5084
|
}
|
|
4196
5085
|
for (let i = options.maxFilesPerDirectory; i < filesInDir.length; i++) {
|
|
4197
|
-
skipped.push({ path:
|
|
5086
|
+
skipped.push({ path: toPosixRelativePath(path12.relative(projectRoot3, filesInDir[i].path)), reason: "excluded" });
|
|
4198
5087
|
}
|
|
4199
5088
|
const canRecurse = options.maxDepth === -1 || currentDepth < options.maxDepth;
|
|
4200
5089
|
if (canRecurse) {
|
|
@@ -4234,8 +5123,8 @@ async function collectFiles(projectRoot3, includePatterns, excludePatterns, maxF
|
|
|
4234
5123
|
if (additionalRoots && additionalRoots.length > 0) {
|
|
4235
5124
|
const normalizedRoots = /* @__PURE__ */ new Set();
|
|
4236
5125
|
for (const kbRoot of additionalRoots) {
|
|
4237
|
-
const resolved =
|
|
4238
|
-
|
|
5126
|
+
const resolved = path12.normalize(
|
|
5127
|
+
path12.isAbsolute(kbRoot) ? kbRoot : path12.resolve(projectRoot3, kbRoot)
|
|
4239
5128
|
);
|
|
4240
5129
|
normalizedRoots.add(resolved);
|
|
4241
5130
|
}
|
|
@@ -4276,7 +5165,7 @@ function getErrorMessage(error) {
|
|
|
4276
5165
|
return error instanceof Error ? error.message : String(error);
|
|
4277
5166
|
}
|
|
4278
5167
|
function runCommand(file, args, options) {
|
|
4279
|
-
return new Promise((
|
|
5168
|
+
return new Promise((resolve18, reject) => {
|
|
4280
5169
|
childProcess.execFile(
|
|
4281
5170
|
file,
|
|
4282
5171
|
args,
|
|
@@ -4286,7 +5175,7 @@ function runCommand(file, args, options) {
|
|
|
4286
5175
|
reject(error);
|
|
4287
5176
|
return;
|
|
4288
5177
|
}
|
|
4289
|
-
|
|
5178
|
+
resolve18(stdout);
|
|
4290
5179
|
}
|
|
4291
5180
|
);
|
|
4292
5181
|
});
|
|
@@ -4378,8 +5267,8 @@ var AutoIndexCancelledError = class extends Error {
|
|
|
4378
5267
|
function now() {
|
|
4379
5268
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
4380
5269
|
}
|
|
4381
|
-
function
|
|
4382
|
-
const resolved =
|
|
5270
|
+
function canonicalizePath2(targetPath) {
|
|
5271
|
+
const resolved = path13.resolve(targetPath);
|
|
4383
5272
|
if ((0, import_fs8.existsSync)(resolved)) {
|
|
4384
5273
|
try {
|
|
4385
5274
|
return import_fs8.realpathSync.native(resolved);
|
|
@@ -4387,20 +5276,20 @@ function canonicalizePath(targetPath) {
|
|
|
4387
5276
|
return resolved;
|
|
4388
5277
|
}
|
|
4389
5278
|
}
|
|
4390
|
-
const parent =
|
|
5279
|
+
const parent = path13.dirname(resolved);
|
|
4391
5280
|
if (parent === resolved) return resolved;
|
|
4392
|
-
return
|
|
5281
|
+
return path13.join(canonicalizePath2(parent), path13.basename(resolved));
|
|
4393
5282
|
}
|
|
4394
5283
|
function isHomeDirectory(projectRoot3) {
|
|
4395
|
-
return
|
|
5284
|
+
return canonicalizePath2(projectRoot3) === canonicalizePath2(os5.homedir());
|
|
4396
5285
|
}
|
|
4397
|
-
function
|
|
4398
|
-
return `${host}::${
|
|
5286
|
+
function projectLookupKey2(projectRoot3, host) {
|
|
5287
|
+
return `${host}::${canonicalizePath2(projectRoot3)}`;
|
|
4399
5288
|
}
|
|
4400
5289
|
function coordinatorKey(projectRoot3, config, host) {
|
|
4401
|
-
const canonicalProjectRoot =
|
|
5290
|
+
const canonicalProjectRoot = canonicalizePath2(projectRoot3);
|
|
4402
5291
|
const indexPath = resolveProjectIndexPath(projectRoot3, config.scope, host);
|
|
4403
|
-
return `${
|
|
5292
|
+
return `${canonicalizePath2(indexPath)}::${canonicalProjectRoot}`;
|
|
4404
5293
|
}
|
|
4405
5294
|
function getProjectSafety(projectRoot3, config) {
|
|
4406
5295
|
if (isHomeDirectory(projectRoot3)) {
|
|
@@ -4431,10 +5320,10 @@ function safeFailureMessage(error) {
|
|
|
4431
5320
|
}
|
|
4432
5321
|
function cancellableDelay(delayMs, signal) {
|
|
4433
5322
|
if (signal.aborted) return Promise.reject(new AutoIndexCancelledError());
|
|
4434
|
-
return new Promise((
|
|
5323
|
+
return new Promise((resolve18, reject) => {
|
|
4435
5324
|
const timer = setTimeout(() => {
|
|
4436
5325
|
signal.removeEventListener("abort", onAbort);
|
|
4437
|
-
|
|
5326
|
+
resolve18();
|
|
4438
5327
|
}, delayMs);
|
|
4439
5328
|
timer.unref?.();
|
|
4440
5329
|
const onAbort = () => {
|
|
@@ -4446,18 +5335,44 @@ function cancellableDelay(delayMs, signal) {
|
|
|
4446
5335
|
}
|
|
4447
5336
|
function withTimeout(promise, timeoutMs) {
|
|
4448
5337
|
if (timeoutMs <= 0) return Promise.resolve(void 0);
|
|
4449
|
-
return new Promise((
|
|
4450
|
-
const timer = setTimeout(() =>
|
|
5338
|
+
return new Promise((resolve18) => {
|
|
5339
|
+
const timer = setTimeout(() => resolve18(void 0), timeoutMs);
|
|
4451
5340
|
timer.unref?.();
|
|
4452
5341
|
void promise.then((value) => {
|
|
4453
5342
|
clearTimeout(timer);
|
|
4454
|
-
|
|
5343
|
+
resolve18(value);
|
|
4455
5344
|
}, () => {
|
|
4456
5345
|
clearTimeout(timer);
|
|
4457
|
-
|
|
5346
|
+
resolve18(void 0);
|
|
4458
5347
|
});
|
|
4459
5348
|
});
|
|
4460
5349
|
}
|
|
5350
|
+
function settlesWithin(promise, timeoutMs) {
|
|
5351
|
+
if (timeoutMs <= 0) return Promise.resolve(false);
|
|
5352
|
+
return new Promise((resolve18) => {
|
|
5353
|
+
let settled = false;
|
|
5354
|
+
const timer = setTimeout(() => {
|
|
5355
|
+
if (settled) return;
|
|
5356
|
+
settled = true;
|
|
5357
|
+
resolve18(false);
|
|
5358
|
+
}, timeoutMs);
|
|
5359
|
+
timer.unref?.();
|
|
5360
|
+
void promise.then(
|
|
5361
|
+
() => {
|
|
5362
|
+
if (settled) return;
|
|
5363
|
+
settled = true;
|
|
5364
|
+
clearTimeout(timer);
|
|
5365
|
+
resolve18(true);
|
|
5366
|
+
},
|
|
5367
|
+
() => {
|
|
5368
|
+
if (settled) return;
|
|
5369
|
+
settled = true;
|
|
5370
|
+
clearTimeout(timer);
|
|
5371
|
+
resolve18(true);
|
|
5372
|
+
}
|
|
5373
|
+
);
|
|
5374
|
+
});
|
|
5375
|
+
}
|
|
4461
5376
|
function requestPriority(request) {
|
|
4462
5377
|
if (request.force) return 4;
|
|
4463
5378
|
if (request.source === "manual") return 3;
|
|
@@ -4468,6 +5383,7 @@ function mergeRequests(current, next) {
|
|
|
4468
5383
|
if (!current) return next;
|
|
4469
5384
|
const preferred = requestPriority(next) > requestPriority(current) ? next : current;
|
|
4470
5385
|
return {
|
|
5386
|
+
allowDisabledAutoIndex: current.allowDisabledAutoIndex || next.allowDisabledAutoIndex,
|
|
4471
5387
|
checkFreshness: current.checkFreshness && next.checkFreshness,
|
|
4472
5388
|
force: current.force || next.force,
|
|
4473
5389
|
onProgress: next.onProgress ?? current.onProgress,
|
|
@@ -4529,11 +5445,11 @@ var AutoIndexCoordinator = class {
|
|
|
4529
5445
|
progress: this.status.progress ? { ...this.status.progress } : void 0
|
|
4530
5446
|
};
|
|
4531
5447
|
}
|
|
4532
|
-
start(source) {
|
|
5448
|
+
start(source, allowDisabledAutoIndex = false) {
|
|
4533
5449
|
this.refreshSafety();
|
|
4534
|
-
if (!this.registration.config.indexing.autoIndex || !this.registration.safeToRun) return null;
|
|
5450
|
+
if (!this.registration.config.indexing.autoIndex && !allowDisabledAutoIndex || !this.registration.safeToRun) return null;
|
|
4535
5451
|
if (this.status.state === "failed") return this.inFlight;
|
|
4536
|
-
return this.request({ checkFreshness: true, force: false, source });
|
|
5452
|
+
return this.request({ allowDisabledAutoIndex, checkFreshness: true, force: false, source });
|
|
4537
5453
|
}
|
|
4538
5454
|
request(request) {
|
|
4539
5455
|
if (this.stopped) {
|
|
@@ -4608,13 +5524,15 @@ var AutoIndexCoordinator = class {
|
|
|
4608
5524
|
retryAttempt: void 0
|
|
4609
5525
|
});
|
|
4610
5526
|
const inFlight = this.inFlight;
|
|
4611
|
-
|
|
4612
|
-
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
|
|
4616
|
-
|
|
5527
|
+
const completion = inFlight ? inFlight.then(() => void 0, () => void 0) : Promise.resolve();
|
|
5528
|
+
if (!inFlight) {
|
|
5529
|
+
return { completed: true, completion };
|
|
5530
|
+
}
|
|
5531
|
+
if (waitForCompletion) {
|
|
5532
|
+
await completion;
|
|
5533
|
+
return { completed: true, completion };
|
|
4617
5534
|
}
|
|
5535
|
+
return { completed: await settlesWithin(completion, SHUTDOWN_WAIT_MS), completion };
|
|
4618
5536
|
}
|
|
4619
5537
|
startRequest(request) {
|
|
4620
5538
|
if (this.stopped || !this.canRun(request)) {
|
|
@@ -4803,7 +5721,7 @@ var AutoIndexCoordinator = class {
|
|
|
4803
5721
|
if (request.source === "manual" || request.source === "watcher") {
|
|
4804
5722
|
return true;
|
|
4805
5723
|
}
|
|
4806
|
-
return this.registration.safeToRun && this.registration.config.indexing.autoIndex;
|
|
5724
|
+
return this.registration.safeToRun && (this.registration.config.indexing.autoIndex || request.allowDisabledAutoIndex === true);
|
|
4807
5725
|
}
|
|
4808
5726
|
shouldDeferForBattery(request) {
|
|
4809
5727
|
return this.registration.backgroundIndexingPolicy !== null && (request.source === "startup" || request.source === "watcher");
|
|
@@ -4836,17 +5754,17 @@ var AutoIndexCoordinator = class {
|
|
|
4836
5754
|
}
|
|
4837
5755
|
}
|
|
4838
5756
|
waitForBatteryRetry(delayMs) {
|
|
4839
|
-
return new Promise((
|
|
5757
|
+
return new Promise((resolve18) => {
|
|
4840
5758
|
const timer = setTimeout(() => {
|
|
4841
5759
|
if (this.batteryRetryTimer === timer) {
|
|
4842
5760
|
this.batteryRetryTimer = null;
|
|
4843
5761
|
this.resolveBatteryRetry = null;
|
|
4844
5762
|
}
|
|
4845
|
-
|
|
5763
|
+
resolve18();
|
|
4846
5764
|
}, delayMs);
|
|
4847
5765
|
timer.unref?.();
|
|
4848
5766
|
this.batteryRetryTimer = timer;
|
|
4849
|
-
this.resolveBatteryRetry =
|
|
5767
|
+
this.resolveBatteryRetry = resolve18;
|
|
4850
5768
|
});
|
|
4851
5769
|
}
|
|
4852
5770
|
cancelBatteryRetry() {
|
|
@@ -4854,9 +5772,9 @@ var AutoIndexCoordinator = class {
|
|
|
4854
5772
|
clearTimeout(this.batteryRetryTimer);
|
|
4855
5773
|
this.batteryRetryTimer = null;
|
|
4856
5774
|
}
|
|
4857
|
-
const
|
|
5775
|
+
const resolve18 = this.resolveBatteryRetry;
|
|
4858
5776
|
this.resolveBatteryRetry = null;
|
|
4859
|
-
|
|
5777
|
+
resolve18?.();
|
|
4860
5778
|
}
|
|
4861
5779
|
finishBatteryCheck(batteryCheck) {
|
|
4862
5780
|
if (this.batteryCheck !== batteryCheck) return;
|
|
@@ -4869,12 +5787,25 @@ var AutoIndexCoordinator = class {
|
|
|
4869
5787
|
}
|
|
4870
5788
|
};
|
|
4871
5789
|
function getCoordinator(projectRoot3, host) {
|
|
4872
|
-
const key = coordinatorKeysByProject.get(
|
|
5790
|
+
const key = coordinatorKeysByProject.get(projectLookupKey2(projectRoot3, host));
|
|
4873
5791
|
return key ? coordinators.get(key) ?? null : null;
|
|
4874
5792
|
}
|
|
4875
|
-
function
|
|
4876
|
-
|
|
5793
|
+
function synchronizeBackgroundWorker(projectRoot3, host, config, safeToRun) {
|
|
5794
|
+
if (safeToRun) {
|
|
5795
|
+
updateBackgroundWorkerConfig(projectRoot3, host, config);
|
|
5796
|
+
return;
|
|
5797
|
+
}
|
|
5798
|
+
void stopBackgroundWorker(projectRoot3, host).catch((error) => {
|
|
5799
|
+
console.error("[codebase-index] Failed to stop background worker after project safety changed:", error);
|
|
5800
|
+
});
|
|
5801
|
+
}
|
|
5802
|
+
function configureAutoIndex(projectRoot3, host, config, getIndexer, options = {}) {
|
|
5803
|
+
const projectKey = projectLookupKey2(projectRoot3, host);
|
|
4877
5804
|
const safety = getProjectSafety(projectRoot3, config);
|
|
5805
|
+
const synchronizeWorker = options.synchronizeBackgroundWorker ?? true;
|
|
5806
|
+
if (options.preserveManagedWorker === true && isBackgroundWorkerManaged(projectRoot3, host)) {
|
|
5807
|
+
return;
|
|
5808
|
+
}
|
|
4878
5809
|
const registration = {
|
|
4879
5810
|
backgroundIndexingPolicy: createBackgroundIndexingPolicy(
|
|
4880
5811
|
config.indexing.pauseBackgroundIndexingOnBattery
|
|
@@ -4892,6 +5823,9 @@ function configureAutoIndex(projectRoot3, host, config, getIndexer) {
|
|
|
4892
5823
|
const stopPrevious = previousCoordinator?.stop(true) ?? Promise.resolve();
|
|
4893
5824
|
const activation = Promise.all([previousBarrier, stopPrevious]).then(() => void 0);
|
|
4894
5825
|
coordinatorReplacementBarriers.set(projectKey, activation);
|
|
5826
|
+
if (synchronizeWorker) {
|
|
5827
|
+
synchronizeBackgroundWorker(projectRoot3, host, config, safety.safeToRun);
|
|
5828
|
+
}
|
|
4895
5829
|
coordinators.delete(previousKey);
|
|
4896
5830
|
const coordinator2 = new AutoIndexCoordinator(registration);
|
|
4897
5831
|
coordinator2.activateAfter(activation);
|
|
@@ -4907,8 +5841,17 @@ function configureAutoIndex(projectRoot3, host, config, getIndexer) {
|
|
|
4907
5841
|
coordinator.update(registration);
|
|
4908
5842
|
}
|
|
4909
5843
|
coordinatorKeysByProject.set(projectKey, key);
|
|
5844
|
+
if (synchronizeWorker) {
|
|
5845
|
+
synchronizeBackgroundWorker(projectRoot3, host, config, safety.safeToRun);
|
|
5846
|
+
}
|
|
5847
|
+
}
|
|
5848
|
+
function startAutoIndexForBackgroundWorker(projectRoot3, host, source = "startup", allowDisabledAutoIndex = false) {
|
|
5849
|
+
return getCoordinator(projectRoot3, host)?.start(source, allowDisabledAutoIndex) ?? null;
|
|
4910
5850
|
}
|
|
4911
5851
|
function requestBackgroundIndex(projectRoot3, host) {
|
|
5852
|
+
if (isBackgroundWorkerManaged(projectRoot3, host) && !isBackgroundWorkerLeader(projectRoot3, host)) {
|
|
5853
|
+
return null;
|
|
5854
|
+
}
|
|
4912
5855
|
return getCoordinator(projectRoot3, host)?.request({
|
|
4913
5856
|
checkFreshness: false,
|
|
4914
5857
|
force: false,
|
|
@@ -4948,15 +5891,23 @@ async function waitForAutoIndexForRetrieval(projectRoot3, host) {
|
|
|
4948
5891
|
};
|
|
4949
5892
|
}
|
|
4950
5893
|
try {
|
|
4951
|
-
|
|
5894
|
+
const readiness = await getSearchReadiness(coordinator);
|
|
5895
|
+
if (readiness.searchable) {
|
|
5896
|
+
return { ready: true };
|
|
5897
|
+
}
|
|
5898
|
+
if (readiness.blocked) return unavailableSnapshotResult(readiness.reason);
|
|
4952
5899
|
} catch {
|
|
4953
5900
|
}
|
|
4954
|
-
const job =
|
|
5901
|
+
const job = startRetrievalRefresh(projectRoot3, host, coordinator);
|
|
4955
5902
|
if (job) {
|
|
4956
5903
|
await withTimeout(job, coordinator.getWaitMs());
|
|
5904
|
+
} else if (isBackgroundWorkerManaged(projectRoot3, host)) {
|
|
5905
|
+
await waitForPublishedSnapshot(coordinator, coordinator.getWaitMs());
|
|
4957
5906
|
}
|
|
4958
5907
|
try {
|
|
4959
|
-
|
|
5908
|
+
const readiness = await getSearchReadiness(coordinator);
|
|
5909
|
+
if (readiness.searchable) return { ready: true };
|
|
5910
|
+
if (readiness.blocked) return unavailableSnapshotResult(readiness.reason);
|
|
4960
5911
|
} catch {
|
|
4961
5912
|
}
|
|
4962
5913
|
const status = coordinator.snapshot();
|
|
@@ -4977,21 +5928,52 @@ async function waitForAutoIndexForRetrieval(projectRoot3, host) {
|
|
|
4977
5928
|
text: `Automatic indexing is ${status.state}. Retry shortly or call index_status for progress. You can also run index_codebase explicitly.`
|
|
4978
5929
|
};
|
|
4979
5930
|
}
|
|
4980
|
-
async function
|
|
4981
|
-
|
|
5931
|
+
async function stopAutoIndexForBackgroundWorker(projectRoot3, host, waitForCompletion = false) {
|
|
5932
|
+
const coordinator = getCoordinator(projectRoot3, host);
|
|
5933
|
+
if (!coordinator) {
|
|
5934
|
+
return { completed: true, completion: Promise.resolve() };
|
|
5935
|
+
}
|
|
5936
|
+
return coordinator.stop(waitForCompletion);
|
|
4982
5937
|
}
|
|
4983
|
-
async function
|
|
5938
|
+
async function getSearchReadiness(coordinator) {
|
|
4984
5939
|
const indexer = coordinator.getIndexer();
|
|
4985
5940
|
if (indexer.getIndexFreshness) {
|
|
4986
5941
|
const freshness = await indexer.getIndexFreshness();
|
|
4987
|
-
|
|
5942
|
+
const searchable = freshness.readable && freshness.current && freshness.reason === "current";
|
|
5943
|
+
return {
|
|
5944
|
+
blocked: freshness.reason === "unreadable" || freshness.reason === "incompatible" || freshness.reason === "failed-batches" || freshness.reason === "migration-required",
|
|
5945
|
+
reason: freshness.reason,
|
|
5946
|
+
searchable
|
|
5947
|
+
};
|
|
5948
|
+
}
|
|
5949
|
+
const indexed = (await indexer.getStatus()).indexed;
|
|
5950
|
+
return { blocked: false, searchable: indexed };
|
|
5951
|
+
}
|
|
5952
|
+
function unavailableSnapshotResult(reason) {
|
|
5953
|
+
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.";
|
|
5954
|
+
return {
|
|
5955
|
+
ready: false,
|
|
5956
|
+
text: `${detail} Run index_codebase before retrying retrieval.`
|
|
5957
|
+
};
|
|
5958
|
+
}
|
|
5959
|
+
function startRetrievalRefresh(projectRoot3, host, coordinator) {
|
|
5960
|
+
if (isBackgroundWorkerManaged(projectRoot3, host)) {
|
|
5961
|
+
requestBackgroundWorkerRefresh(projectRoot3, host, true);
|
|
5962
|
+
return isBackgroundWorkerLeader(projectRoot3, host) ? coordinator.currentJob() : null;
|
|
5963
|
+
}
|
|
5964
|
+
return coordinator.start("retrieval") ?? coordinator.currentJob();
|
|
5965
|
+
}
|
|
5966
|
+
async function waitForPublishedSnapshot(coordinator, waitMs) {
|
|
5967
|
+
const deadline = Date.now() + waitMs;
|
|
5968
|
+
while (Date.now() < deadline) {
|
|
5969
|
+
if ((await getSearchReadiness(coordinator)).searchable) return;
|
|
5970
|
+
await new Promise((resolve18) => setTimeout(resolve18, Math.min(250, deadline - Date.now())));
|
|
4988
5971
|
}
|
|
4989
|
-
return (await indexer.getStatus()).indexed;
|
|
4990
5972
|
}
|
|
4991
5973
|
|
|
4992
5974
|
// src/tools/config-state.ts
|
|
4993
5975
|
var import_fs9 = require("fs");
|
|
4994
|
-
var
|
|
5976
|
+
var path14 = __toESM(require("path"), 1);
|
|
4995
5977
|
function normalizeKnowledgeBasePaths(config, projectRoot3) {
|
|
4996
5978
|
const normalized = { ...config };
|
|
4997
5979
|
if (Array.isArray(normalized.knowledgeBases)) {
|
|
@@ -5018,8 +6000,8 @@ function loadEditableConfig(projectRoot3, host) {
|
|
|
5018
6000
|
}
|
|
5019
6001
|
function saveConfig(projectRoot3, config, host) {
|
|
5020
6002
|
const configPath = getConfigPath(projectRoot3, host);
|
|
5021
|
-
const configDir =
|
|
5022
|
-
const configBaseDir =
|
|
6003
|
+
const configDir = path14.dirname(configPath);
|
|
6004
|
+
const configBaseDir = path14.dirname(configDir);
|
|
5023
6005
|
if (!(0, import_fs9.existsSync)(configDir)) {
|
|
5024
6006
|
(0, import_fs9.mkdirSync)(configDir, { recursive: true });
|
|
5025
6007
|
}
|
|
@@ -5034,7 +6016,7 @@ function saveConfig(projectRoot3, config, host) {
|
|
|
5034
6016
|
|
|
5035
6017
|
// src/indexer/index.ts
|
|
5036
6018
|
var import_fs12 = require("fs");
|
|
5037
|
-
var
|
|
6019
|
+
var path20 = __toESM(require("path"), 1);
|
|
5038
6020
|
var import_perf_hooks = require("perf_hooks");
|
|
5039
6021
|
var import_child_process4 = require("child_process");
|
|
5040
6022
|
var import_util4 = require("util");
|
|
@@ -5061,7 +6043,7 @@ function pTimeout(promise, options) {
|
|
|
5061
6043
|
} = options;
|
|
5062
6044
|
let timer;
|
|
5063
6045
|
let abortHandler;
|
|
5064
|
-
const wrappedPromise = new Promise((
|
|
6046
|
+
const wrappedPromise = new Promise((resolve18, reject) => {
|
|
5065
6047
|
if (typeof milliseconds !== "number" || Math.sign(milliseconds) !== 1) {
|
|
5066
6048
|
throw new TypeError(`Expected \`milliseconds\` to be a positive number, got \`${milliseconds}\``);
|
|
5067
6049
|
}
|
|
@@ -5075,7 +6057,7 @@ function pTimeout(promise, options) {
|
|
|
5075
6057
|
};
|
|
5076
6058
|
signal.addEventListener("abort", abortHandler, { once: true });
|
|
5077
6059
|
}
|
|
5078
|
-
promise.then(
|
|
6060
|
+
promise.then(resolve18, reject);
|
|
5079
6061
|
if (milliseconds === Number.POSITIVE_INFINITY) {
|
|
5080
6062
|
return;
|
|
5081
6063
|
}
|
|
@@ -5083,7 +6065,7 @@ function pTimeout(promise, options) {
|
|
|
5083
6065
|
timer = customTimers.setTimeout.call(void 0, () => {
|
|
5084
6066
|
if (fallback) {
|
|
5085
6067
|
try {
|
|
5086
|
-
|
|
6068
|
+
resolve18(fallback());
|
|
5087
6069
|
} catch (error) {
|
|
5088
6070
|
reject(error);
|
|
5089
6071
|
}
|
|
@@ -5093,7 +6075,7 @@ function pTimeout(promise, options) {
|
|
|
5093
6075
|
promise.cancel();
|
|
5094
6076
|
}
|
|
5095
6077
|
if (message === false) {
|
|
5096
|
-
|
|
6078
|
+
resolve18();
|
|
5097
6079
|
} else if (message instanceof Error) {
|
|
5098
6080
|
reject(message);
|
|
5099
6081
|
} else {
|
|
@@ -5495,7 +6477,7 @@ var PQueue = class extends import_index.default {
|
|
|
5495
6477
|
// Assign unique ID if not provided
|
|
5496
6478
|
id: options.id ?? (this.#idAssigner++).toString()
|
|
5497
6479
|
};
|
|
5498
|
-
return new Promise((
|
|
6480
|
+
return new Promise((resolve18, reject) => {
|
|
5499
6481
|
const taskSymbol = /* @__PURE__ */ Symbol(`task-${options.id}`);
|
|
5500
6482
|
let cleanupQueueAbortHandler = () => void 0;
|
|
5501
6483
|
const run = async () => {
|
|
@@ -5535,7 +6517,7 @@ var PQueue = class extends import_index.default {
|
|
|
5535
6517
|
})]);
|
|
5536
6518
|
}
|
|
5537
6519
|
const result = await operation;
|
|
5538
|
-
|
|
6520
|
+
resolve18(result);
|
|
5539
6521
|
this.emit("completed", result);
|
|
5540
6522
|
} catch (error) {
|
|
5541
6523
|
reject(error);
|
|
@@ -5723,13 +6705,13 @@ var PQueue = class extends import_index.default {
|
|
|
5723
6705
|
});
|
|
5724
6706
|
}
|
|
5725
6707
|
async #onEvent(event, filter) {
|
|
5726
|
-
return new Promise((
|
|
6708
|
+
return new Promise((resolve18) => {
|
|
5727
6709
|
const listener = () => {
|
|
5728
6710
|
if (filter && !filter()) {
|
|
5729
6711
|
return;
|
|
5730
6712
|
}
|
|
5731
6713
|
this.off(event, listener);
|
|
5732
|
-
|
|
6714
|
+
resolve18();
|
|
5733
6715
|
};
|
|
5734
6716
|
this.on(event, listener);
|
|
5735
6717
|
});
|
|
@@ -6015,7 +6997,7 @@ async function onAttemptFailure({ error, attemptNumber, retriesConsumed, startTi
|
|
|
6015
6997
|
const finalDelay = Math.min(delayTime, remainingTime);
|
|
6016
6998
|
options.signal?.throwIfAborted();
|
|
6017
6999
|
if (finalDelay > 0) {
|
|
6018
|
-
await new Promise((
|
|
7000
|
+
await new Promise((resolve18, reject) => {
|
|
6019
7001
|
const onAbort = () => {
|
|
6020
7002
|
clearTimeout(timeoutToken);
|
|
6021
7003
|
options.signal?.removeEventListener("abort", onAbort);
|
|
@@ -6023,7 +7005,7 @@ async function onAttemptFailure({ error, attemptNumber, retriesConsumed, startTi
|
|
|
6023
7005
|
};
|
|
6024
7006
|
const timeoutToken = setTimeout(() => {
|
|
6025
7007
|
options.signal?.removeEventListener("abort", onAbort);
|
|
6026
|
-
|
|
7008
|
+
resolve18();
|
|
6027
7009
|
}, finalDelay);
|
|
6028
7010
|
if (options.unref) {
|
|
6029
7011
|
timeoutToken.unref?.();
|
|
@@ -6141,17 +7123,17 @@ function validateExternalUrl(urlString) {
|
|
|
6141
7123
|
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
6142
7124
|
return { valid: false, reason: `Blocked protocol: ${parsed.protocol}` };
|
|
6143
7125
|
}
|
|
6144
|
-
const
|
|
6145
|
-
if (BLOCKED_HOSTNAMES.has(
|
|
6146
|
-
return { valid: false, reason: `Blocked: cloud metadata service (${
|
|
7126
|
+
const hostname3 = parsed.hostname.toLowerCase();
|
|
7127
|
+
if (BLOCKED_HOSTNAMES.has(hostname3)) {
|
|
7128
|
+
return { valid: false, reason: `Blocked: cloud metadata service (${hostname3})` };
|
|
6147
7129
|
}
|
|
6148
7130
|
for (const pattern of BLOCKED_METADATA_IPS) {
|
|
6149
|
-
if (pattern.test(
|
|
6150
|
-
return { valid: false, reason: `Blocked: cloud metadata IP (${
|
|
7131
|
+
if (pattern.test(hostname3)) {
|
|
7132
|
+
return { valid: false, reason: `Blocked: cloud metadata IP (${hostname3})` };
|
|
6151
7133
|
}
|
|
6152
7134
|
}
|
|
6153
|
-
if (/^169\.254\./.test(
|
|
6154
|
-
return { valid: false, reason: `Blocked: link-local address (${
|
|
7135
|
+
if (/^169\.254\./.test(hostname3)) {
|
|
7136
|
+
return { valid: false, reason: `Blocked: link-local address (${hostname3})` };
|
|
6155
7137
|
}
|
|
6156
7138
|
return { valid: true };
|
|
6157
7139
|
}
|
|
@@ -7163,8 +8145,8 @@ function extractParamNames(params) {
|
|
|
7163
8145
|
}
|
|
7164
8146
|
|
|
7165
8147
|
// src/native/binding.ts
|
|
7166
|
-
var
|
|
7167
|
-
var
|
|
8148
|
+
var os6 = __toESM(require("os"), 1);
|
|
8149
|
+
var path15 = __toESM(require("path"), 1);
|
|
7168
8150
|
var module2 = __toESM(require("module"), 1);
|
|
7169
8151
|
var import_node_url = require("url");
|
|
7170
8152
|
|
|
@@ -7201,7 +8183,7 @@ var STABLE_NATIVE_BINARY_NAME = IDENTITY_CATALOG.native.binaryName;
|
|
|
7201
8183
|
|
|
7202
8184
|
// src/native/binding.ts
|
|
7203
8185
|
var import_meta = {};
|
|
7204
|
-
function getNativeBindingFilename(platform2 =
|
|
8186
|
+
function getNativeBindingFilename(platform2 = os6.platform(), arch2 = os6.arch()) {
|
|
7205
8187
|
if (platform2 === "darwin" && arch2 === "arm64") {
|
|
7206
8188
|
return `${STABLE_NATIVE_BINARY_NAME}.darwin-arm64.node`;
|
|
7207
8189
|
}
|
|
@@ -7219,25 +8201,25 @@ function getNativeBindingFilename(platform2 = os5.platform(), arch2 = os5.arch()
|
|
|
7219
8201
|
}
|
|
7220
8202
|
throw new Error(`Unsupported platform: ${platform2}-${arch2}`);
|
|
7221
8203
|
}
|
|
7222
|
-
function resolveNativeBindingPath(packageRoot, platform2 =
|
|
7223
|
-
return
|
|
8204
|
+
function resolveNativeBindingPath(packageRoot, platform2 = os6.platform(), arch2 = os6.arch()) {
|
|
8205
|
+
return path15.join(packageRoot, "native", getNativeBindingFilename(platform2, arch2));
|
|
7224
8206
|
}
|
|
7225
8207
|
function getNativeBinding() {
|
|
7226
8208
|
let currentDir;
|
|
7227
8209
|
let requireTarget;
|
|
7228
8210
|
if (typeof import_meta !== "undefined" && import_meta.url) {
|
|
7229
|
-
currentDir =
|
|
8211
|
+
currentDir = path15.dirname((0, import_node_url.fileURLToPath)(import_meta.url));
|
|
7230
8212
|
requireTarget = import_meta.url;
|
|
7231
8213
|
} else if (typeof __dirname !== "undefined") {
|
|
7232
8214
|
currentDir = __dirname;
|
|
7233
8215
|
requireTarget = __filename;
|
|
7234
8216
|
} else {
|
|
7235
8217
|
currentDir = process.cwd();
|
|
7236
|
-
requireTarget =
|
|
8218
|
+
requireTarget = path15.join(currentDir, "index.js");
|
|
7237
8219
|
}
|
|
7238
8220
|
const normalizedDir = currentDir.replace(/\\/g, "/");
|
|
7239
|
-
const isDevMode = normalizedDir.includes("/src/native") || currentDir.includes(
|
|
7240
|
-
const packageRoot = isDevMode ?
|
|
8221
|
+
const isDevMode = normalizedDir.includes("/src/native") || currentDir.includes(path15.join("src", "native"));
|
|
8222
|
+
const packageRoot = isDevMode ? path15.resolve(currentDir, "../..") : path15.resolve(currentDir, "..");
|
|
7241
8223
|
const nativePath = resolveNativeBindingPath(packageRoot);
|
|
7242
8224
|
const require2 = module2.createRequire(requireTarget);
|
|
7243
8225
|
return require2(nativePath);
|
|
@@ -7821,8 +8803,8 @@ var Database = class _Database {
|
|
|
7821
8803
|
|
|
7822
8804
|
// src/git/branch-materialization.ts
|
|
7823
8805
|
var import_fs10 = require("fs");
|
|
7824
|
-
var
|
|
7825
|
-
var
|
|
8806
|
+
var os7 = __toESM(require("os"), 1);
|
|
8807
|
+
var path16 = __toESM(require("path"), 1);
|
|
7826
8808
|
|
|
7827
8809
|
// src/git/branch-resolution.ts
|
|
7828
8810
|
var import_child_process = require("child_process");
|
|
@@ -8141,13 +9123,13 @@ async function isWorktreeRegistered(projectRoot3, worktreePath) {
|
|
|
8141
9123
|
return false;
|
|
8142
9124
|
}
|
|
8143
9125
|
function isPathWithinRoot(filePath, rootPath) {
|
|
8144
|
-
const relative13 =
|
|
8145
|
-
return relative13 === "" || !relative13.startsWith(`..${
|
|
9126
|
+
const relative13 = path16.relative(path16.resolve(rootPath), path16.resolve(filePath));
|
|
9127
|
+
return relative13 === "" || !relative13.startsWith(`..${path16.sep}`) && relative13 !== ".." && !path16.isAbsolute(relative13);
|
|
8146
9128
|
}
|
|
8147
9129
|
async function pruneExactMissingWorktreeRegistration(projectRoot3, worktreePath) {
|
|
8148
9130
|
if (await pathExists(worktreePath)) return false;
|
|
8149
9131
|
const commonDir = await runGit(projectRoot3, ["rev-parse", "--path-format=absolute", "--git-common-dir"]);
|
|
8150
|
-
const registrationsRoot =
|
|
9132
|
+
const registrationsRoot = path16.join(commonDir, "worktrees");
|
|
8151
9133
|
let entries;
|
|
8152
9134
|
try {
|
|
8153
9135
|
entries = await import_fs10.promises.readdir(registrationsRoot, { withFileTypes: true });
|
|
@@ -8158,16 +9140,16 @@ async function pruneExactMissingWorktreeRegistration(projectRoot3, worktreePath)
|
|
|
8158
9140
|
const target = canonicalizePathForComparison(worktreePath);
|
|
8159
9141
|
for (const entry of entries) {
|
|
8160
9142
|
if (!entry.isDirectory()) continue;
|
|
8161
|
-
const registrationPath =
|
|
9143
|
+
const registrationPath = path16.join(registrationsRoot, entry.name);
|
|
8162
9144
|
if (!isPathWithinRoot(registrationPath, registrationsRoot)) continue;
|
|
8163
9145
|
let gitdirPath;
|
|
8164
9146
|
try {
|
|
8165
|
-
gitdirPath = (await import_fs10.promises.readFile(
|
|
9147
|
+
gitdirPath = (await import_fs10.promises.readFile(path16.join(registrationPath, "gitdir"), "utf8")).trim();
|
|
8166
9148
|
} catch {
|
|
8167
9149
|
continue;
|
|
8168
9150
|
}
|
|
8169
|
-
const resolvedGitdirPath =
|
|
8170
|
-
if (canonicalizePathForComparison(
|
|
9151
|
+
const resolvedGitdirPath = path16.isAbsolute(gitdirPath) ? gitdirPath : path16.resolve(registrationPath, gitdirPath);
|
|
9152
|
+
if (canonicalizePathForComparison(path16.dirname(resolvedGitdirPath)) !== target) continue;
|
|
8171
9153
|
await import_fs10.promises.rm(registrationPath, { recursive: true, force: true });
|
|
8172
9154
|
return true;
|
|
8173
9155
|
}
|
|
@@ -8185,7 +9167,7 @@ async function removeWorktree(projectRoot3, worktreePath) {
|
|
|
8185
9167
|
registered = await isWorktreeRegistered(projectRoot3, worktreePath);
|
|
8186
9168
|
} catch (error) {
|
|
8187
9169
|
errors.push(asError(error));
|
|
8188
|
-
throw new AggregateError(errors, `Could not verify temporary worktree deregistration; preserved ${
|
|
9170
|
+
throw new AggregateError(errors, `Could not verify temporary worktree deregistration; preserved ${path16.dirname(worktreePath)}`);
|
|
8189
9171
|
}
|
|
8190
9172
|
if (registered) {
|
|
8191
9173
|
try {
|
|
@@ -8201,7 +9183,7 @@ async function removeWorktree(projectRoot3, worktreePath) {
|
|
|
8201
9183
|
registered = await isWorktreeRegistered(projectRoot3, worktreePath);
|
|
8202
9184
|
} catch (error) {
|
|
8203
9185
|
errors.push(asError(error));
|
|
8204
|
-
throw new AggregateError(errors, `Could not verify temporary worktree deregistration; preserved ${
|
|
9186
|
+
throw new AggregateError(errors, `Could not verify temporary worktree deregistration; preserved ${path16.dirname(worktreePath)}`);
|
|
8205
9187
|
}
|
|
8206
9188
|
}
|
|
8207
9189
|
if (registered && !await pathExists(worktreePath)) {
|
|
@@ -8214,13 +9196,13 @@ async function removeWorktree(projectRoot3, worktreePath) {
|
|
|
8214
9196
|
}
|
|
8215
9197
|
if (registered) {
|
|
8216
9198
|
errors.push(new Error(`Temporary worktree remains registered: ${worktreePath}`));
|
|
8217
|
-
throw new AggregateError(errors, `Failed to deregister temporary worktree; preserved ${
|
|
9199
|
+
throw new AggregateError(errors, `Failed to deregister temporary worktree; preserved ${path16.dirname(worktreePath)}`);
|
|
8218
9200
|
}
|
|
8219
9201
|
try {
|
|
8220
|
-
await import_fs10.promises.rm(
|
|
9202
|
+
await import_fs10.promises.rm(path16.dirname(worktreePath), { recursive: true, force: true });
|
|
8221
9203
|
} catch (error) {
|
|
8222
9204
|
errors.push(asError(error));
|
|
8223
|
-
throw new AggregateError(errors, `Deregistered the temporary worktree but could not remove ${
|
|
9205
|
+
throw new AggregateError(errors, `Deregistered the temporary worktree but could not remove ${path16.dirname(worktreePath)}`);
|
|
8224
9206
|
}
|
|
8225
9207
|
}
|
|
8226
9208
|
async function cleanupTemporaryWorktree(projectRoot3, worktreePath, temporaryRoot) {
|
|
@@ -8256,9 +9238,9 @@ async function withMaterializedBranch(request, callback) {
|
|
|
8256
9238
|
`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.`
|
|
8257
9239
|
);
|
|
8258
9240
|
}
|
|
8259
|
-
const temporaryRoot = await import_fs10.promises.mkdtemp(
|
|
8260
|
-
const worktreePath =
|
|
8261
|
-
const hooksPath =
|
|
9241
|
+
const temporaryRoot = await import_fs10.promises.mkdtemp(path16.join(os7.tmpdir(), "codebase-index-branch-"));
|
|
9242
|
+
const worktreePath = path16.join(temporaryRoot, "worktree");
|
|
9243
|
+
const hooksPath = path16.join(temporaryRoot, "hooks");
|
|
8262
9244
|
await import_fs10.promises.mkdir(hooksPath);
|
|
8263
9245
|
const info = {
|
|
8264
9246
|
branch: request.branch,
|
|
@@ -8310,7 +9292,7 @@ async function withMaterializedBranch(request, callback) {
|
|
|
8310
9292
|
// src/tools/changed-files.ts
|
|
8311
9293
|
var import_child_process2 = require("child_process");
|
|
8312
9294
|
var import_fs11 = require("fs");
|
|
8313
|
-
var
|
|
9295
|
+
var path17 = __toESM(require("path"), 1);
|
|
8314
9296
|
var import_util2 = require("util");
|
|
8315
9297
|
var execFileAsync2 = (0, import_util2.promisify)(import_child_process2.execFile);
|
|
8316
9298
|
var GH_PR_VIEW_FIELDS = [
|
|
@@ -8452,7 +9434,7 @@ function getHeadRepositoryIdentity(data, host) {
|
|
|
8452
9434
|
return `${host}/${owner.toLowerCase()}/${repository.replace(/\.git$/i, "").toLowerCase()}`;
|
|
8453
9435
|
}
|
|
8454
9436
|
function getLocalRepositoryIdentity(projectRoot3) {
|
|
8455
|
-
let canonicalRoot =
|
|
9437
|
+
let canonicalRoot = path17.resolve(projectRoot3);
|
|
8456
9438
|
try {
|
|
8457
9439
|
canonicalRoot = import_fs11.realpathSync.native(canonicalRoot);
|
|
8458
9440
|
} catch {
|
|
@@ -8513,17 +9495,17 @@ async function getMergeBase(projectRoot3, baseCommit, headCommit) {
|
|
|
8513
9495
|
return commit;
|
|
8514
9496
|
}
|
|
8515
9497
|
function normalizeFiles(rawFiles, projectRoot3) {
|
|
8516
|
-
const root =
|
|
9498
|
+
const root = path17.resolve(projectRoot3);
|
|
8517
9499
|
const seen = /* @__PURE__ */ new Set();
|
|
8518
9500
|
const result = [];
|
|
8519
9501
|
for (const raw of rawFiles) {
|
|
8520
9502
|
if (raw.length === 0) continue;
|
|
8521
|
-
const absolute =
|
|
8522
|
-
const relative13 =
|
|
8523
|
-
if (
|
|
9503
|
+
const absolute = path17.resolve(root, raw);
|
|
9504
|
+
const relative13 = path17.relative(root, absolute);
|
|
9505
|
+
if (path17.isAbsolute(raw) || relative13 === ".." || relative13.startsWith(`..${path17.sep}`) || path17.isAbsolute(relative13)) {
|
|
8524
9506
|
throw new Error(`Changed file escapes the project root: ${JSON.stringify(raw)}`);
|
|
8525
9507
|
}
|
|
8526
|
-
const cleaned = relative13.startsWith(`.${
|
|
9508
|
+
const cleaned = relative13.startsWith(`.${path17.sep}`) ? relative13.slice(2) : relative13;
|
|
8527
9509
|
if (!seen.has(cleaned)) {
|
|
8528
9510
|
seen.add(cleaned);
|
|
8529
9511
|
result.push(cleaned);
|
|
@@ -8534,7 +9516,7 @@ function normalizeFiles(rawFiles, projectRoot3) {
|
|
|
8534
9516
|
|
|
8535
9517
|
// src/indexer/git-blame.ts
|
|
8536
9518
|
var import_child_process3 = require("child_process");
|
|
8537
|
-
var
|
|
9519
|
+
var path18 = __toESM(require("path"), 1);
|
|
8538
9520
|
var import_util3 = require("util");
|
|
8539
9521
|
var execFileAsync3 = (0, import_util3.promisify)(import_child_process3.execFile);
|
|
8540
9522
|
function parseGitBlamePorcelain(output) {
|
|
@@ -8572,7 +9554,7 @@ function parseGitBlamePorcelain(output) {
|
|
|
8572
9554
|
return Array.from(commits.values()).filter((commit) => commit.lines > 0).sort((a, b) => b.lines - a.lines || b.committedAt - a.committedAt)[0];
|
|
8573
9555
|
}
|
|
8574
9556
|
async function getChunkGitBlame(projectRoot3, filePath, startLine, endLine) {
|
|
8575
|
-
const relativePath =
|
|
9557
|
+
const relativePath = path18.relative(projectRoot3, filePath);
|
|
8576
9558
|
try {
|
|
8577
9559
|
const { stdout } = await execFileAsync3(
|
|
8578
9560
|
"git",
|
|
@@ -9151,8 +10133,8 @@ function pathSegmentsForAffinityMatch(filePath) {
|
|
|
9151
10133
|
if (segments.length === 0) {
|
|
9152
10134
|
return [];
|
|
9153
10135
|
}
|
|
9154
|
-
const
|
|
9155
|
-
const basenameWithoutExt =
|
|
10136
|
+
const basename8 = segments[segments.length - 1] ?? "";
|
|
10137
|
+
const basenameWithoutExt = basename8.replace(/\.[^/.]+$/u, "");
|
|
9156
10138
|
const normalizedSegments = segments.map((segment) => segment.toLowerCase());
|
|
9157
10139
|
return Array.from(/* @__PURE__ */ new Set([
|
|
9158
10140
|
...normalizedSegments,
|
|
@@ -9461,8 +10443,8 @@ function hasAllEmbeddingParts(parts, expectedPartCount) {
|
|
|
9461
10443
|
|
|
9462
10444
|
// src/indexer/failed-state-persistence.ts
|
|
9463
10445
|
var fs2 = __toESM(require("fs"), 1);
|
|
9464
|
-
var
|
|
9465
|
-
var
|
|
10446
|
+
var import_node_crypto2 = require("crypto");
|
|
10447
|
+
var path19 = __toESM(require("path"), 1);
|
|
9466
10448
|
var import_node_string_decoder = require("string_decoder");
|
|
9467
10449
|
var CURRENT_FAILED_BATCH_VERSION = 1;
|
|
9468
10450
|
var DEFAULT_MALFORMED_LINE_ACTION = "skip";
|
|
@@ -9480,7 +10462,7 @@ function* readFailedBatchRecords(filePath, options = {}) {
|
|
|
9480
10462
|
function createFailedBatchWriter(targetPath) {
|
|
9481
10463
|
const temporaryPath = createTemporaryPath(targetPath);
|
|
9482
10464
|
let finalized = false;
|
|
9483
|
-
fs2.mkdirSync(
|
|
10465
|
+
fs2.mkdirSync(path19.dirname(targetPath), { recursive: true });
|
|
9484
10466
|
fs2.closeSync(fs2.openSync(temporaryPath, "w"));
|
|
9485
10467
|
const write = (record) => {
|
|
9486
10468
|
if (finalized) {
|
|
@@ -9499,7 +10481,7 @@ function createFailedBatchWriter(targetPath) {
|
|
|
9499
10481
|
if (lines.length === 0) {
|
|
9500
10482
|
return;
|
|
9501
10483
|
}
|
|
9502
|
-
fs2.mkdirSync(
|
|
10484
|
+
fs2.mkdirSync(path19.dirname(targetPath), { recursive: true });
|
|
9503
10485
|
fs2.appendFileSync(temporaryPath, `${lines.join("\n")}
|
|
9504
10486
|
`, "utf-8");
|
|
9505
10487
|
};
|
|
@@ -9507,7 +10489,7 @@ function createFailedBatchWriter(targetPath) {
|
|
|
9507
10489
|
if (finalized) {
|
|
9508
10490
|
return;
|
|
9509
10491
|
}
|
|
9510
|
-
fs2.mkdirSync(
|
|
10492
|
+
fs2.mkdirSync(path19.dirname(targetPath), { recursive: true });
|
|
9511
10493
|
fs2.renameSync(temporaryPath, targetPath);
|
|
9512
10494
|
finalized = true;
|
|
9513
10495
|
};
|
|
@@ -9653,10 +10635,10 @@ function stripLeadingBomAndWhitespace(value) {
|
|
|
9653
10635
|
return result;
|
|
9654
10636
|
}
|
|
9655
10637
|
function createTemporaryPath(targetPath) {
|
|
9656
|
-
const randomId = (0,
|
|
9657
|
-
const targetDir =
|
|
9658
|
-
const baseName =
|
|
9659
|
-
return
|
|
10638
|
+
const randomId = (0, import_node_crypto2.createHash)("sha1").update(`${Date.now()}:${(0, import_node_crypto2.randomBytes)(8).toString("hex")}`).digest("hex");
|
|
10639
|
+
const targetDir = path19.dirname(targetPath);
|
|
10640
|
+
const baseName = path19.basename(targetPath);
|
|
10641
|
+
return path19.join(targetDir, `.${baseName}.${randomId}.tmp`);
|
|
9660
10642
|
}
|
|
9661
10643
|
function handleMalformedLine(filePath, lineNumber, line, error, options) {
|
|
9662
10644
|
const action = options.malformedLineAction ?? DEFAULT_MALFORMED_LINE_ACTION;
|
|
@@ -9902,9 +10884,9 @@ var SWIFT_PARSER_VERSION = "1";
|
|
|
9902
10884
|
var METAL_PARSER_VERSION = "1";
|
|
9903
10885
|
var SYMBOL_EXTRACTOR_VERSION = "1";
|
|
9904
10886
|
function isPathWithinRoot2(filePath, rootPath) {
|
|
9905
|
-
const normalizedFilePath =
|
|
9906
|
-
const normalizedRoot =
|
|
9907
|
-
return normalizedFilePath === normalizedRoot || normalizedFilePath.startsWith(`${normalizedRoot}${
|
|
10887
|
+
const normalizedFilePath = path20.resolve(filePath);
|
|
10888
|
+
const normalizedRoot = path20.resolve(rootPath);
|
|
10889
|
+
return normalizedFilePath === normalizedRoot || normalizedFilePath.startsWith(`${normalizedRoot}${path20.sep}`);
|
|
9908
10890
|
}
|
|
9909
10891
|
function promoteIdentifierMatches(query, combined, semanticCandidates, keywordCandidates, database, branchChunkIds, prioritizeSourcePaths = classifyQueryIntentRaw(query) === "source") {
|
|
9910
10892
|
if (combined.length === 0) {
|
|
@@ -10235,10 +11217,10 @@ function matchesHardSearchFilters(candidate, options, projectRoot3) {
|
|
|
10235
11217
|
}
|
|
10236
11218
|
if (options?.directory) {
|
|
10237
11219
|
const candidatePath = canonicalizePathForComparison(
|
|
10238
|
-
|
|
11220
|
+
path20.resolve(projectRoot3, candidate.metadata.filePath.replace(/\\/g, path20.sep))
|
|
10239
11221
|
);
|
|
10240
11222
|
const directoryPath = canonicalizePathForComparison(
|
|
10241
|
-
|
|
11223
|
+
path20.resolve(projectRoot3, options.directory.trim().replace(/\\/g, path20.sep))
|
|
10242
11224
|
);
|
|
10243
11225
|
if (!isPathWithinRoot2(candidatePath, directoryPath)) return false;
|
|
10244
11226
|
}
|
|
@@ -10351,26 +11333,37 @@ var Indexer = class _Indexer {
|
|
|
10351
11333
|
return this.indexPathOverride ?? resolveProjectIndexPath(this.projectRoot, this.config.scope, this.host);
|
|
10352
11334
|
}
|
|
10353
11335
|
toCanonicalFilePath(filePath) {
|
|
10354
|
-
if (!
|
|
11336
|
+
if (!path20.isAbsolute(filePath)) {
|
|
10355
11337
|
return this.resolveStoredFilePath(filePath, this.projectRoot);
|
|
10356
11338
|
}
|
|
10357
|
-
if (
|
|
11339
|
+
if (path20.resolve(this.materializedProjectRoot) === path20.resolve(this.projectRoot) || !isPathWithinRoot2(filePath, this.materializedProjectRoot)) {
|
|
10358
11340
|
return filePath;
|
|
10359
11341
|
}
|
|
10360
|
-
return
|
|
11342
|
+
return path20.resolve(this.projectRoot, path20.relative(this.materializedProjectRoot, filePath));
|
|
10361
11343
|
}
|
|
10362
11344
|
toStoredFilePath(filePath) {
|
|
10363
11345
|
const canonicalFilePath = this.toCanonicalFilePath(filePath);
|
|
10364
11346
|
if (this.config.scope !== "project" || !isPathWithinRoot2(canonicalFilePath, this.projectRoot)) {
|
|
10365
11347
|
return canonicalFilePath;
|
|
10366
11348
|
}
|
|
10367
|
-
return
|
|
11349
|
+
return path20.relative(this.projectRoot, canonicalFilePath).split(path20.sep).join("/");
|
|
11350
|
+
}
|
|
11351
|
+
isStoredPathExcluded(storedPath) {
|
|
11352
|
+
let matchPath = storedPath.split(path20.sep).join("/");
|
|
11353
|
+
if (path20.isAbsolute(storedPath)) {
|
|
11354
|
+
const relativePath = path20.relative(this.projectRoot, storedPath).split(path20.sep).join("/");
|
|
11355
|
+
if (relativePath.startsWith("..") || path20.isAbsolute(relativePath)) {
|
|
11356
|
+
return false;
|
|
11357
|
+
}
|
|
11358
|
+
matchPath = relativePath;
|
|
11359
|
+
}
|
|
11360
|
+
return isExcludedByPatterns(matchPath, this.config.exclude);
|
|
10368
11361
|
}
|
|
10369
11362
|
resolveStoredFilePath(filePath, rootPath = this.projectRoot) {
|
|
10370
|
-
if (
|
|
11363
|
+
if (path20.isAbsolute(filePath)) {
|
|
10371
11364
|
return filePath;
|
|
10372
11365
|
}
|
|
10373
|
-
const resolvedPath =
|
|
11366
|
+
const resolvedPath = path20.resolve(rootPath, ...filePath.split("/"));
|
|
10374
11367
|
if (!isPathWithinRoot2(resolvedPath, rootPath)) {
|
|
10375
11368
|
throw new Error(`Stored project path escapes project root: ${JSON.stringify(filePath)}`);
|
|
10376
11369
|
}
|
|
@@ -10394,7 +11387,7 @@ var Indexer = class _Indexer {
|
|
|
10394
11387
|
}
|
|
10395
11388
|
toMaterializedFilePath(filePath) {
|
|
10396
11389
|
const storedFilePath = this.toStoredFilePath(filePath);
|
|
10397
|
-
if (
|
|
11390
|
+
if (path20.isAbsolute(storedFilePath)) {
|
|
10398
11391
|
return storedFilePath;
|
|
10399
11392
|
}
|
|
10400
11393
|
return this.resolveStoredFilePath(storedFilePath, this.materializedProjectRoot);
|
|
@@ -10411,10 +11404,10 @@ var Indexer = class _Indexer {
|
|
|
10411
11404
|
}
|
|
10412
11405
|
getRuntimeArtifactPath(fileName) {
|
|
10413
11406
|
const namespace = this.getRuntimeArtifactNamespace();
|
|
10414
|
-
if (!namespace) return
|
|
10415
|
-
const extension =
|
|
11407
|
+
if (!namespace) return path20.join(this.indexPath, fileName);
|
|
11408
|
+
const extension = path20.extname(fileName);
|
|
10416
11409
|
const baseName = fileName.slice(0, fileName.length - extension.length);
|
|
10417
|
-
return
|
|
11410
|
+
return path20.join(this.indexPath, `${baseName}.${namespace}${extension}`);
|
|
10418
11411
|
}
|
|
10419
11412
|
refreshRuntimeArtifactPaths() {
|
|
10420
11413
|
this.fileHashCachePath = this.getRuntimeArtifactPath("file-hashes.json");
|
|
@@ -10427,14 +11420,14 @@ var Indexer = class _Indexer {
|
|
|
10427
11420
|
getMaterializedKnowledgeBases() {
|
|
10428
11421
|
const canonicalProjectRoot = this.getCanonicalPath(this.projectRoot);
|
|
10429
11422
|
return this.config.knowledgeBases.map((knowledgeBase) => {
|
|
10430
|
-
const configuredPath =
|
|
11423
|
+
const configuredPath = path20.isAbsolute(knowledgeBase) ? knowledgeBase : path20.resolve(this.projectRoot, knowledgeBase);
|
|
10431
11424
|
const canonicalPath = this.getCanonicalPath(configuredPath);
|
|
10432
11425
|
if (!isPathWithinRoot2(canonicalPath, canonicalProjectRoot)) {
|
|
10433
11426
|
return canonicalPath;
|
|
10434
11427
|
}
|
|
10435
|
-
return
|
|
11428
|
+
return path20.resolve(
|
|
10436
11429
|
this.materializedProjectRoot,
|
|
10437
|
-
|
|
11430
|
+
path20.relative(canonicalProjectRoot, canonicalPath)
|
|
10438
11431
|
);
|
|
10439
11432
|
});
|
|
10440
11433
|
}
|
|
@@ -10442,7 +11435,7 @@ var Indexer = class _Indexer {
|
|
|
10442
11435
|
try {
|
|
10443
11436
|
return canonicalizePathForComparison(targetPath);
|
|
10444
11437
|
} catch {
|
|
10445
|
-
return
|
|
11438
|
+
return path20.resolve(targetPath);
|
|
10446
11439
|
}
|
|
10447
11440
|
}
|
|
10448
11441
|
getProjectIdentityHash(projectRoot3) {
|
|
@@ -10568,7 +11561,7 @@ var Indexer = class _Indexer {
|
|
|
10568
11561
|
atomicWriteSync(targetPath, data) {
|
|
10569
11562
|
const lease = this.requireActiveLease();
|
|
10570
11563
|
const tempPath = createLeaseTemporaryPath(targetPath, lease.owner, "tmp");
|
|
10571
|
-
(0, import_fs12.mkdirSync)(
|
|
11564
|
+
(0, import_fs12.mkdirSync)(path20.dirname(targetPath), { recursive: true });
|
|
10572
11565
|
try {
|
|
10573
11566
|
(0, import_fs12.writeFileSync)(tempPath, data);
|
|
10574
11567
|
(0, import_fs12.renameSync)(tempPath, targetPath);
|
|
@@ -10578,14 +11571,14 @@ var Indexer = class _Indexer {
|
|
|
10578
11571
|
}
|
|
10579
11572
|
saveInvertedIndex(invertedIndex) {
|
|
10580
11573
|
this.atomicWriteSync(
|
|
10581
|
-
|
|
11574
|
+
path20.join(this.indexPath, "inverted-index.json"),
|
|
10582
11575
|
invertedIndex.serialize()
|
|
10583
11576
|
);
|
|
10584
11577
|
}
|
|
10585
11578
|
getScopedRoots(projectRoot3 = this.projectRoot) {
|
|
10586
11579
|
const roots = /* @__PURE__ */ new Set([this.getCanonicalPath(projectRoot3)]);
|
|
10587
11580
|
for (const kbRoot of this.config.knowledgeBases) {
|
|
10588
|
-
roots.add(this.getCanonicalPath(
|
|
11581
|
+
roots.add(this.getCanonicalPath(path20.resolve(projectRoot3, kbRoot)));
|
|
10589
11582
|
}
|
|
10590
11583
|
return Array.from(roots);
|
|
10591
11584
|
}
|
|
@@ -11002,7 +11995,7 @@ var Indexer = class _Indexer {
|
|
|
11002
11995
|
return configuredProviderInfo !== null && recovery.embeddingProvider === configuredProviderInfo.provider && recovery.embeddingModel === configuredProviderInfo.modelInfo.model && recovery.embeddingDimensions === configuredProviderInfo.modelInfo.dimensions && recovery.embeddingStrategyVersion === EMBEDDING_STRATEGY_VERSION;
|
|
11003
11996
|
}
|
|
11004
11997
|
hasUnknownLegacyForceIndexClear(owner) {
|
|
11005
|
-
return owner.operation === "force-index" && owner.clearRecovery === void 0 && owner.recoveryProtocolVersion !== 1 && (0, import_fs12.existsSync)(
|
|
11998
|
+
return owner.operation === "force-index" && owner.clearRecovery === void 0 && owner.recoveryProtocolVersion !== 1 && (0, import_fs12.existsSync)(path20.join(this.indexPath, "force-index-phase"));
|
|
11006
11999
|
}
|
|
11007
12000
|
async recoverFromInterruptedIndexingUnlocked(owners) {
|
|
11008
12001
|
for (const owner of owners) {
|
|
@@ -11390,7 +12383,7 @@ var Indexer = class _Indexer {
|
|
|
11390
12383
|
await options.queue.onSizeLessThan(Math.max(1, options.providerRateLimits.concurrency));
|
|
11391
12384
|
const task = options.queue.add(async () => {
|
|
11392
12385
|
if (options.rateLimitState.backoffMs > 0) {
|
|
11393
|
-
await new Promise((
|
|
12386
|
+
await new Promise((resolve18) => setTimeout(resolve18, options.rateLimitState.backoffMs));
|
|
11394
12387
|
}
|
|
11395
12388
|
try {
|
|
11396
12389
|
const embeddingResult = await pRetry(
|
|
@@ -11809,12 +12802,12 @@ var Indexer = class _Indexer {
|
|
|
11809
12802
|
}
|
|
11810
12803
|
}
|
|
11811
12804
|
captureReaderArtifactFingerprint() {
|
|
11812
|
-
const storePath =
|
|
12805
|
+
const storePath = path20.join(this.indexPath, "vectors");
|
|
11813
12806
|
return {
|
|
11814
12807
|
vectors: `${this.getReaderFileFingerprint(storePath)}|${this.getReaderFileFingerprint(`${storePath}.meta.json`)}`,
|
|
11815
|
-
keyword: this.getReaderFileFingerprint(
|
|
11816
|
-
database: this.getReaderFileFingerprint(
|
|
11817
|
-
databaseIdentity: this.getReaderFileFingerprint(
|
|
12808
|
+
keyword: this.getReaderFileFingerprint(path20.join(this.indexPath, "inverted-index.json")),
|
|
12809
|
+
database: this.getReaderFileFingerprint(path20.join(this.indexPath, "codebase.db")),
|
|
12810
|
+
databaseIdentity: this.getReaderFileFingerprint(path20.join(this.indexPath, "codebase.db"), true)
|
|
11818
12811
|
};
|
|
11819
12812
|
}
|
|
11820
12813
|
refreshReaderArtifacts() {
|
|
@@ -11839,10 +12832,10 @@ var Indexer = class _Indexer {
|
|
|
11839
12832
|
issues.set(component, this.createReadIssue(component, message));
|
|
11840
12833
|
this.readerArtifactRetryAfter.set(component, Date.now() + READER_ARTIFACT_RETRY_INTERVAL_MS);
|
|
11841
12834
|
};
|
|
11842
|
-
const storePath =
|
|
12835
|
+
const storePath = path20.join(this.indexPath, "vectors");
|
|
11843
12836
|
const vectorMetadataPath = `${storePath}.meta.json`;
|
|
11844
|
-
const invertedIndexPath =
|
|
11845
|
-
const dbPath =
|
|
12837
|
+
const invertedIndexPath = path20.join(this.indexPath, "inverted-index.json");
|
|
12838
|
+
const dbPath = path20.join(this.indexPath, "codebase.db");
|
|
11846
12839
|
if (vectorsChanged || retryDue("vectors")) {
|
|
11847
12840
|
const vectorStoreExists = (0, import_fs12.existsSync)(storePath);
|
|
11848
12841
|
const vectorMetadataExists = (0, import_fs12.existsSync)(vectorMetadataPath);
|
|
@@ -11958,10 +12951,10 @@ var Indexer = class _Indexer {
|
|
|
11958
12951
|
});
|
|
11959
12952
|
this.provider = createEmbeddingProvider(this.configuredProviderInfo);
|
|
11960
12953
|
const dimensions = this.configuredProviderInfo.modelInfo.dimensions;
|
|
11961
|
-
const storePath =
|
|
12954
|
+
const storePath = path20.join(this.indexPath, "vectors");
|
|
11962
12955
|
const vectorMetadataPath = `${storePath}.meta.json`;
|
|
11963
|
-
const invertedIndexPath =
|
|
11964
|
-
const dbPath =
|
|
12956
|
+
const invertedIndexPath = path20.join(this.indexPath, "inverted-index.json");
|
|
12957
|
+
const dbPath = path20.join(this.indexPath, "codebase.db");
|
|
11965
12958
|
let dbIsNew = !(0, import_fs12.existsSync)(dbPath);
|
|
11966
12959
|
const readerArtifactFingerprint = mode === "reader" ? this.captureReaderArtifactFingerprint() : null;
|
|
11967
12960
|
if (mode === "writer") {
|
|
@@ -12139,7 +13132,7 @@ var Indexer = class _Indexer {
|
|
|
12139
13132
|
if (await this.tryResetCorruptedIndex("running automatic orphan garbage collection", error)) {
|
|
12140
13133
|
return {
|
|
12141
13134
|
resetCorruptedIndex: true,
|
|
12142
|
-
warning: this.getCorruptedIndexWarning(
|
|
13135
|
+
warning: this.getCorruptedIndexWarning(path20.join(this.indexPath, "codebase.db"))
|
|
12143
13136
|
};
|
|
12144
13137
|
}
|
|
12145
13138
|
throw error;
|
|
@@ -12154,7 +13147,7 @@ var Indexer = class _Indexer {
|
|
|
12154
13147
|
return;
|
|
12155
13148
|
}
|
|
12156
13149
|
const retainedEntries = store.getAllMetadata().filter(({ key }) => !excludedSet.has(key));
|
|
12157
|
-
const storeBasePath =
|
|
13150
|
+
const storeBasePath = path20.join(this.indexPath, "vectors");
|
|
12158
13151
|
const storeIndexPath = storeBasePath;
|
|
12159
13152
|
const storeMetadataPath = `${storeBasePath}.meta.json`;
|
|
12160
13153
|
const lease = this.requireActiveLease();
|
|
@@ -12241,7 +13234,7 @@ var Indexer = class _Indexer {
|
|
|
12241
13234
|
const names = await import_fs12.promises.readdir(this.indexPath);
|
|
12242
13235
|
const runtimeStatePattern = /^(?:file-hashes|failed-batches)(?:\.[a-f0-9]{16})?\.json$/;
|
|
12243
13236
|
await Promise.all(
|
|
12244
|
-
names.filter((name) => runtimeStatePattern.test(name)).map((name) => import_fs12.promises.rm(
|
|
13237
|
+
names.filter((name) => runtimeStatePattern.test(name)).map((name) => import_fs12.promises.rm(path20.join(this.indexPath, name), { force: true }))
|
|
12245
13238
|
);
|
|
12246
13239
|
}
|
|
12247
13240
|
async resetLocalIndexArtifacts() {
|
|
@@ -12257,13 +13250,13 @@ var Indexer = class _Indexer {
|
|
|
12257
13250
|
this.readerArtifactRetryAfter.clear();
|
|
12258
13251
|
this.fileHashCache.clear();
|
|
12259
13252
|
const resetPaths = [
|
|
12260
|
-
|
|
12261
|
-
|
|
12262
|
-
|
|
12263
|
-
|
|
12264
|
-
|
|
12265
|
-
|
|
12266
|
-
|
|
13253
|
+
path20.join(this.indexPath, "codebase.db"),
|
|
13254
|
+
path20.join(this.indexPath, "codebase.db-shm"),
|
|
13255
|
+
path20.join(this.indexPath, "codebase.db-wal"),
|
|
13256
|
+
path20.join(this.indexPath, "vectors"),
|
|
13257
|
+
path20.join(this.indexPath, "vectors.usearch"),
|
|
13258
|
+
path20.join(this.indexPath, "vectors.meta.json"),
|
|
13259
|
+
path20.join(this.indexPath, "inverted-index.json")
|
|
12267
13260
|
];
|
|
12268
13261
|
await Promise.all(resetPaths.map((targetPath) => import_fs12.promises.rm(targetPath, { recursive: true, force: true })));
|
|
12269
13262
|
await this.removeProjectRuntimeStateArtifacts();
|
|
@@ -12273,7 +13266,7 @@ var Indexer = class _Indexer {
|
|
|
12273
13266
|
if (!isSqliteCorruptionError(error)) {
|
|
12274
13267
|
return false;
|
|
12275
13268
|
}
|
|
12276
|
-
const dbPath =
|
|
13269
|
+
const dbPath = path20.join(this.indexPath, "codebase.db");
|
|
12277
13270
|
const warning = this.getCorruptedIndexWarning(dbPath);
|
|
12278
13271
|
const errorMessage = getErrorMessage4(error);
|
|
12279
13272
|
if (this.config.scope === "global") {
|
|
@@ -12660,10 +13653,10 @@ var Indexer = class _Indexer {
|
|
|
12660
13653
|
const reparseCachedMetalFiles = database.getMetadata(metalParserMetadataKey) !== METAL_PARSER_VERSION;
|
|
12661
13654
|
const symbolExtractorMetadataKey = this.getSymbolExtractorVersionMetadataKey();
|
|
12662
13655
|
const refreshCachedSymbols = database.getMetadata(symbolExtractorMetadataKey) !== SYMBOL_EXTRACTOR_VERSION;
|
|
12663
|
-
if (reparseCachedSwiftFiles && Array.from(this.fileHashCache.keys()).some((filePath) =>
|
|
13656
|
+
if (reparseCachedSwiftFiles && Array.from(this.fileHashCache.keys()).some((filePath) => path20.extname(filePath).toLowerCase() === ".swift")) {
|
|
12664
13657
|
this.logger.info("Reindexing cached Swift files for parser support");
|
|
12665
13658
|
}
|
|
12666
|
-
if (reparseCachedMetalFiles && Array.from(this.fileHashCache.keys()).some((filePath) =>
|
|
13659
|
+
if (reparseCachedMetalFiles && Array.from(this.fileHashCache.keys()).some((filePath) => path20.extname(filePath).toLowerCase() === ".metal")) {
|
|
12667
13660
|
this.logger.info("Reindexing cached Metal files for parser support");
|
|
12668
13661
|
}
|
|
12669
13662
|
const includePatterns = [...this.config.include, ...this.config.additionalInclude];
|
|
@@ -12707,8 +13700,8 @@ var Indexer = class _Indexer {
|
|
|
12707
13700
|
const needsCallGraphRefresh = cachedHashMatches && needsCallGraphResolutionMigration && database.getChunksByFile(storedPath).some(
|
|
12708
13701
|
(chunk) => chunk.language === "php" || chunk.language === "c" || chunk.language === "cpp"
|
|
12709
13702
|
);
|
|
12710
|
-
const requiresSwiftParserUpgrade = reparseCachedSwiftFiles &&
|
|
12711
|
-
const requiresMetalParserUpgrade = reparseCachedMetalFiles &&
|
|
13703
|
+
const requiresSwiftParserUpgrade = reparseCachedSwiftFiles && path20.extname(storedPath).toLowerCase() === ".swift";
|
|
13704
|
+
const requiresMetalParserUpgrade = reparseCachedMetalFiles && path20.extname(storedPath).toLowerCase() === ".metal";
|
|
12712
13705
|
const inMigrationScope = forceScopedReembed && scopedRoots !== null && this.isFileInCurrentScope(storedPath, scopedRoots);
|
|
12713
13706
|
if (cachedHashMatches && !inMigrationScope && !needsCallGraphRefresh && !requiresSwiftParserUpgrade && !requiresMetalParserUpgrade && !refreshCachedSymbols) {
|
|
12714
13707
|
unchangedFilePaths.add(storedPath);
|
|
@@ -12767,7 +13760,7 @@ var Indexer = class _Indexer {
|
|
|
12767
13760
|
}
|
|
12768
13761
|
}
|
|
12769
13762
|
}
|
|
12770
|
-
const shouldRetryFailedPath = (filePath) => filePath !== null && currentFileHashes.has(filePath) && unchangedFilePaths.has(filePath);
|
|
13763
|
+
const shouldRetryFailedPath = (filePath) => filePath !== null && !this.isStoredPathExcluded(filePath) && currentFileHashes.has(filePath) && unchangedFilePaths.has(filePath);
|
|
12771
13764
|
const failedProcessing = this.prepareFailedBatchProcessing(scopedRoots, shouldRetryFailedPath);
|
|
12772
13765
|
const maxChunkTokens = getSafeEmbeddingChunkTokenLimit(configuredProviderInfo);
|
|
12773
13766
|
const providerRateLimits = this.getProviderRateLimits(configuredProviderInfo.provider);
|
|
@@ -12871,7 +13864,7 @@ var Indexer = class _Indexer {
|
|
|
12871
13864
|
throw new Error(`Parsed file was not present in its source batch: ${parsed.path}`);
|
|
12872
13865
|
}
|
|
12873
13866
|
if (parsed.chunks.length === 0) {
|
|
12874
|
-
stats.parseFailures.push(
|
|
13867
|
+
stats.parseFailures.push(path20.isAbsolute(parsed.path) ? path20.relative(this.projectRoot, parsed.path) : parsed.path);
|
|
12875
13868
|
}
|
|
12876
13869
|
let chunksToProcess = parsed.chunks;
|
|
12877
13870
|
if (this.config.indexing.fallbackToTextOnMaxChunks && chunksToProcess.length > this.config.indexing.maxChunksPerFile) {
|
|
@@ -13206,7 +14199,7 @@ var Indexer = class _Indexer {
|
|
|
13206
14199
|
previousBranchSymbolIds,
|
|
13207
14200
|
Array.from(allSymbolIds)
|
|
13208
14201
|
);
|
|
13209
|
-
const vectorPath =
|
|
14202
|
+
const vectorPath = path20.join(this.indexPath, "vectors");
|
|
13210
14203
|
const shouldFingerprintLegacyPair = !store.hasFingerprint() && (0, import_fs12.existsSync)(vectorPath) && (0, import_fs12.existsSync)(`${vectorPath}.meta.json`);
|
|
13211
14204
|
if (backfilledBlameMetadata || shouldFingerprintLegacyPair || removedStoredChunks) {
|
|
13212
14205
|
store.save();
|
|
@@ -14065,7 +15058,7 @@ var Indexer = class _Indexer {
|
|
|
14065
15058
|
gcOrphanSymbols: 0,
|
|
14066
15059
|
gcOrphanCallEdges: 0,
|
|
14067
15060
|
resetCorruptedIndex: true,
|
|
14068
|
-
warning: this.getCorruptedIndexWarning(
|
|
15061
|
+
warning: this.getCorruptedIndexWarning(path20.join(this.indexPath, "codebase.db"))
|
|
14069
15062
|
};
|
|
14070
15063
|
}
|
|
14071
15064
|
this.logger.recordGc(removedCount, gcOrphanChunks, gcOrphanEmbeddings);
|
|
@@ -14095,7 +15088,8 @@ var Indexer = class _Indexer {
|
|
|
14095
15088
|
const maxChunkTokens = getSafeEmbeddingChunkTokenLimit(configuredProviderInfo);
|
|
14096
15089
|
const providerRateLimits = this.getProviderRateLimits(configuredProviderInfo.provider);
|
|
14097
15090
|
const roots = this.config.scope === "global" ? this.getScopedRoots() : null;
|
|
14098
|
-
const
|
|
15091
|
+
const shouldProcessFailedPath = (filePath) => filePath === null || !this.isStoredPathExcluded(filePath);
|
|
15092
|
+
const failedProcessing = this.prepareFailedBatchProcessing(roots, shouldProcessFailedPath);
|
|
14099
15093
|
if (failedProcessing.latestById.size === 0) {
|
|
14100
15094
|
this.finalizeFailedBatchWriteState(failedProcessing.state);
|
|
14101
15095
|
return { succeeded: 0, failed: 0, remaining: 0 };
|
|
@@ -14108,7 +15102,7 @@ var Indexer = class _Indexer {
|
|
|
14108
15102
|
const retryableChunks = this.iterateLatestFailedChunks(
|
|
14109
15103
|
failedProcessing.latestById,
|
|
14110
15104
|
roots,
|
|
14111
|
-
|
|
15105
|
+
shouldProcessFailedPath,
|
|
14112
15106
|
maxChunkTokens
|
|
14113
15107
|
);
|
|
14114
15108
|
for (const retryBatch of iterateOrderedFileBatches(
|
|
@@ -14378,9 +15372,9 @@ var Indexer = class _Indexer {
|
|
|
14378
15372
|
this.requireReadableComponents(readIssues, "database");
|
|
14379
15373
|
let shortest = [];
|
|
14380
15374
|
for (const branchKey of this.getBranchCatalogKeys()) {
|
|
14381
|
-
const
|
|
14382
|
-
if (
|
|
14383
|
-
shortest =
|
|
15375
|
+
const path26 = database.findShortestPath(fromName, toName, branchKey, maxDepth);
|
|
15376
|
+
if (path26.length > 0 && (shortest.length === 0 || path26.length < shortest.length)) {
|
|
15377
|
+
shortest = path26;
|
|
14384
15378
|
}
|
|
14385
15379
|
}
|
|
14386
15380
|
return shortest.map((hop) => this.resolveFilePathRecord(hop));
|
|
@@ -14428,13 +15422,13 @@ var Indexer = class _Indexer {
|
|
|
14428
15422
|
}
|
|
14429
15423
|
}
|
|
14430
15424
|
if (!found) continue;
|
|
14431
|
-
const
|
|
15425
|
+
const path26 = [];
|
|
14432
15426
|
let currentSymbolId = toSymbolId;
|
|
14433
15427
|
while (true) {
|
|
14434
15428
|
const symbol = symbolsById.get(currentSymbolId);
|
|
14435
15429
|
if (!symbol) break;
|
|
14436
15430
|
const parent = parentBySymbolId.get(currentSymbolId);
|
|
14437
|
-
|
|
15431
|
+
path26.push({
|
|
14438
15432
|
symbolId: symbol.id,
|
|
14439
15433
|
symbolName: symbol.name,
|
|
14440
15434
|
filePath: symbol.filePath,
|
|
@@ -14444,9 +15438,9 @@ var Indexer = class _Indexer {
|
|
|
14444
15438
|
if (!parent) break;
|
|
14445
15439
|
currentSymbolId = parent.parentId;
|
|
14446
15440
|
}
|
|
14447
|
-
|
|
14448
|
-
if (
|
|
14449
|
-
shortest =
|
|
15441
|
+
path26.reverse();
|
|
15442
|
+
if (path26.length > 0 && (shortest.length === 0 || path26.length < shortest.length)) {
|
|
15443
|
+
shortest = path26;
|
|
14450
15444
|
}
|
|
14451
15445
|
}
|
|
14452
15446
|
return shortest.map((hop) => this.resolveFilePathRecord(hop));
|
|
@@ -14597,7 +15591,7 @@ var Indexer = class _Indexer {
|
|
|
14597
15591
|
);
|
|
14598
15592
|
}
|
|
14599
15593
|
}
|
|
14600
|
-
const toStoredChangedFiles = (filePaths) => filePaths.map((filePath) => this.toStoredFilePath(
|
|
15594
|
+
const toStoredChangedFiles = (filePaths) => filePaths.map((filePath) => this.toStoredFilePath(path20.resolve(this.projectRoot, filePath)));
|
|
14601
15595
|
const storedChangedFiles = toStoredChangedFiles(changedFiles);
|
|
14602
15596
|
const directSymbols = database.getSymbolsForFiles(storedChangedFiles, branchKey);
|
|
14603
15597
|
const directIds = directSymbols.map((s) => s.id);
|
|
@@ -14746,12 +15740,12 @@ var Indexer = class _Indexer {
|
|
|
14746
15740
|
if (meta.filePath) filePaths.add(meta.filePath);
|
|
14747
15741
|
}
|
|
14748
15742
|
const directory = options?.directory?.replace(/\/$/, "");
|
|
14749
|
-
const absoluteDirectoryFilter = directory ?
|
|
15743
|
+
const absoluteDirectoryFilter = directory ? path20.resolve(this.projectRoot, directory) : void 0;
|
|
14750
15744
|
for (const filePath of filePaths) {
|
|
14751
15745
|
if (directory) {
|
|
14752
15746
|
const absoluteFilePath = this.resolveStoredFilePath(filePath);
|
|
14753
15747
|
const matchesRelative = filePath === directory || filePath.startsWith(directory + "/");
|
|
14754
|
-
const matchesProjectRelative = absoluteDirectoryFilter !== void 0 && (absoluteFilePath === absoluteDirectoryFilter || absoluteFilePath.startsWith(absoluteDirectoryFilter +
|
|
15748
|
+
const matchesProjectRelative = absoluteDirectoryFilter !== void 0 && (absoluteFilePath === absoluteDirectoryFilter || absoluteFilePath.startsWith(absoluteDirectoryFilter + path20.sep));
|
|
14755
15749
|
if (!matchesRelative && !matchesProjectRelative) {
|
|
14756
15750
|
continue;
|
|
14757
15751
|
}
|
|
@@ -14868,7 +15862,10 @@ function getOrCreateIndexer(projectRoot3, host) {
|
|
|
14868
15862
|
}
|
|
14869
15863
|
const indexer = new Indexer(projectRoot3, config, host);
|
|
14870
15864
|
indexerCache.set(key, indexer);
|
|
14871
|
-
configureAutoIndex(projectRoot3, host, config, () => getOrCreateIndexer(projectRoot3, host)
|
|
15865
|
+
configureAutoIndex(projectRoot3, host, config, () => getOrCreateIndexer(projectRoot3, host), {
|
|
15866
|
+
preserveManagedWorker: true,
|
|
15867
|
+
synchronizeBackgroundWorker: false
|
|
15868
|
+
});
|
|
14872
15869
|
return indexer;
|
|
14873
15870
|
}
|
|
14874
15871
|
function getIndexerForProject(projectRoot3, host) {
|
|
@@ -14883,7 +15880,9 @@ function refreshIndexerForDirectory(projectRoot3, host, config = parseConfig(loa
|
|
|
14883
15880
|
const key = getIndexerCacheKey(projectRoot3, host);
|
|
14884
15881
|
configCache.set(key, config);
|
|
14885
15882
|
indexerCache.set(key, new Indexer(projectRoot3, config, host));
|
|
14886
|
-
configureAutoIndex(projectRoot3, host, config, () => getOrCreateIndexer(projectRoot3, host)
|
|
15883
|
+
configureAutoIndex(projectRoot3, host, config, () => getOrCreateIndexer(projectRoot3, host), {
|
|
15884
|
+
synchronizeBackgroundWorker: true
|
|
15885
|
+
});
|
|
14887
15886
|
return config;
|
|
14888
15887
|
}
|
|
14889
15888
|
var AutoIndexRetrievalUnavailableError = class extends Error {
|
|
@@ -14910,7 +15909,7 @@ function trimOrUndefined(value) {
|
|
|
14910
15909
|
return normalized || void 0;
|
|
14911
15910
|
}
|
|
14912
15911
|
function normalizeCallGraphPath(value) {
|
|
14913
|
-
let normalized =
|
|
15912
|
+
let normalized = path21.posix.normalize(value.trim().replaceAll("\\", "/"));
|
|
14914
15913
|
if (normalized.startsWith("./")) {
|
|
14915
15914
|
normalized = normalized.slice(2);
|
|
14916
15915
|
}
|
|
@@ -15103,12 +16102,12 @@ async function getCallGraphPath(projectRoot3, host, from, to, maxDepth, fromFile
|
|
|
15103
16102
|
if (fromResolution.status !== "resolved" || toResolution.status !== "resolved") {
|
|
15104
16103
|
return { from: fromResolution, to: toResolution, path: [] };
|
|
15105
16104
|
}
|
|
15106
|
-
const
|
|
16105
|
+
const path26 = await indexer.findCallPathBySymbolIds(
|
|
15107
16106
|
fromResolution.symbolId,
|
|
15108
16107
|
toResolution.symbolId,
|
|
15109
16108
|
maxDepth
|
|
15110
16109
|
);
|
|
15111
|
-
return { from: fromResolution, to: toResolution, path:
|
|
16110
|
+
return { from: fromResolution, to: toResolution, path: path26 };
|
|
15112
16111
|
}
|
|
15113
16112
|
async function runIndexCodebase(projectRoot3, host, args, onProgress) {
|
|
15114
16113
|
const root = getProjectRoot(projectRoot3, host);
|
|
@@ -15306,8 +16305,8 @@ async function getIndexLogs(projectRoot3, host, args) {
|
|
|
15306
16305
|
function addKnowledgeBase(projectRoot3, host, knowledgeBasePath) {
|
|
15307
16306
|
const root = getProjectRoot(projectRoot3, host);
|
|
15308
16307
|
const inputPath = knowledgeBasePath.trim();
|
|
15309
|
-
const normalizedPath2 =
|
|
15310
|
-
|
|
16308
|
+
const normalizedPath2 = path21.resolve(
|
|
16309
|
+
path21.isAbsolute(inputPath) ? inputPath : resolveKnowledgeBasePath(inputPath, root)
|
|
15311
16310
|
);
|
|
15312
16311
|
if (!(0, import_fs13.existsSync)(normalizedPath2)) {
|
|
15313
16312
|
return `Error: Directory does not exist: ${normalizedPath2}`;
|
|
@@ -15343,7 +16342,7 @@ function addKnowledgeBase(projectRoot3, host, knowledgeBasePath) {
|
|
|
15343
16342
|
}
|
|
15344
16343
|
}
|
|
15345
16344
|
for (const dotDir of sensitiveDotDirs) {
|
|
15346
|
-
const sensitiveDir =
|
|
16345
|
+
const sensitiveDir = path21.join(homeDir, dotDir);
|
|
15347
16346
|
if (sensitiveDir && (realPath === sensitiveDir || realPath.startsWith(`${sensitiveDir}/`))) {
|
|
15348
16347
|
return `Error: Adding sensitive directory as knowledge base is not allowed: ${normalizedPath2}`;
|
|
15349
16348
|
}
|
|
@@ -15406,7 +16405,7 @@ function listKnowledgeBases(projectRoot3, host) {
|
|
|
15406
16405
|
}
|
|
15407
16406
|
result += "\n";
|
|
15408
16407
|
}
|
|
15409
|
-
const hasHostConfig = (0, import_fs13.existsSync)(
|
|
16408
|
+
const hasHostConfig = (0, import_fs13.existsSync)(path21.join(root, getHostProjectConfigRelativePath(host)));
|
|
15410
16409
|
if (hasHostConfig) {
|
|
15411
16410
|
result += `
|
|
15412
16411
|
Config sources: 1 file(s).`;
|
|
@@ -15879,7 +16878,7 @@ async function resolveCodebaseContextUnmeasured(projectRoot3, host, input) {
|
|
|
15879
16878
|
const directory = input.directory ?? void 0;
|
|
15880
16879
|
const tokenBudget = input.tokenBudget ?? void 0;
|
|
15881
16880
|
if (from && to) {
|
|
15882
|
-
const
|
|
16881
|
+
const path26 = await getCallGraphPath(
|
|
15883
16882
|
projectRoot3,
|
|
15884
16883
|
host,
|
|
15885
16884
|
from,
|
|
@@ -15888,25 +16887,25 @@ async function resolveCodebaseContextUnmeasured(projectRoot3, host, input) {
|
|
|
15888
16887
|
fromFilePath,
|
|
15889
16888
|
toFilePath
|
|
15890
16889
|
);
|
|
15891
|
-
const pathText = formatCallGraphPathResult(
|
|
15892
|
-
if (
|
|
16890
|
+
const pathText = formatCallGraphPathResult(path26);
|
|
16891
|
+
if (path26.path.length > 0) {
|
|
15893
16892
|
const fitted2 = fitTextToContextBudget(
|
|
15894
16893
|
pathText,
|
|
15895
16894
|
tokenBudget
|
|
15896
16895
|
);
|
|
15897
16896
|
return {
|
|
15898
16897
|
text: fitted2.text,
|
|
15899
|
-
details: fittedDetails("path", fitted2,
|
|
16898
|
+
details: fittedDetails("path", fitted2, path26.path.length)
|
|
15900
16899
|
};
|
|
15901
16900
|
}
|
|
15902
|
-
if (
|
|
16901
|
+
if (path26.from.status !== "resolved" || path26.to.status !== "resolved") {
|
|
15903
16902
|
const fitted2 = fitTextToContextBudget(pathText, tokenBudget);
|
|
15904
16903
|
return {
|
|
15905
16904
|
text: fitted2.text,
|
|
15906
16905
|
details: fittedDetails("path", fitted2, 0)
|
|
15907
16906
|
};
|
|
15908
16907
|
}
|
|
15909
|
-
const resolvedFrom =
|
|
16908
|
+
const resolvedFrom = path26.from;
|
|
15910
16909
|
const { callers } = await getCallGraphData(projectRoot3, host, {
|
|
15911
16910
|
name: to,
|
|
15912
16911
|
direction: "callers",
|
|
@@ -16351,7 +17350,7 @@ var import_fs14 = require("fs");
|
|
|
16351
17350
|
|
|
16352
17351
|
// node_modules/chokidar/index.js
|
|
16353
17352
|
var import_node_events = require("events");
|
|
16354
|
-
var
|
|
17353
|
+
var import_node_fs3 = require("fs");
|
|
16355
17354
|
var import_promises3 = require("fs/promises");
|
|
16356
17355
|
var sp2 = __toESM(require("path"), 1);
|
|
16357
17356
|
|
|
@@ -16439,7 +17438,7 @@ var ReaddirpStream = class extends import_node_stream.Readable {
|
|
|
16439
17438
|
this._directoryFilter = normalizeFilter(opts.directoryFilter);
|
|
16440
17439
|
const statMethod = opts.lstat ? import_promises.lstat : import_promises.stat;
|
|
16441
17440
|
if (wantBigintFsStats) {
|
|
16442
|
-
this._stat = (
|
|
17441
|
+
this._stat = (path26) => statMethod(path26, { bigint: true });
|
|
16443
17442
|
} else {
|
|
16444
17443
|
this._stat = statMethod;
|
|
16445
17444
|
}
|
|
@@ -16464,8 +17463,8 @@ var ReaddirpStream = class extends import_node_stream.Readable {
|
|
|
16464
17463
|
const par = this.parent;
|
|
16465
17464
|
const fil = par && par.files;
|
|
16466
17465
|
if (fil && fil.length > 0) {
|
|
16467
|
-
const { path:
|
|
16468
|
-
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent,
|
|
17466
|
+
const { path: path26, depth } = par;
|
|
17467
|
+
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path26));
|
|
16469
17468
|
const awaited = await Promise.all(slice);
|
|
16470
17469
|
for (const entry of awaited) {
|
|
16471
17470
|
if (!entry)
|
|
@@ -16505,21 +17504,21 @@ var ReaddirpStream = class extends import_node_stream.Readable {
|
|
|
16505
17504
|
this.reading = false;
|
|
16506
17505
|
}
|
|
16507
17506
|
}
|
|
16508
|
-
async _exploreDir(
|
|
17507
|
+
async _exploreDir(path26, depth) {
|
|
16509
17508
|
let files;
|
|
16510
17509
|
try {
|
|
16511
|
-
files = await (0, import_promises.readdir)(
|
|
17510
|
+
files = await (0, import_promises.readdir)(path26, this._rdOptions);
|
|
16512
17511
|
} catch (error) {
|
|
16513
17512
|
this._onError(error);
|
|
16514
17513
|
}
|
|
16515
|
-
return { files, depth, path:
|
|
17514
|
+
return { files, depth, path: path26 };
|
|
16516
17515
|
}
|
|
16517
|
-
async _formatEntry(dirent,
|
|
17516
|
+
async _formatEntry(dirent, path26) {
|
|
16518
17517
|
let entry;
|
|
16519
|
-
const
|
|
17518
|
+
const basename8 = this._isDirent ? dirent.name : dirent;
|
|
16520
17519
|
try {
|
|
16521
|
-
const fullPath = (0, import_node_path.resolve)((0, import_node_path.join)(
|
|
16522
|
-
entry = { path: (0, import_node_path.relative)(this._root, fullPath), fullPath, basename:
|
|
17520
|
+
const fullPath = (0, import_node_path.resolve)((0, import_node_path.join)(path26, basename8));
|
|
17521
|
+
entry = { path: (0, import_node_path.relative)(this._root, fullPath), fullPath, basename: basename8 };
|
|
16523
17522
|
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
16524
17523
|
} catch (err) {
|
|
16525
17524
|
this._onError(err);
|
|
@@ -16589,7 +17588,7 @@ function readdirp(root, options = {}) {
|
|
|
16589
17588
|
}
|
|
16590
17589
|
|
|
16591
17590
|
// node_modules/chokidar/handler.js
|
|
16592
|
-
var
|
|
17591
|
+
var import_node_fs2 = require("fs");
|
|
16593
17592
|
var import_promises2 = require("fs/promises");
|
|
16594
17593
|
var import_node_os = require("os");
|
|
16595
17594
|
var sp = __toESM(require("path"), 1);
|
|
@@ -16918,16 +17917,16 @@ var delFromSet = (main, prop, item) => {
|
|
|
16918
17917
|
};
|
|
16919
17918
|
var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
|
|
16920
17919
|
var FsWatchInstances = /* @__PURE__ */ new Map();
|
|
16921
|
-
function createFsWatchInstance(
|
|
17920
|
+
function createFsWatchInstance(path26, options, listener, errHandler, emitRaw) {
|
|
16922
17921
|
const handleEvent = (rawEvent, evPath) => {
|
|
16923
|
-
listener(
|
|
16924
|
-
emitRaw(rawEvent, evPath, { watchedPath:
|
|
16925
|
-
if (evPath &&
|
|
16926
|
-
fsWatchBroadcast(sp.resolve(
|
|
17922
|
+
listener(path26);
|
|
17923
|
+
emitRaw(rawEvent, evPath, { watchedPath: path26 });
|
|
17924
|
+
if (evPath && path26 !== evPath) {
|
|
17925
|
+
fsWatchBroadcast(sp.resolve(path26, evPath), KEY_LISTENERS, sp.join(path26, evPath));
|
|
16927
17926
|
}
|
|
16928
17927
|
};
|
|
16929
17928
|
try {
|
|
16930
|
-
return (0,
|
|
17929
|
+
return (0, import_node_fs2.watch)(path26, {
|
|
16931
17930
|
persistent: options.persistent
|
|
16932
17931
|
}, handleEvent);
|
|
16933
17932
|
} catch (error) {
|
|
@@ -16943,12 +17942,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
|
|
|
16943
17942
|
listener(val1, val2, val3);
|
|
16944
17943
|
});
|
|
16945
17944
|
};
|
|
16946
|
-
var setFsWatchListener = (
|
|
17945
|
+
var setFsWatchListener = (path26, fullPath, options, handlers) => {
|
|
16947
17946
|
const { listener, errHandler, rawEmitter } = handlers;
|
|
16948
17947
|
let cont = FsWatchInstances.get(fullPath);
|
|
16949
17948
|
let watcher;
|
|
16950
17949
|
if (!options.persistent) {
|
|
16951
|
-
watcher = createFsWatchInstance(
|
|
17950
|
+
watcher = createFsWatchInstance(path26, options, listener, errHandler, rawEmitter);
|
|
16952
17951
|
if (!watcher)
|
|
16953
17952
|
return;
|
|
16954
17953
|
return watcher.close.bind(watcher);
|
|
@@ -16959,7 +17958,7 @@ var setFsWatchListener = (path25, fullPath, options, handlers) => {
|
|
|
16959
17958
|
addAndConvert(cont, KEY_RAW, rawEmitter);
|
|
16960
17959
|
} else {
|
|
16961
17960
|
watcher = createFsWatchInstance(
|
|
16962
|
-
|
|
17961
|
+
path26,
|
|
16963
17962
|
options,
|
|
16964
17963
|
fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
|
|
16965
17964
|
errHandler,
|
|
@@ -16974,7 +17973,7 @@ var setFsWatchListener = (path25, fullPath, options, handlers) => {
|
|
|
16974
17973
|
cont.watcherUnusable = true;
|
|
16975
17974
|
if (isWindows && error.code === "EPERM") {
|
|
16976
17975
|
try {
|
|
16977
|
-
const fd = await (0, import_promises2.open)(
|
|
17976
|
+
const fd = await (0, import_promises2.open)(path26, "r");
|
|
16978
17977
|
await fd.close();
|
|
16979
17978
|
broadcastErr(error);
|
|
16980
17979
|
} catch (err) {
|
|
@@ -17005,12 +18004,12 @@ var setFsWatchListener = (path25, fullPath, options, handlers) => {
|
|
|
17005
18004
|
};
|
|
17006
18005
|
};
|
|
17007
18006
|
var FsWatchFileInstances = /* @__PURE__ */ new Map();
|
|
17008
|
-
var setFsWatchFileListener = (
|
|
18007
|
+
var setFsWatchFileListener = (path26, fullPath, options, handlers) => {
|
|
17009
18008
|
const { listener, rawEmitter } = handlers;
|
|
17010
18009
|
let cont = FsWatchFileInstances.get(fullPath);
|
|
17011
18010
|
const copts = cont && cont.options;
|
|
17012
18011
|
if (copts && (copts.persistent < options.persistent || copts.interval > options.interval)) {
|
|
17013
|
-
(0,
|
|
18012
|
+
(0, import_node_fs2.unwatchFile)(fullPath);
|
|
17014
18013
|
cont = void 0;
|
|
17015
18014
|
}
|
|
17016
18015
|
if (cont) {
|
|
@@ -17021,13 +18020,13 @@ var setFsWatchFileListener = (path25, fullPath, options, handlers) => {
|
|
|
17021
18020
|
listeners: listener,
|
|
17022
18021
|
rawEmitters: rawEmitter,
|
|
17023
18022
|
options,
|
|
17024
|
-
watcher: (0,
|
|
18023
|
+
watcher: (0, import_node_fs2.watchFile)(fullPath, options, (curr, prev) => {
|
|
17025
18024
|
foreach(cont.rawEmitters, (rawEmitter2) => {
|
|
17026
18025
|
rawEmitter2(EV.CHANGE, fullPath, { curr, prev });
|
|
17027
18026
|
});
|
|
17028
18027
|
const currmtime = curr.mtimeMs;
|
|
17029
18028
|
if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
|
|
17030
|
-
foreach(cont.listeners, (listener2) => listener2(
|
|
18029
|
+
foreach(cont.listeners, (listener2) => listener2(path26, curr));
|
|
17031
18030
|
}
|
|
17032
18031
|
})
|
|
17033
18032
|
};
|
|
@@ -17038,7 +18037,7 @@ var setFsWatchFileListener = (path25, fullPath, options, handlers) => {
|
|
|
17038
18037
|
delFromSet(cont, KEY_RAW, rawEmitter);
|
|
17039
18038
|
if (isEmptySet(cont.listeners)) {
|
|
17040
18039
|
FsWatchFileInstances.delete(fullPath);
|
|
17041
|
-
(0,
|
|
18040
|
+
(0, import_node_fs2.unwatchFile)(fullPath);
|
|
17042
18041
|
cont.options = cont.watcher = void 0;
|
|
17043
18042
|
Object.freeze(cont);
|
|
17044
18043
|
}
|
|
@@ -17057,13 +18056,13 @@ var NodeFsHandler = class {
|
|
|
17057
18056
|
* @param listener on fs change
|
|
17058
18057
|
* @returns closer for the watcher instance
|
|
17059
18058
|
*/
|
|
17060
|
-
_watchWithNodeFs(
|
|
18059
|
+
_watchWithNodeFs(path26, listener) {
|
|
17061
18060
|
const opts = this.fsw.options;
|
|
17062
|
-
const directory = sp.dirname(
|
|
17063
|
-
const
|
|
18061
|
+
const directory = sp.dirname(path26);
|
|
18062
|
+
const basename8 = sp.basename(path26);
|
|
17064
18063
|
const parent = this.fsw._getWatchedDir(directory);
|
|
17065
|
-
parent.add(
|
|
17066
|
-
const absolutePath = sp.resolve(
|
|
18064
|
+
parent.add(basename8);
|
|
18065
|
+
const absolutePath = sp.resolve(path26);
|
|
17067
18066
|
const options = {
|
|
17068
18067
|
persistent: opts.persistent
|
|
17069
18068
|
};
|
|
@@ -17072,13 +18071,13 @@ var NodeFsHandler = class {
|
|
|
17072
18071
|
let closer;
|
|
17073
18072
|
if (opts.usePolling) {
|
|
17074
18073
|
const enableBin = opts.interval !== opts.binaryInterval;
|
|
17075
|
-
options.interval = enableBin && isBinaryPath(
|
|
17076
|
-
closer = setFsWatchFileListener(
|
|
18074
|
+
options.interval = enableBin && isBinaryPath(basename8) ? opts.binaryInterval : opts.interval;
|
|
18075
|
+
closer = setFsWatchFileListener(path26, absolutePath, options, {
|
|
17077
18076
|
listener,
|
|
17078
18077
|
rawEmitter: this.fsw._emitRaw
|
|
17079
18078
|
});
|
|
17080
18079
|
} else {
|
|
17081
|
-
closer = setFsWatchListener(
|
|
18080
|
+
closer = setFsWatchListener(path26, absolutePath, options, {
|
|
17082
18081
|
listener,
|
|
17083
18082
|
errHandler: this._boundHandleError,
|
|
17084
18083
|
rawEmitter: this.fsw._emitRaw
|
|
@@ -17094,13 +18093,13 @@ var NodeFsHandler = class {
|
|
|
17094
18093
|
if (this.fsw.closed) {
|
|
17095
18094
|
return;
|
|
17096
18095
|
}
|
|
17097
|
-
const
|
|
17098
|
-
const
|
|
17099
|
-
const parent = this.fsw._getWatchedDir(
|
|
18096
|
+
const dirname14 = sp.dirname(file);
|
|
18097
|
+
const basename8 = sp.basename(file);
|
|
18098
|
+
const parent = this.fsw._getWatchedDir(dirname14);
|
|
17100
18099
|
let prevStats = stats;
|
|
17101
|
-
if (parent.has(
|
|
18100
|
+
if (parent.has(basename8))
|
|
17102
18101
|
return;
|
|
17103
|
-
const listener = async (
|
|
18102
|
+
const listener = async (path26, newStats) => {
|
|
17104
18103
|
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
|
|
17105
18104
|
return;
|
|
17106
18105
|
if (!newStats || newStats.mtimeMs === 0) {
|
|
@@ -17114,18 +18113,18 @@ var NodeFsHandler = class {
|
|
|
17114
18113
|
this.fsw._emit(EV.CHANGE, file, newStats2);
|
|
17115
18114
|
}
|
|
17116
18115
|
if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
|
|
17117
|
-
this.fsw._closeFile(
|
|
18116
|
+
this.fsw._closeFile(path26);
|
|
17118
18117
|
prevStats = newStats2;
|
|
17119
18118
|
const closer2 = this._watchWithNodeFs(file, listener);
|
|
17120
18119
|
if (closer2)
|
|
17121
|
-
this.fsw._addPathCloser(
|
|
18120
|
+
this.fsw._addPathCloser(path26, closer2);
|
|
17122
18121
|
} else {
|
|
17123
18122
|
prevStats = newStats2;
|
|
17124
18123
|
}
|
|
17125
18124
|
} catch (error) {
|
|
17126
|
-
this.fsw._remove(
|
|
18125
|
+
this.fsw._remove(dirname14, basename8);
|
|
17127
18126
|
}
|
|
17128
|
-
} else if (parent.has(
|
|
18127
|
+
} else if (parent.has(basename8)) {
|
|
17129
18128
|
const at = newStats.atimeMs;
|
|
17130
18129
|
const mt = newStats.mtimeMs;
|
|
17131
18130
|
if (!at || at <= mt || mt !== prevStats.mtimeMs) {
|
|
@@ -17150,7 +18149,7 @@ var NodeFsHandler = class {
|
|
|
17150
18149
|
* @param item basename of this item
|
|
17151
18150
|
* @returns true if no more processing is needed for this entry.
|
|
17152
18151
|
*/
|
|
17153
|
-
async _handleSymlink(entry, directory,
|
|
18152
|
+
async _handleSymlink(entry, directory, path26, item) {
|
|
17154
18153
|
if (this.fsw.closed) {
|
|
17155
18154
|
return;
|
|
17156
18155
|
}
|
|
@@ -17160,7 +18159,7 @@ var NodeFsHandler = class {
|
|
|
17160
18159
|
this.fsw._incrReadyCount();
|
|
17161
18160
|
let linkPath;
|
|
17162
18161
|
try {
|
|
17163
|
-
linkPath = await (0, import_promises2.realpath)(
|
|
18162
|
+
linkPath = await (0, import_promises2.realpath)(path26);
|
|
17164
18163
|
} catch (e) {
|
|
17165
18164
|
this.fsw._emitReady();
|
|
17166
18165
|
return true;
|
|
@@ -17170,12 +18169,12 @@ var NodeFsHandler = class {
|
|
|
17170
18169
|
if (dir.has(item)) {
|
|
17171
18170
|
if (this.fsw._symlinkPaths.get(full) !== linkPath) {
|
|
17172
18171
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
17173
|
-
this.fsw._emit(EV.CHANGE,
|
|
18172
|
+
this.fsw._emit(EV.CHANGE, path26, entry.stats);
|
|
17174
18173
|
}
|
|
17175
18174
|
} else {
|
|
17176
18175
|
dir.add(item);
|
|
17177
18176
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
17178
|
-
this.fsw._emit(EV.ADD,
|
|
18177
|
+
this.fsw._emit(EV.ADD, path26, entry.stats);
|
|
17179
18178
|
}
|
|
17180
18179
|
this.fsw._emitReady();
|
|
17181
18180
|
return true;
|
|
@@ -17205,9 +18204,9 @@ var NodeFsHandler = class {
|
|
|
17205
18204
|
return;
|
|
17206
18205
|
}
|
|
17207
18206
|
const item = entry.path;
|
|
17208
|
-
let
|
|
18207
|
+
let path26 = sp.join(directory, item);
|
|
17209
18208
|
current.add(item);
|
|
17210
|
-
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory,
|
|
18209
|
+
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path26, item)) {
|
|
17211
18210
|
return;
|
|
17212
18211
|
}
|
|
17213
18212
|
if (this.fsw.closed) {
|
|
@@ -17216,11 +18215,11 @@ var NodeFsHandler = class {
|
|
|
17216
18215
|
}
|
|
17217
18216
|
if (item === target || !target && !previous.has(item)) {
|
|
17218
18217
|
this.fsw._incrReadyCount();
|
|
17219
|
-
|
|
17220
|
-
this._addToNodeFs(
|
|
18218
|
+
path26 = sp.join(dir, sp.relative(dir, path26));
|
|
18219
|
+
this._addToNodeFs(path26, initialAdd, wh, depth + 1);
|
|
17221
18220
|
}
|
|
17222
18221
|
}).on(EV.ERROR, this._boundHandleError);
|
|
17223
|
-
return new Promise((
|
|
18222
|
+
return new Promise((resolve18, reject) => {
|
|
17224
18223
|
if (!stream)
|
|
17225
18224
|
return reject();
|
|
17226
18225
|
stream.once(STR_END, () => {
|
|
@@ -17229,7 +18228,7 @@ var NodeFsHandler = class {
|
|
|
17229
18228
|
return;
|
|
17230
18229
|
}
|
|
17231
18230
|
const wasThrottled = throttler ? throttler.clear() : false;
|
|
17232
|
-
|
|
18231
|
+
resolve18(void 0);
|
|
17233
18232
|
previous.getChildren().filter((item) => {
|
|
17234
18233
|
return item !== directory && !current.has(item);
|
|
17235
18234
|
}).forEach((item) => {
|
|
@@ -17286,13 +18285,13 @@ var NodeFsHandler = class {
|
|
|
17286
18285
|
* @param depth Child path actually targeted for watch
|
|
17287
18286
|
* @param target Child path actually targeted for watch
|
|
17288
18287
|
*/
|
|
17289
|
-
async _addToNodeFs(
|
|
18288
|
+
async _addToNodeFs(path26, initialAdd, priorWh, depth, target) {
|
|
17290
18289
|
const ready = this.fsw._emitReady;
|
|
17291
|
-
if (this.fsw._isIgnored(
|
|
18290
|
+
if (this.fsw._isIgnored(path26) || this.fsw.closed) {
|
|
17292
18291
|
ready();
|
|
17293
18292
|
return false;
|
|
17294
18293
|
}
|
|
17295
|
-
const wh = this.fsw._getWatchHelpers(
|
|
18294
|
+
const wh = this.fsw._getWatchHelpers(path26);
|
|
17296
18295
|
if (priorWh) {
|
|
17297
18296
|
wh.filterPath = (entry) => priorWh.filterPath(entry);
|
|
17298
18297
|
wh.filterDir = (entry) => priorWh.filterDir(entry);
|
|
@@ -17308,8 +18307,8 @@ var NodeFsHandler = class {
|
|
|
17308
18307
|
const follow = this.fsw.options.followSymlinks;
|
|
17309
18308
|
let closer;
|
|
17310
18309
|
if (stats.isDirectory()) {
|
|
17311
|
-
const absPath = sp.resolve(
|
|
17312
|
-
const targetPath = follow ? await (0, import_promises2.realpath)(
|
|
18310
|
+
const absPath = sp.resolve(path26);
|
|
18311
|
+
const targetPath = follow ? await (0, import_promises2.realpath)(path26) : path26;
|
|
17313
18312
|
if (this.fsw.closed)
|
|
17314
18313
|
return;
|
|
17315
18314
|
closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
|
|
@@ -17319,29 +18318,29 @@ var NodeFsHandler = class {
|
|
|
17319
18318
|
this.fsw._symlinkPaths.set(absPath, targetPath);
|
|
17320
18319
|
}
|
|
17321
18320
|
} else if (stats.isSymbolicLink()) {
|
|
17322
|
-
const targetPath = follow ? await (0, import_promises2.realpath)(
|
|
18321
|
+
const targetPath = follow ? await (0, import_promises2.realpath)(path26) : path26;
|
|
17323
18322
|
if (this.fsw.closed)
|
|
17324
18323
|
return;
|
|
17325
18324
|
const parent = sp.dirname(wh.watchPath);
|
|
17326
18325
|
this.fsw._getWatchedDir(parent).add(wh.watchPath);
|
|
17327
18326
|
this.fsw._emit(EV.ADD, wh.watchPath, stats);
|
|
17328
|
-
closer = await this._handleDir(parent, stats, initialAdd, depth,
|
|
18327
|
+
closer = await this._handleDir(parent, stats, initialAdd, depth, path26, wh, targetPath);
|
|
17329
18328
|
if (this.fsw.closed)
|
|
17330
18329
|
return;
|
|
17331
18330
|
if (targetPath !== void 0) {
|
|
17332
|
-
this.fsw._symlinkPaths.set(sp.resolve(
|
|
18331
|
+
this.fsw._symlinkPaths.set(sp.resolve(path26), targetPath);
|
|
17333
18332
|
}
|
|
17334
18333
|
} else {
|
|
17335
18334
|
closer = this._handleFile(wh.watchPath, stats, initialAdd);
|
|
17336
18335
|
}
|
|
17337
18336
|
ready();
|
|
17338
18337
|
if (closer)
|
|
17339
|
-
this.fsw._addPathCloser(
|
|
18338
|
+
this.fsw._addPathCloser(path26, closer);
|
|
17340
18339
|
return false;
|
|
17341
18340
|
} catch (error) {
|
|
17342
18341
|
if (this.fsw._handleError(error)) {
|
|
17343
18342
|
ready();
|
|
17344
|
-
return
|
|
18343
|
+
return path26;
|
|
17345
18344
|
}
|
|
17346
18345
|
}
|
|
17347
18346
|
}
|
|
@@ -17384,24 +18383,24 @@ function createPattern(matcher) {
|
|
|
17384
18383
|
}
|
|
17385
18384
|
return () => false;
|
|
17386
18385
|
}
|
|
17387
|
-
function normalizePath2(
|
|
17388
|
-
if (typeof
|
|
18386
|
+
function normalizePath2(path26) {
|
|
18387
|
+
if (typeof path26 !== "string")
|
|
17389
18388
|
throw new Error("string expected");
|
|
17390
|
-
|
|
17391
|
-
|
|
18389
|
+
path26 = sp2.normalize(path26);
|
|
18390
|
+
path26 = path26.replace(/\\/g, "/");
|
|
17392
18391
|
let prepend = false;
|
|
17393
|
-
if (
|
|
18392
|
+
if (path26.startsWith("//"))
|
|
17394
18393
|
prepend = true;
|
|
17395
|
-
|
|
18394
|
+
path26 = path26.replace(DOUBLE_SLASH_RE, "/");
|
|
17396
18395
|
if (prepend)
|
|
17397
|
-
|
|
17398
|
-
return
|
|
18396
|
+
path26 = "/" + path26;
|
|
18397
|
+
return path26;
|
|
17399
18398
|
}
|
|
17400
18399
|
function matchPatterns(patterns, testString, stats) {
|
|
17401
|
-
const
|
|
18400
|
+
const path26 = normalizePath2(testString);
|
|
17402
18401
|
for (let index = 0; index < patterns.length; index++) {
|
|
17403
18402
|
const pattern = patterns[index];
|
|
17404
|
-
if (pattern(
|
|
18403
|
+
if (pattern(path26, stats)) {
|
|
17405
18404
|
return true;
|
|
17406
18405
|
}
|
|
17407
18406
|
}
|
|
@@ -17439,19 +18438,19 @@ var toUnix = (string) => {
|
|
|
17439
18438
|
}
|
|
17440
18439
|
return str;
|
|
17441
18440
|
};
|
|
17442
|
-
var normalizePathToUnix = (
|
|
17443
|
-
var normalizeIgnored = (cwd = "") => (
|
|
17444
|
-
if (typeof
|
|
17445
|
-
return normalizePathToUnix(sp2.isAbsolute(
|
|
18441
|
+
var normalizePathToUnix = (path26) => toUnix(sp2.normalize(toUnix(path26)));
|
|
18442
|
+
var normalizeIgnored = (cwd = "") => (path26) => {
|
|
18443
|
+
if (typeof path26 === "string") {
|
|
18444
|
+
return normalizePathToUnix(sp2.isAbsolute(path26) ? path26 : sp2.join(cwd, path26));
|
|
17446
18445
|
} else {
|
|
17447
|
-
return
|
|
18446
|
+
return path26;
|
|
17448
18447
|
}
|
|
17449
18448
|
};
|
|
17450
|
-
var getAbsolutePath = (
|
|
17451
|
-
if (sp2.isAbsolute(
|
|
17452
|
-
return
|
|
18449
|
+
var getAbsolutePath = (path26, cwd) => {
|
|
18450
|
+
if (sp2.isAbsolute(path26)) {
|
|
18451
|
+
return path26;
|
|
17453
18452
|
}
|
|
17454
|
-
return sp2.join(cwd,
|
|
18453
|
+
return sp2.join(cwd, path26);
|
|
17455
18454
|
};
|
|
17456
18455
|
var EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
|
|
17457
18456
|
var DirEntry = class {
|
|
@@ -17516,10 +18515,10 @@ var WatchHelper = class {
|
|
|
17516
18515
|
dirParts;
|
|
17517
18516
|
followSymlinks;
|
|
17518
18517
|
statMethod;
|
|
17519
|
-
constructor(
|
|
18518
|
+
constructor(path26, follow, fsw) {
|
|
17520
18519
|
this.fsw = fsw;
|
|
17521
|
-
const watchPath =
|
|
17522
|
-
this.path =
|
|
18520
|
+
const watchPath = path26;
|
|
18521
|
+
this.path = path26 = path26.replace(REPLACER_RE, "");
|
|
17523
18522
|
this.watchPath = watchPath;
|
|
17524
18523
|
this.fullWatchPath = sp2.resolve(watchPath);
|
|
17525
18524
|
this.dirParts = [];
|
|
@@ -17659,20 +18658,20 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
17659
18658
|
this._closePromise = void 0;
|
|
17660
18659
|
let paths = unifyPaths(paths_);
|
|
17661
18660
|
if (cwd) {
|
|
17662
|
-
paths = paths.map((
|
|
17663
|
-
const absPath = getAbsolutePath(
|
|
18661
|
+
paths = paths.map((path26) => {
|
|
18662
|
+
const absPath = getAbsolutePath(path26, cwd);
|
|
17664
18663
|
return absPath;
|
|
17665
18664
|
});
|
|
17666
18665
|
}
|
|
17667
|
-
paths.forEach((
|
|
17668
|
-
this._removeIgnoredPath(
|
|
18666
|
+
paths.forEach((path26) => {
|
|
18667
|
+
this._removeIgnoredPath(path26);
|
|
17669
18668
|
});
|
|
17670
18669
|
this._userIgnored = void 0;
|
|
17671
18670
|
if (!this._readyCount)
|
|
17672
18671
|
this._readyCount = 0;
|
|
17673
18672
|
this._readyCount += paths.length;
|
|
17674
|
-
Promise.all(paths.map(async (
|
|
17675
|
-
const res = await this._nodeFsHandler._addToNodeFs(
|
|
18673
|
+
Promise.all(paths.map(async (path26) => {
|
|
18674
|
+
const res = await this._nodeFsHandler._addToNodeFs(path26, !_internal, void 0, 0, _origAdd);
|
|
17676
18675
|
if (res)
|
|
17677
18676
|
this._emitReady();
|
|
17678
18677
|
return res;
|
|
@@ -17694,17 +18693,17 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
17694
18693
|
return this;
|
|
17695
18694
|
const paths = unifyPaths(paths_);
|
|
17696
18695
|
const { cwd } = this.options;
|
|
17697
|
-
paths.forEach((
|
|
17698
|
-
if (!sp2.isAbsolute(
|
|
18696
|
+
paths.forEach((path26) => {
|
|
18697
|
+
if (!sp2.isAbsolute(path26) && !this._closers.has(path26)) {
|
|
17699
18698
|
if (cwd)
|
|
17700
|
-
|
|
17701
|
-
|
|
18699
|
+
path26 = sp2.join(cwd, path26);
|
|
18700
|
+
path26 = sp2.resolve(path26);
|
|
17702
18701
|
}
|
|
17703
|
-
this._closePath(
|
|
17704
|
-
this._addIgnoredPath(
|
|
17705
|
-
if (this._watched.has(
|
|
18702
|
+
this._closePath(path26);
|
|
18703
|
+
this._addIgnoredPath(path26);
|
|
18704
|
+
if (this._watched.has(path26)) {
|
|
17706
18705
|
this._addIgnoredPath({
|
|
17707
|
-
path:
|
|
18706
|
+
path: path26,
|
|
17708
18707
|
recursive: true
|
|
17709
18708
|
});
|
|
17710
18709
|
}
|
|
@@ -17768,38 +18767,38 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
17768
18767
|
* @param stats arguments to be passed with event
|
|
17769
18768
|
* @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
|
|
17770
18769
|
*/
|
|
17771
|
-
async _emit(event,
|
|
18770
|
+
async _emit(event, path26, stats) {
|
|
17772
18771
|
if (this.closed)
|
|
17773
18772
|
return;
|
|
17774
18773
|
const opts = this.options;
|
|
17775
18774
|
if (isWindows)
|
|
17776
|
-
|
|
18775
|
+
path26 = sp2.normalize(path26);
|
|
17777
18776
|
if (opts.cwd)
|
|
17778
|
-
|
|
17779
|
-
const args = [
|
|
18777
|
+
path26 = sp2.relative(opts.cwd, path26);
|
|
18778
|
+
const args = [path26];
|
|
17780
18779
|
if (stats != null)
|
|
17781
18780
|
args.push(stats);
|
|
17782
18781
|
const awf = opts.awaitWriteFinish;
|
|
17783
18782
|
let pw;
|
|
17784
|
-
if (awf && (pw = this._pendingWrites.get(
|
|
18783
|
+
if (awf && (pw = this._pendingWrites.get(path26))) {
|
|
17785
18784
|
pw.lastChange = /* @__PURE__ */ new Date();
|
|
17786
18785
|
return this;
|
|
17787
18786
|
}
|
|
17788
18787
|
if (opts.atomic) {
|
|
17789
18788
|
if (event === EVENTS.UNLINK) {
|
|
17790
|
-
this._pendingUnlinks.set(
|
|
18789
|
+
this._pendingUnlinks.set(path26, [event, ...args]);
|
|
17791
18790
|
setTimeout(() => {
|
|
17792
|
-
this._pendingUnlinks.forEach((entry,
|
|
18791
|
+
this._pendingUnlinks.forEach((entry, path27) => {
|
|
17793
18792
|
this.emit(...entry);
|
|
17794
18793
|
this.emit(EVENTS.ALL, ...entry);
|
|
17795
|
-
this._pendingUnlinks.delete(
|
|
18794
|
+
this._pendingUnlinks.delete(path27);
|
|
17796
18795
|
});
|
|
17797
18796
|
}, typeof opts.atomic === "number" ? opts.atomic : 100);
|
|
17798
18797
|
return this;
|
|
17799
18798
|
}
|
|
17800
|
-
if (event === EVENTS.ADD && this._pendingUnlinks.has(
|
|
18799
|
+
if (event === EVENTS.ADD && this._pendingUnlinks.has(path26)) {
|
|
17801
18800
|
event = EVENTS.CHANGE;
|
|
17802
|
-
this._pendingUnlinks.delete(
|
|
18801
|
+
this._pendingUnlinks.delete(path26);
|
|
17803
18802
|
}
|
|
17804
18803
|
}
|
|
17805
18804
|
if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
|
|
@@ -17817,16 +18816,16 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
17817
18816
|
this.emitWithAll(event, args);
|
|
17818
18817
|
}
|
|
17819
18818
|
};
|
|
17820
|
-
this._awaitWriteFinish(
|
|
18819
|
+
this._awaitWriteFinish(path26, awf.stabilityThreshold, event, awfEmit);
|
|
17821
18820
|
return this;
|
|
17822
18821
|
}
|
|
17823
18822
|
if (event === EVENTS.CHANGE) {
|
|
17824
|
-
const isThrottled = !this._throttle(EVENTS.CHANGE,
|
|
18823
|
+
const isThrottled = !this._throttle(EVENTS.CHANGE, path26, 50);
|
|
17825
18824
|
if (isThrottled)
|
|
17826
18825
|
return this;
|
|
17827
18826
|
}
|
|
17828
18827
|
if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
|
|
17829
|
-
const fullPath = opts.cwd ? sp2.join(opts.cwd,
|
|
18828
|
+
const fullPath = opts.cwd ? sp2.join(opts.cwd, path26) : path26;
|
|
17830
18829
|
let stats2;
|
|
17831
18830
|
try {
|
|
17832
18831
|
stats2 = await (0, import_promises3.stat)(fullPath);
|
|
@@ -17857,23 +18856,23 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
17857
18856
|
* @param timeout duration of time to suppress duplicate actions
|
|
17858
18857
|
* @returns tracking object or false if action should be suppressed
|
|
17859
18858
|
*/
|
|
17860
|
-
_throttle(actionType,
|
|
18859
|
+
_throttle(actionType, path26, timeout) {
|
|
17861
18860
|
if (!this._throttled.has(actionType)) {
|
|
17862
18861
|
this._throttled.set(actionType, /* @__PURE__ */ new Map());
|
|
17863
18862
|
}
|
|
17864
18863
|
const action = this._throttled.get(actionType);
|
|
17865
18864
|
if (!action)
|
|
17866
18865
|
throw new Error("invalid throttle");
|
|
17867
|
-
const actionPath = action.get(
|
|
18866
|
+
const actionPath = action.get(path26);
|
|
17868
18867
|
if (actionPath) {
|
|
17869
18868
|
actionPath.count++;
|
|
17870
18869
|
return false;
|
|
17871
18870
|
}
|
|
17872
18871
|
let timeoutObject;
|
|
17873
18872
|
const clear = () => {
|
|
17874
|
-
const item = action.get(
|
|
18873
|
+
const item = action.get(path26);
|
|
17875
18874
|
const count = item ? item.count : 0;
|
|
17876
|
-
action.delete(
|
|
18875
|
+
action.delete(path26);
|
|
17877
18876
|
clearTimeout(timeoutObject);
|
|
17878
18877
|
if (item)
|
|
17879
18878
|
clearTimeout(item.timeoutObject);
|
|
@@ -17881,7 +18880,7 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
17881
18880
|
};
|
|
17882
18881
|
timeoutObject = setTimeout(clear, timeout);
|
|
17883
18882
|
const thr = { timeoutObject, clear, count: 0 };
|
|
17884
|
-
action.set(
|
|
18883
|
+
action.set(path26, thr);
|
|
17885
18884
|
return thr;
|
|
17886
18885
|
}
|
|
17887
18886
|
_incrReadyCount() {
|
|
@@ -17895,44 +18894,44 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
17895
18894
|
* @param event
|
|
17896
18895
|
* @param awfEmit Callback to be called when ready for event to be emitted.
|
|
17897
18896
|
*/
|
|
17898
|
-
_awaitWriteFinish(
|
|
18897
|
+
_awaitWriteFinish(path26, threshold, event, awfEmit) {
|
|
17899
18898
|
const awf = this.options.awaitWriteFinish;
|
|
17900
18899
|
if (typeof awf !== "object")
|
|
17901
18900
|
return;
|
|
17902
18901
|
const pollInterval = awf.pollInterval;
|
|
17903
18902
|
let timeoutHandler;
|
|
17904
|
-
let fullPath =
|
|
17905
|
-
if (this.options.cwd && !sp2.isAbsolute(
|
|
17906
|
-
fullPath = sp2.join(this.options.cwd,
|
|
18903
|
+
let fullPath = path26;
|
|
18904
|
+
if (this.options.cwd && !sp2.isAbsolute(path26)) {
|
|
18905
|
+
fullPath = sp2.join(this.options.cwd, path26);
|
|
17907
18906
|
}
|
|
17908
18907
|
const now2 = /* @__PURE__ */ new Date();
|
|
17909
18908
|
const writes = this._pendingWrites;
|
|
17910
18909
|
function awaitWriteFinishFn(prevStat) {
|
|
17911
|
-
(0,
|
|
17912
|
-
if (err || !writes.has(
|
|
18910
|
+
(0, import_node_fs3.stat)(fullPath, (err, curStat) => {
|
|
18911
|
+
if (err || !writes.has(path26)) {
|
|
17913
18912
|
if (err && err.code !== "ENOENT")
|
|
17914
18913
|
awfEmit(err);
|
|
17915
18914
|
return;
|
|
17916
18915
|
}
|
|
17917
18916
|
const now3 = Number(/* @__PURE__ */ new Date());
|
|
17918
18917
|
if (prevStat && curStat.size !== prevStat.size) {
|
|
17919
|
-
writes.get(
|
|
18918
|
+
writes.get(path26).lastChange = now3;
|
|
17920
18919
|
}
|
|
17921
|
-
const pw = writes.get(
|
|
18920
|
+
const pw = writes.get(path26);
|
|
17922
18921
|
const df = now3 - pw.lastChange;
|
|
17923
18922
|
if (df >= threshold) {
|
|
17924
|
-
writes.delete(
|
|
18923
|
+
writes.delete(path26);
|
|
17925
18924
|
awfEmit(void 0, curStat);
|
|
17926
18925
|
} else {
|
|
17927
18926
|
timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
|
|
17928
18927
|
}
|
|
17929
18928
|
});
|
|
17930
18929
|
}
|
|
17931
|
-
if (!writes.has(
|
|
17932
|
-
writes.set(
|
|
18930
|
+
if (!writes.has(path26)) {
|
|
18931
|
+
writes.set(path26, {
|
|
17933
18932
|
lastChange: now2,
|
|
17934
18933
|
cancelWait: () => {
|
|
17935
|
-
writes.delete(
|
|
18934
|
+
writes.delete(path26);
|
|
17936
18935
|
clearTimeout(timeoutHandler);
|
|
17937
18936
|
return event;
|
|
17938
18937
|
}
|
|
@@ -17943,8 +18942,8 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
17943
18942
|
/**
|
|
17944
18943
|
* Determines whether user has asked to ignore this path.
|
|
17945
18944
|
*/
|
|
17946
|
-
_isIgnored(
|
|
17947
|
-
if (this.options.atomic && DOT_RE.test(
|
|
18945
|
+
_isIgnored(path26, stats) {
|
|
18946
|
+
if (this.options.atomic && DOT_RE.test(path26))
|
|
17948
18947
|
return true;
|
|
17949
18948
|
if (!this._userIgnored) {
|
|
17950
18949
|
const { cwd } = this.options;
|
|
@@ -17954,17 +18953,17 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
17954
18953
|
const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
|
|
17955
18954
|
this._userIgnored = anymatch(list, void 0);
|
|
17956
18955
|
}
|
|
17957
|
-
return this._userIgnored(
|
|
18956
|
+
return this._userIgnored(path26, stats);
|
|
17958
18957
|
}
|
|
17959
|
-
_isntIgnored(
|
|
17960
|
-
return !this._isIgnored(
|
|
18958
|
+
_isntIgnored(path26, stat5) {
|
|
18959
|
+
return !this._isIgnored(path26, stat5);
|
|
17961
18960
|
}
|
|
17962
18961
|
/**
|
|
17963
18962
|
* Provides a set of common helpers and properties relating to symlink handling.
|
|
17964
18963
|
* @param path file or directory pattern being watched
|
|
17965
18964
|
*/
|
|
17966
|
-
_getWatchHelpers(
|
|
17967
|
-
return new WatchHelper(
|
|
18965
|
+
_getWatchHelpers(path26) {
|
|
18966
|
+
return new WatchHelper(path26, this.options.followSymlinks, this);
|
|
17968
18967
|
}
|
|
17969
18968
|
// Directory helpers
|
|
17970
18969
|
// -----------------
|
|
@@ -17996,63 +18995,63 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
17996
18995
|
* @param item base path of item/directory
|
|
17997
18996
|
*/
|
|
17998
18997
|
_remove(directory, item, isDirectory) {
|
|
17999
|
-
const
|
|
18000
|
-
const fullPath = sp2.resolve(
|
|
18001
|
-
isDirectory = isDirectory != null ? isDirectory : this._watched.has(
|
|
18002
|
-
if (!this._throttle("remove",
|
|
18998
|
+
const path26 = sp2.join(directory, item);
|
|
18999
|
+
const fullPath = sp2.resolve(path26);
|
|
19000
|
+
isDirectory = isDirectory != null ? isDirectory : this._watched.has(path26) || this._watched.has(fullPath);
|
|
19001
|
+
if (!this._throttle("remove", path26, 100))
|
|
18003
19002
|
return;
|
|
18004
19003
|
if (!isDirectory && this._watched.size === 1) {
|
|
18005
19004
|
this.add(directory, item, true);
|
|
18006
19005
|
}
|
|
18007
|
-
const wp = this._getWatchedDir(
|
|
19006
|
+
const wp = this._getWatchedDir(path26);
|
|
18008
19007
|
const nestedDirectoryChildren = wp.getChildren();
|
|
18009
|
-
nestedDirectoryChildren.forEach((nested) => this._remove(
|
|
19008
|
+
nestedDirectoryChildren.forEach((nested) => this._remove(path26, nested));
|
|
18010
19009
|
const parent = this._getWatchedDir(directory);
|
|
18011
19010
|
const wasTracked = parent.has(item);
|
|
18012
19011
|
parent.remove(item);
|
|
18013
19012
|
if (this._symlinkPaths.has(fullPath)) {
|
|
18014
19013
|
this._symlinkPaths.delete(fullPath);
|
|
18015
19014
|
}
|
|
18016
|
-
let relPath =
|
|
19015
|
+
let relPath = path26;
|
|
18017
19016
|
if (this.options.cwd)
|
|
18018
|
-
relPath = sp2.relative(this.options.cwd,
|
|
19017
|
+
relPath = sp2.relative(this.options.cwd, path26);
|
|
18019
19018
|
if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
|
|
18020
19019
|
const event = this._pendingWrites.get(relPath).cancelWait();
|
|
18021
19020
|
if (event === EVENTS.ADD)
|
|
18022
19021
|
return;
|
|
18023
19022
|
}
|
|
18024
|
-
this._watched.delete(
|
|
19023
|
+
this._watched.delete(path26);
|
|
18025
19024
|
this._watched.delete(fullPath);
|
|
18026
19025
|
const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
|
|
18027
|
-
if (wasTracked && !this._isIgnored(
|
|
18028
|
-
this._emit(eventName,
|
|
18029
|
-
this._closePath(
|
|
19026
|
+
if (wasTracked && !this._isIgnored(path26))
|
|
19027
|
+
this._emit(eventName, path26);
|
|
19028
|
+
this._closePath(path26);
|
|
18030
19029
|
}
|
|
18031
19030
|
/**
|
|
18032
19031
|
* Closes all watchers for a path
|
|
18033
19032
|
*/
|
|
18034
|
-
_closePath(
|
|
18035
|
-
this._closeFile(
|
|
18036
|
-
const dir = sp2.dirname(
|
|
18037
|
-
this._getWatchedDir(dir).remove(sp2.basename(
|
|
19033
|
+
_closePath(path26) {
|
|
19034
|
+
this._closeFile(path26);
|
|
19035
|
+
const dir = sp2.dirname(path26);
|
|
19036
|
+
this._getWatchedDir(dir).remove(sp2.basename(path26));
|
|
18038
19037
|
}
|
|
18039
19038
|
/**
|
|
18040
19039
|
* Closes only file-specific watchers
|
|
18041
19040
|
*/
|
|
18042
|
-
_closeFile(
|
|
18043
|
-
const closers = this._closers.get(
|
|
19041
|
+
_closeFile(path26) {
|
|
19042
|
+
const closers = this._closers.get(path26);
|
|
18044
19043
|
if (!closers)
|
|
18045
19044
|
return;
|
|
18046
19045
|
closers.forEach((closer) => closer());
|
|
18047
|
-
this._closers.delete(
|
|
19046
|
+
this._closers.delete(path26);
|
|
18048
19047
|
}
|
|
18049
|
-
_addPathCloser(
|
|
19048
|
+
_addPathCloser(path26, closer) {
|
|
18050
19049
|
if (!closer)
|
|
18051
19050
|
return;
|
|
18052
|
-
let list = this._closers.get(
|
|
19051
|
+
let list = this._closers.get(path26);
|
|
18053
19052
|
if (!list) {
|
|
18054
19053
|
list = [];
|
|
18055
|
-
this._closers.set(
|
|
19054
|
+
this._closers.set(path26, list);
|
|
18056
19055
|
}
|
|
18057
19056
|
list.push(closer);
|
|
18058
19057
|
}
|
|
@@ -18082,11 +19081,11 @@ function watch(paths, options = {}) {
|
|
|
18082
19081
|
var chokidar_default = { watch, FSWatcher };
|
|
18083
19082
|
|
|
18084
19083
|
// src/watcher/file-watcher.ts
|
|
18085
|
-
var
|
|
19084
|
+
var path24 = __toESM(require("path"), 1);
|
|
18086
19085
|
|
|
18087
19086
|
// src/watcher/native-recursive-watcher.ts
|
|
18088
|
-
var
|
|
18089
|
-
var
|
|
19087
|
+
var import_node_fs4 = require("fs");
|
|
19088
|
+
var path22 = __toESM(require("path"), 1);
|
|
18090
19089
|
var NativeRecursiveWatcher = class {
|
|
18091
19090
|
constructor(root, onChange, options = {}) {
|
|
18092
19091
|
this.root = root;
|
|
@@ -18134,26 +19133,26 @@ var NativeRecursiveWatcher = class {
|
|
|
18134
19133
|
toAbsolutePath(filename) {
|
|
18135
19134
|
if (filename == null) return null;
|
|
18136
19135
|
const normalizedFilename = typeof filename === "string" ? filename : filename.toString();
|
|
18137
|
-
const absolutePath =
|
|
18138
|
-
const relativePath =
|
|
18139
|
-
const outsideRoot = relativePath === ".." || relativePath.startsWith(`..${
|
|
19136
|
+
const absolutePath = path22.resolve(this.root, normalizedFilename);
|
|
19137
|
+
const relativePath = path22.relative(this.root, absolutePath);
|
|
19138
|
+
const outsideRoot = relativePath === ".." || relativePath.startsWith(`..${path22.sep}`) || path22.isAbsolute(relativePath);
|
|
18140
19139
|
return outsideRoot ? null : absolutePath;
|
|
18141
19140
|
}
|
|
18142
|
-
defaultWatchFactory = (root, listener, options) => (0,
|
|
19141
|
+
defaultWatchFactory = (root, listener, options) => (0, import_node_fs4.watch)(root, options, listener);
|
|
18143
19142
|
};
|
|
18144
19143
|
|
|
18145
19144
|
// src/watcher/snapshot.ts
|
|
18146
19145
|
var fsPromises4 = __toESM(require("fs/promises"), 1);
|
|
18147
|
-
var
|
|
19146
|
+
var path23 = __toESM(require("path"), 1);
|
|
18148
19147
|
async function buildFileSnapshotScan(projectRoot3, config, configPaths = []) {
|
|
18149
|
-
const normalizedProjectRoot =
|
|
19148
|
+
const normalizedProjectRoot = path23.resolve(projectRoot3);
|
|
18150
19149
|
const ignoreFilter = createIgnoreFilter(normalizedProjectRoot);
|
|
18151
19150
|
const includePatterns = [...config.include, ...config.additionalInclude ?? []];
|
|
18152
19151
|
const maxDepth = config.indexing?.maxDepth ?? -1;
|
|
18153
19152
|
const snapshot = /* @__PURE__ */ new Map();
|
|
18154
19153
|
const unreadablePrefixes = /* @__PURE__ */ new Set();
|
|
18155
19154
|
const includeFile = async (filePath) => {
|
|
18156
|
-
const normalizedPath2 =
|
|
19155
|
+
const normalizedPath2 = path23.resolve(filePath);
|
|
18157
19156
|
if (!shouldIncludeFile(normalizedPath2, normalizedProjectRoot, includePatterns, config.exclude, ignoreFilter)) return;
|
|
18158
19157
|
const stat5 = await readStatIfFile(normalizedPath2, unreadablePrefixes);
|
|
18159
19158
|
if (stat5) snapshot.set(normalizedPath2, { size: stat5.size, mtimeMs: stat5.mtimeMs });
|
|
@@ -18165,16 +19164,16 @@ async function buildFileSnapshotScan(projectRoot3, config, configPaths = []) {
|
|
|
18165
19164
|
} catch (error) {
|
|
18166
19165
|
if (isMissingFsError(error)) return;
|
|
18167
19166
|
if (isPermissionFsError(error)) {
|
|
18168
|
-
unreadablePrefixes.add(
|
|
19167
|
+
unreadablePrefixes.add(path23.resolve(directoryPath));
|
|
18169
19168
|
return;
|
|
18170
19169
|
}
|
|
18171
19170
|
throw error;
|
|
18172
19171
|
}
|
|
18173
19172
|
for (const entry of entries) {
|
|
18174
|
-
const fullPath =
|
|
18175
|
-
const relativePath =
|
|
19173
|
+
const fullPath = path23.join(directoryPath, entry.name);
|
|
19174
|
+
const relativePath = path23.relative(normalizedProjectRoot, fullPath);
|
|
18176
19175
|
if (entry.isDirectory()) {
|
|
18177
|
-
if (hasFilteredPathSegment(relativePath,
|
|
19176
|
+
if (hasFilteredPathSegment(relativePath, path23.sep) || isRestrictedDirectory(relativePath, path23.sep)) continue;
|
|
18178
19177
|
if (ignoreFilter.ignores(relativePath)) continue;
|
|
18179
19178
|
if (maxDepth === -1 || depth < maxDepth) await walk(fullPath, depth + 1);
|
|
18180
19179
|
} else if (entry.isFile()) {
|
|
@@ -18187,19 +19186,19 @@ async function buildFileSnapshotScan(projectRoot3, config, configPaths = []) {
|
|
|
18187
19186
|
return { entries: snapshot, unreadablePrefixes };
|
|
18188
19187
|
}
|
|
18189
19188
|
async function buildFileSnapshotForPathScan(projectRoot3, config, configPaths, targetPath) {
|
|
18190
|
-
const normalizedProjectRoot =
|
|
18191
|
-
const normalizedTargetPath =
|
|
19189
|
+
const normalizedProjectRoot = path23.resolve(projectRoot3);
|
|
19190
|
+
const normalizedTargetPath = path23.resolve(targetPath);
|
|
18192
19191
|
if (!isWithinPath(normalizedProjectRoot, normalizedTargetPath)) {
|
|
18193
19192
|
return { entries: /* @__PURE__ */ new Map(), unreadablePrefixes: /* @__PURE__ */ new Set() };
|
|
18194
19193
|
}
|
|
18195
19194
|
const ignoreFilter = createIgnoreFilter(normalizedProjectRoot);
|
|
18196
19195
|
const includePatterns = [...config.include, ...config.additionalInclude ?? []];
|
|
18197
19196
|
const maxDepth = config.indexing?.maxDepth ?? -1;
|
|
18198
|
-
const explicitConfigPaths = new Set(configPaths.map((configPath) =>
|
|
19197
|
+
const explicitConfigPaths = new Set(configPaths.map((configPath) => path23.resolve(configPath)));
|
|
18199
19198
|
const snapshot = /* @__PURE__ */ new Map();
|
|
18200
19199
|
const unreadablePrefixes = /* @__PURE__ */ new Set();
|
|
18201
19200
|
const includeFile = async (filePath) => {
|
|
18202
|
-
const normalizedPath2 =
|
|
19201
|
+
const normalizedPath2 = path23.resolve(filePath);
|
|
18203
19202
|
if (!explicitConfigPaths.has(normalizedPath2) && !shouldIncludeFile(
|
|
18204
19203
|
normalizedPath2,
|
|
18205
19204
|
normalizedProjectRoot,
|
|
@@ -18217,16 +19216,16 @@ async function buildFileSnapshotForPathScan(projectRoot3, config, configPaths, t
|
|
|
18217
19216
|
} catch (error) {
|
|
18218
19217
|
if (isMissingFsError(error)) return;
|
|
18219
19218
|
if (isPermissionFsError(error)) {
|
|
18220
|
-
unreadablePrefixes.add(
|
|
19219
|
+
unreadablePrefixes.add(path23.resolve(directoryPath));
|
|
18221
19220
|
return;
|
|
18222
19221
|
}
|
|
18223
19222
|
throw error;
|
|
18224
19223
|
}
|
|
18225
19224
|
for (const entry of entries) {
|
|
18226
|
-
const fullPath =
|
|
18227
|
-
const relativePath =
|
|
19225
|
+
const fullPath = path23.join(directoryPath, entry.name);
|
|
19226
|
+
const relativePath = path23.relative(normalizedProjectRoot, fullPath);
|
|
18228
19227
|
if (entry.isDirectory()) {
|
|
18229
|
-
if (hasFilteredPathSegment(relativePath,
|
|
19228
|
+
if (hasFilteredPathSegment(relativePath, path23.sep) || isRestrictedDirectory(relativePath, path23.sep)) continue;
|
|
18230
19229
|
if (ignoreFilter.ignores(relativePath)) continue;
|
|
18231
19230
|
if (maxDepth === -1 || depth < maxDepth) await walk(fullPath, depth + 1);
|
|
18232
19231
|
} else if (entry.isFile()) {
|
|
@@ -18250,7 +19249,7 @@ function completeFileSnapshot(previous, scan) {
|
|
|
18250
19249
|
return completed;
|
|
18251
19250
|
}
|
|
18252
19251
|
async function includeExplicitConfigPaths(snapshot, unreadablePrefixes, configPaths) {
|
|
18253
|
-
for (const configPath of [...new Set(configPaths.map((value) =>
|
|
19252
|
+
for (const configPath of [...new Set(configPaths.map((value) => path23.resolve(value)))]) {
|
|
18254
19253
|
if (snapshot.has(configPath)) continue;
|
|
18255
19254
|
const stat5 = await readStatIfFile(configPath, unreadablePrefixes);
|
|
18256
19255
|
if (stat5) snapshot.set(configPath, { size: stat5.size, mtimeMs: stat5.mtimeMs });
|
|
@@ -18260,12 +19259,12 @@ async function includeExplicitConfigPathsInPath(snapshot, unreadablePrefixes, co
|
|
|
18260
19259
|
await includeExplicitConfigPaths(
|
|
18261
19260
|
snapshot,
|
|
18262
19261
|
unreadablePrefixes,
|
|
18263
|
-
configPaths.filter((configPath) => isWithinPath(targetPath,
|
|
19262
|
+
configPaths.filter((configPath) => isWithinPath(targetPath, path23.resolve(configPath)))
|
|
18264
19263
|
);
|
|
18265
19264
|
}
|
|
18266
19265
|
function isWithinPath(parentPath, childPath) {
|
|
18267
|
-
const relativePath =
|
|
18268
|
-
return relativePath === "" || !relativePath.startsWith(`..${
|
|
19266
|
+
const relativePath = path23.relative(parentPath, childPath);
|
|
19267
|
+
return relativePath === "" || !relativePath.startsWith(`..${path23.sep}`) && relativePath !== ".." && !path23.isAbsolute(relativePath);
|
|
18269
19268
|
}
|
|
18270
19269
|
async function readStatIfFile(filePath, unreadablePrefixes) {
|
|
18271
19270
|
try {
|
|
@@ -18274,7 +19273,7 @@ async function readStatIfFile(filePath, unreadablePrefixes) {
|
|
|
18274
19273
|
} catch (error) {
|
|
18275
19274
|
if (isMissingFsError(error)) return null;
|
|
18276
19275
|
if (isPermissionFsError(error)) {
|
|
18277
|
-
unreadablePrefixes.add(
|
|
19276
|
+
unreadablePrefixes.add(path23.resolve(filePath));
|
|
18278
19277
|
return null;
|
|
18279
19278
|
}
|
|
18280
19279
|
throw error;
|
|
@@ -18411,8 +19410,8 @@ var FileWatcher = class {
|
|
|
18411
19410
|
this.createWatcher();
|
|
18412
19411
|
}
|
|
18413
19412
|
resetReady() {
|
|
18414
|
-
this.readyPromise = new Promise((
|
|
18415
|
-
this.resolveReady =
|
|
19413
|
+
this.readyPromise = new Promise((resolve18) => {
|
|
19414
|
+
this.resolveReady = resolve18;
|
|
18416
19415
|
});
|
|
18417
19416
|
this.startupReadySignals = 1;
|
|
18418
19417
|
}
|
|
@@ -18443,7 +19442,7 @@ var FileWatcher = class {
|
|
|
18443
19442
|
const resolvedWatchTargets = watchTargets ?? this.getFullChokidarWatchTargets();
|
|
18444
19443
|
const watcherOptions = {
|
|
18445
19444
|
ignored: (filePath) => {
|
|
18446
|
-
const relativePath =
|
|
19445
|
+
const relativePath = path24.relative(this.projectRoot, filePath);
|
|
18447
19446
|
if (!relativePath) return false;
|
|
18448
19447
|
if (this.isProjectConfigPathOrAncestor(relativePath)) {
|
|
18449
19448
|
return false;
|
|
@@ -18451,10 +19450,10 @@ var FileWatcher = class {
|
|
|
18451
19450
|
if (this.isOutsideProjectPath(relativePath)) {
|
|
18452
19451
|
return true;
|
|
18453
19452
|
}
|
|
18454
|
-
if (hasFilteredPathSegment(relativePath,
|
|
19453
|
+
if (hasFilteredPathSegment(relativePath, path24.sep)) {
|
|
18455
19454
|
return true;
|
|
18456
19455
|
}
|
|
18457
|
-
if (isRestrictedDirectory(relativePath,
|
|
19456
|
+
if (isRestrictedDirectory(relativePath, path24.sep)) {
|
|
18458
19457
|
return true;
|
|
18459
19458
|
}
|
|
18460
19459
|
if (ignoreFilter.ignores(relativePath)) {
|
|
@@ -18545,13 +19544,13 @@ var FileWatcher = class {
|
|
|
18545
19544
|
getExternalConfigWatchTargets() {
|
|
18546
19545
|
return [...new Set(
|
|
18547
19546
|
this.projectConfigPaths.filter((projectConfigPath) => {
|
|
18548
|
-
const relativeConfigPath =
|
|
19547
|
+
const relativeConfigPath = path24.relative(this.projectRoot, projectConfigPath);
|
|
18549
19548
|
return this.isOutsideProjectPath(relativeConfigPath);
|
|
18550
19549
|
}).map((projectConfigPath) => {
|
|
18551
19550
|
if ((0, import_fs14.existsSync)(projectConfigPath)) {
|
|
18552
19551
|
return projectConfigPath;
|
|
18553
19552
|
}
|
|
18554
|
-
return this.getNearestExistingDirectory(
|
|
19553
|
+
return this.getNearestExistingDirectory(path24.dirname(projectConfigPath));
|
|
18555
19554
|
})
|
|
18556
19555
|
)];
|
|
18557
19556
|
}
|
|
@@ -18613,7 +19612,7 @@ var FileWatcher = class {
|
|
|
18613
19612
|
}
|
|
18614
19613
|
scheduleNativeReconciliation(generation, filePath) {
|
|
18615
19614
|
if (!this.isCurrentNativeSetup(generation)) return;
|
|
18616
|
-
const requiresFullReconciliation = filePath ===
|
|
19615
|
+
const requiresFullReconciliation = filePath === path24.join(this.projectRoot, ".gitignore");
|
|
18617
19616
|
const invalidatedPath = requiresFullReconciliation ? null : filePath;
|
|
18618
19617
|
this.nativeInvalidatedPaths.set(invalidatedPath, invalidatedPath !== null);
|
|
18619
19618
|
if (this.nativeReconcileTimer) {
|
|
@@ -18708,23 +19707,23 @@ var FileWatcher = class {
|
|
|
18708
19707
|
this.scheduleFlush();
|
|
18709
19708
|
}
|
|
18710
19709
|
isProjectConfigPath(filePath) {
|
|
18711
|
-
const relativePath =
|
|
18712
|
-
const normalizedRelativePath =
|
|
19710
|
+
const relativePath = path24.relative(this.projectRoot, filePath);
|
|
19711
|
+
const normalizedRelativePath = path24.normalize(relativePath);
|
|
18713
19712
|
return this.getProjectConfigRelativePaths().some((configPath) => configPath === normalizedRelativePath);
|
|
18714
19713
|
}
|
|
18715
19714
|
isProjectConfigPathOrAncestor(relativePath) {
|
|
18716
|
-
const normalizedRelativePath =
|
|
19715
|
+
const normalizedRelativePath = path24.normalize(relativePath);
|
|
18717
19716
|
return this.getProjectConfigRelativePaths().some(
|
|
18718
|
-
(configPath) => configPath === normalizedRelativePath || configPath.startsWith(`${normalizedRelativePath}${
|
|
19717
|
+
(configPath) => configPath === normalizedRelativePath || configPath.startsWith(`${normalizedRelativePath}${path24.sep}`)
|
|
18719
19718
|
);
|
|
18720
19719
|
}
|
|
18721
19720
|
isOutsideProjectPath(relativePath) {
|
|
18722
|
-
return relativePath === ".." || relativePath.startsWith(`..${
|
|
19721
|
+
return relativePath === ".." || relativePath.startsWith(`..${path24.sep}`) || path24.isAbsolute(relativePath);
|
|
18723
19722
|
}
|
|
18724
19723
|
getNearestExistingDirectory(directoryPath) {
|
|
18725
19724
|
let candidate = directoryPath;
|
|
18726
19725
|
while (!(0, import_fs14.existsSync)(candidate)) {
|
|
18727
|
-
const parent =
|
|
19726
|
+
const parent = path24.dirname(candidate);
|
|
18728
19727
|
if (parent === candidate) break;
|
|
18729
19728
|
candidate = parent;
|
|
18730
19729
|
}
|
|
@@ -18732,7 +19731,7 @@ var FileWatcher = class {
|
|
|
18732
19731
|
}
|
|
18733
19732
|
getProjectConfigRelativePaths() {
|
|
18734
19733
|
return this.projectConfigPaths.map(
|
|
18735
|
-
(configPath) =>
|
|
19734
|
+
(configPath) => path24.normalize(path24.relative(this.projectRoot, configPath))
|
|
18736
19735
|
);
|
|
18737
19736
|
}
|
|
18738
19737
|
getConfigPathStates() {
|
|
@@ -18790,7 +19789,7 @@ var FileWatcher = class {
|
|
|
18790
19789
|
return;
|
|
18791
19790
|
}
|
|
18792
19791
|
const changes = Array.from(this.pendingChanges.entries()).map(
|
|
18793
|
-
([
|
|
19792
|
+
([path26, type]) => ({ path: path26, type })
|
|
18794
19793
|
);
|
|
18795
19794
|
this.pendingChanges.clear();
|
|
18796
19795
|
try {
|
|
@@ -18836,7 +19835,7 @@ var FileWatcher = class {
|
|
|
18836
19835
|
};
|
|
18837
19836
|
|
|
18838
19837
|
// src/watcher/git-head-watcher.ts
|
|
18839
|
-
var
|
|
19838
|
+
var path25 = __toESM(require("path"), 1);
|
|
18840
19839
|
var GitHeadWatcher = class {
|
|
18841
19840
|
watcher = null;
|
|
18842
19841
|
projectRoot;
|
|
@@ -18858,13 +19857,13 @@ var GitHeadWatcher = class {
|
|
|
18858
19857
|
this.readyPromise = Promise.resolve();
|
|
18859
19858
|
return;
|
|
18860
19859
|
}
|
|
18861
|
-
this.readyPromise = new Promise((
|
|
18862
|
-
this.resolveReady =
|
|
19860
|
+
this.readyPromise = new Promise((resolve18) => {
|
|
19861
|
+
this.resolveReady = resolve18;
|
|
18863
19862
|
});
|
|
18864
19863
|
this.onBranchChange = handler;
|
|
18865
19864
|
this.currentBranch = getCurrentBranch(this.projectRoot);
|
|
18866
19865
|
const headPath = getHeadPath(this.projectRoot);
|
|
18867
|
-
const refsPath =
|
|
19866
|
+
const refsPath = path25.join(this.projectRoot, ".git", "refs", "heads");
|
|
18868
19867
|
this.watcher = chokidar_default.watch([headPath, refsPath], {
|
|
18869
19868
|
persistent: true,
|
|
18870
19869
|
ignoreInitial: true,
|
|
@@ -18932,7 +19931,9 @@ var GitHeadWatcher = class {
|
|
|
18932
19931
|
function createWatcherWithIndexer(getIndexer, projectRoot3, config, host, options = {}) {
|
|
18933
19932
|
const fileWatcher = new FileWatcher(projectRoot3, config, host, options);
|
|
18934
19933
|
const configPaths = getConfigPaths(projectRoot3, host, options);
|
|
18935
|
-
configureAutoIndex(projectRoot3, host, parseConfig(config), getIndexer
|
|
19934
|
+
configureAutoIndex(projectRoot3, host, parseConfig(config), getIndexer, {
|
|
19935
|
+
synchronizeBackgroundWorker: false
|
|
19936
|
+
});
|
|
18936
19937
|
let stopped = false;
|
|
18937
19938
|
const requestReindex = () => {
|
|
18938
19939
|
if (stopped) return;
|
|
@@ -18952,7 +19953,9 @@ function createWatcherWithIndexer(getIndexer, projectRoot3, config, host, option
|
|
|
18952
19953
|
const parsedConfig = options.configPath ? parseConfig(loadConfigFile(options.configPath)) : void 0;
|
|
18953
19954
|
const refreshedConfig = refreshIndexerForDirectory(projectRoot3, host, parsedConfig);
|
|
18954
19955
|
if (refreshedConfig) {
|
|
18955
|
-
configureAutoIndex(projectRoot3, host, refreshedConfig, getIndexer
|
|
19956
|
+
configureAutoIndex(projectRoot3, host, refreshedConfig, getIndexer, {
|
|
19957
|
+
synchronizeBackgroundWorker: false
|
|
19958
|
+
});
|
|
18956
19959
|
}
|
|
18957
19960
|
}
|
|
18958
19961
|
requestReindex();
|
|
@@ -19000,7 +20003,6 @@ function getConfigPaths(projectRoot3, host, options) {
|
|
|
19000
20003
|
|
|
19001
20004
|
// src/adapters/pi/extension.ts
|
|
19002
20005
|
var HOST2 = "pi";
|
|
19003
|
-
var activeWatchers = /* @__PURE__ */ new Map();
|
|
19004
20006
|
var ChunkType = import_typebox2.Type.Union([
|
|
19005
20007
|
import_typebox2.Type.Literal("function"),
|
|
19006
20008
|
import_typebox2.Type.Literal("class"),
|
|
@@ -19019,24 +20021,30 @@ function projectRoot2(ctx) {
|
|
|
19019
20021
|
function isValidProject(projectRoot3, requireProjectMarker) {
|
|
19020
20022
|
return !isHomeDirectory(projectRoot3) && (!requireProjectMarker || hasProjectMarker(projectRoot3));
|
|
19021
20023
|
}
|
|
19022
|
-
function ensureWatcher(projectRoot3) {
|
|
19023
|
-
if (activeWatchers.has(projectRoot3)) return;
|
|
20024
|
+
async function ensureWatcher(projectRoot3) {
|
|
19024
20025
|
const config = parseConfig(loadMergedConfig(projectRoot3, HOST2));
|
|
19025
|
-
if (!
|
|
20026
|
+
if (!isValidProject(projectRoot3, config.indexing.requireProjectMarker)) {
|
|
20027
|
+
await stopBackgroundWorker(projectRoot3, HOST2).catch((error) => {
|
|
20028
|
+
console.error("[codebase-index] Failed to stop Pi background worker:", error);
|
|
20029
|
+
});
|
|
19026
20030
|
return;
|
|
19027
20031
|
}
|
|
19028
|
-
|
|
20032
|
+
getIndexerForProject(projectRoot3, HOST2);
|
|
20033
|
+
const watcherFactoryForConfig = (refreshedConfig) => refreshedConfig.indexing.watchFiles ? () => createWatcherWithIndexer(
|
|
19029
20034
|
() => getIndexerForProject(projectRoot3, HOST2),
|
|
19030
20035
|
projectRoot3,
|
|
19031
|
-
|
|
20036
|
+
refreshedConfig,
|
|
19032
20037
|
HOST2
|
|
19033
|
-
)
|
|
19034
|
-
|
|
19035
|
-
|
|
19036
|
-
|
|
19037
|
-
|
|
19038
|
-
|
|
19039
|
-
|
|
20038
|
+
) : null;
|
|
20039
|
+
configureBackgroundWorker(projectRoot3, HOST2, config, {
|
|
20040
|
+
startAutoIndex: (source, allowDisabledAutoIndex) => {
|
|
20041
|
+
startAutoIndexForBackgroundWorker(projectRoot3, HOST2, source, allowDisabledAutoIndex);
|
|
20042
|
+
},
|
|
20043
|
+
stopAutoIndex: () => stopAutoIndexForBackgroundWorker(projectRoot3, HOST2),
|
|
20044
|
+
watcherFactory: watcherFactoryForConfig(config),
|
|
20045
|
+
watcherFactoryForConfig
|
|
20046
|
+
});
|
|
20047
|
+
await waitForBackgroundWorkerStart(projectRoot3, HOST2);
|
|
19040
20048
|
}
|
|
19041
20049
|
function codebaseIndexPiExtension(pi) {
|
|
19042
20050
|
pi.registerTool({
|
|
@@ -19269,7 +20277,7 @@ function codebaseIndexPiExtension(pi) {
|
|
|
19269
20277
|
});
|
|
19270
20278
|
registerPiCallGraphTools(pi);
|
|
19271
20279
|
pi.on("before_agent_start", async (event, ctx) => {
|
|
19272
|
-
ensureWatcher(projectRoot2(ctx));
|
|
20280
|
+
await ensureWatcher(projectRoot2(ctx));
|
|
19273
20281
|
return {
|
|
19274
20282
|
systemPrompt: `${event.systemPrompt}
|
|
19275
20283
|
|
|
@@ -19278,7 +20286,7 @@ Check index_status first when index readiness is unknown. Use codebase_context o
|
|
|
19278
20286
|
});
|
|
19279
20287
|
pi.on("session_shutdown", async (_event, ctx) => {
|
|
19280
20288
|
const root = projectRoot2(ctx);
|
|
19281
|
-
await
|
|
20289
|
+
await stopBackgroundWorker(root, HOST2);
|
|
19282
20290
|
});
|
|
19283
20291
|
pi.registerTool({
|
|
19284
20292
|
name: TOOL_NAME.PR_IMPACT,
|