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.js
CHANGED
|
@@ -328,7 +328,7 @@ var require_ignore = __commonJS({
|
|
|
328
328
|
// path matching.
|
|
329
329
|
// - check `string` either `MODE_IGNORE` or `MODE_CHECK_IGNORE`
|
|
330
330
|
// @returns {TestResult} true if a file is ignored
|
|
331
|
-
test(
|
|
331
|
+
test(path26, checkUnignored, mode) {
|
|
332
332
|
let ignored = false;
|
|
333
333
|
let unignored = false;
|
|
334
334
|
let matchedRule;
|
|
@@ -337,7 +337,7 @@ var require_ignore = __commonJS({
|
|
|
337
337
|
if (unignored === negative && ignored !== unignored || negative && !ignored && !unignored && !checkUnignored) {
|
|
338
338
|
return;
|
|
339
339
|
}
|
|
340
|
-
const matched = rule[mode].test(
|
|
340
|
+
const matched = rule[mode].test(path26);
|
|
341
341
|
if (!matched) {
|
|
342
342
|
return;
|
|
343
343
|
}
|
|
@@ -358,17 +358,17 @@ var require_ignore = __commonJS({
|
|
|
358
358
|
var throwError = (message, Ctor) => {
|
|
359
359
|
throw new Ctor(message);
|
|
360
360
|
};
|
|
361
|
-
var checkPath = (
|
|
362
|
-
if (!isString(
|
|
361
|
+
var checkPath = (path26, originalPath, doThrow) => {
|
|
362
|
+
if (!isString(path26)) {
|
|
363
363
|
return doThrow(
|
|
364
364
|
`path must be a string, but got \`${originalPath}\``,
|
|
365
365
|
TypeError
|
|
366
366
|
);
|
|
367
367
|
}
|
|
368
|
-
if (!
|
|
368
|
+
if (!path26) {
|
|
369
369
|
return doThrow(`path must not be empty`, TypeError);
|
|
370
370
|
}
|
|
371
|
-
if (checkPath.isNotRelative(
|
|
371
|
+
if (checkPath.isNotRelative(path26)) {
|
|
372
372
|
const r = "`path.relative()`d";
|
|
373
373
|
return doThrow(
|
|
374
374
|
`path should be a ${r} string, but got "${originalPath}"`,
|
|
@@ -377,7 +377,7 @@ var require_ignore = __commonJS({
|
|
|
377
377
|
}
|
|
378
378
|
return true;
|
|
379
379
|
};
|
|
380
|
-
var isNotRelative = (
|
|
380
|
+
var isNotRelative = (path26) => REGEX_TEST_INVALID_PATH.test(path26);
|
|
381
381
|
checkPath.isNotRelative = isNotRelative;
|
|
382
382
|
checkPath.convert = (p) => p;
|
|
383
383
|
var Ignore2 = class {
|
|
@@ -407,19 +407,19 @@ var require_ignore = __commonJS({
|
|
|
407
407
|
}
|
|
408
408
|
// @returns {TestResult}
|
|
409
409
|
_test(originalPath, cache, checkUnignored, slices) {
|
|
410
|
-
const
|
|
410
|
+
const path26 = originalPath && checkPath.convert(originalPath);
|
|
411
411
|
checkPath(
|
|
412
|
-
|
|
412
|
+
path26,
|
|
413
413
|
originalPath,
|
|
414
414
|
this._strictPathCheck ? throwError : RETURN_FALSE
|
|
415
415
|
);
|
|
416
|
-
return this._t(
|
|
416
|
+
return this._t(path26, cache, checkUnignored, slices);
|
|
417
417
|
}
|
|
418
|
-
checkIgnore(
|
|
419
|
-
if (!REGEX_TEST_TRAILING_SLASH.test(
|
|
420
|
-
return this.test(
|
|
418
|
+
checkIgnore(path26) {
|
|
419
|
+
if (!REGEX_TEST_TRAILING_SLASH.test(path26)) {
|
|
420
|
+
return this.test(path26);
|
|
421
421
|
}
|
|
422
|
-
const slices =
|
|
422
|
+
const slices = path26.split(SLASH2).filter(Boolean);
|
|
423
423
|
slices.pop();
|
|
424
424
|
if (slices.length) {
|
|
425
425
|
const parent = this._t(
|
|
@@ -432,18 +432,18 @@ var require_ignore = __commonJS({
|
|
|
432
432
|
return parent;
|
|
433
433
|
}
|
|
434
434
|
}
|
|
435
|
-
return this._rules.test(
|
|
435
|
+
return this._rules.test(path26, false, MODE_CHECK_IGNORE);
|
|
436
436
|
}
|
|
437
|
-
_t(
|
|
438
|
-
if (
|
|
439
|
-
return cache[
|
|
437
|
+
_t(path26, cache, checkUnignored, slices) {
|
|
438
|
+
if (path26 in cache) {
|
|
439
|
+
return cache[path26];
|
|
440
440
|
}
|
|
441
441
|
if (!slices) {
|
|
442
|
-
slices =
|
|
442
|
+
slices = path26.split(SLASH2).filter(Boolean);
|
|
443
443
|
}
|
|
444
444
|
slices.pop();
|
|
445
445
|
if (!slices.length) {
|
|
446
|
-
return cache[
|
|
446
|
+
return cache[path26] = this._rules.test(path26, checkUnignored, MODE_IGNORE);
|
|
447
447
|
}
|
|
448
448
|
const parent = this._t(
|
|
449
449
|
slices.join(SLASH2) + SLASH2,
|
|
@@ -451,29 +451,29 @@ var require_ignore = __commonJS({
|
|
|
451
451
|
checkUnignored,
|
|
452
452
|
slices
|
|
453
453
|
);
|
|
454
|
-
return cache[
|
|
454
|
+
return cache[path26] = parent.ignored ? parent : this._rules.test(path26, checkUnignored, MODE_IGNORE);
|
|
455
455
|
}
|
|
456
|
-
ignores(
|
|
457
|
-
return this._test(
|
|
456
|
+
ignores(path26) {
|
|
457
|
+
return this._test(path26, this._ignoreCache, false).ignored;
|
|
458
458
|
}
|
|
459
459
|
createFilter() {
|
|
460
|
-
return (
|
|
460
|
+
return (path26) => !this.ignores(path26);
|
|
461
461
|
}
|
|
462
462
|
filter(paths) {
|
|
463
463
|
return makeArray(paths).filter(this.createFilter());
|
|
464
464
|
}
|
|
465
465
|
// @returns {TestResult}
|
|
466
|
-
test(
|
|
467
|
-
return this._test(
|
|
466
|
+
test(path26) {
|
|
467
|
+
return this._test(path26, this._testCache, true);
|
|
468
468
|
}
|
|
469
469
|
};
|
|
470
470
|
var factory = (options) => new Ignore2(options);
|
|
471
|
-
var isPathValid = (
|
|
471
|
+
var isPathValid = (path26) => checkPath(path26 && checkPath.convert(path26), path26, RETURN_FALSE);
|
|
472
472
|
var setupWindows = () => {
|
|
473
473
|
const makePosix = (str) => /^\\\\\?\\/.test(str) || /["<>|\u0000-\u001F]+/u.test(str) ? str : str.replace(/\\/g, "/");
|
|
474
474
|
checkPath.convert = makePosix;
|
|
475
475
|
const REGEX_TEST_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i;
|
|
476
|
-
checkPath.isNotRelative = (
|
|
476
|
+
checkPath.isNotRelative = (path26) => REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path26) || isNotRelative(path26);
|
|
477
477
|
};
|
|
478
478
|
if (
|
|
479
479
|
// Detect `process` so that it can run in browsers.
|
|
@@ -2241,8 +2241,8 @@ function formatCodeCommunities(result) {
|
|
|
2241
2241
|
}
|
|
2242
2242
|
|
|
2243
2243
|
// src/tools/operations.ts
|
|
2244
|
-
import { existsSync as
|
|
2245
|
-
import * as
|
|
2244
|
+
import { existsSync as existsSync13, realpathSync as realpathSync6, statSync as statSync5 } from "fs";
|
|
2245
|
+
import * as path21 from "path";
|
|
2246
2246
|
|
|
2247
2247
|
// src/tools/knowledge-base-paths.ts
|
|
2248
2248
|
import * as path9 from "path";
|
|
@@ -2954,8 +2954,8 @@ function formatExactSearchHandoff(results) {
|
|
|
2954
2954
|
}
|
|
2955
2955
|
function formatContextEvidence(result, index) {
|
|
2956
2956
|
const symbol = result.name ? ` ${JSON.stringify(compactEvidenceValue(result.name, 80))}` : "";
|
|
2957
|
-
const
|
|
2958
|
-
return `[${index}] ${result.chunkType}${symbol} in ${
|
|
2957
|
+
const path26 = compactEvidenceValue(result.filePath, 120);
|
|
2958
|
+
return `[${index}] ${result.chunkType}${symbol} in ${path26}:${result.startLine}-${result.endLine} (score ${result.score.toFixed(2)})`;
|
|
2959
2959
|
}
|
|
2960
2960
|
function formatContextPack(heading, selected, candidateCount, duplicateCount, limitOmittedCount, budgetOmittedCount, includeExactSearchHandoff) {
|
|
2961
2961
|
const lines = selected.map((result, index) => formatContextEvidence(result, index + 1));
|
|
@@ -3597,9 +3597,9 @@ function formatEffectivenessMetrics(snapshot) {
|
|
|
3597
3597
|
}
|
|
3598
3598
|
|
|
3599
3599
|
// src/utils/auto-index.ts
|
|
3600
|
-
import { existsSync as
|
|
3601
|
-
import * as
|
|
3602
|
-
import * as
|
|
3600
|
+
import { existsSync as existsSync9, realpathSync as realpathSync4 } from "fs";
|
|
3601
|
+
import * as os5 from "os";
|
|
3602
|
+
import * as path13 from "path";
|
|
3603
3603
|
|
|
3604
3604
|
// src/indexer/index-lock.ts
|
|
3605
3605
|
import { randomUUID } from "crypto";
|
|
@@ -3856,7 +3856,7 @@ function removeDeadReclaimMarker(lockPath, expectedOwner) {
|
|
|
3856
3856
|
return true;
|
|
3857
3857
|
}
|
|
3858
3858
|
function reclaimDeadOwner(indexPath, lockPath, expectedOwner) {
|
|
3859
|
-
const
|
|
3859
|
+
const reclaimPath2 = path10.join(lockPath, RECLAIM_DIRECTORY_NAME);
|
|
3860
3860
|
const reclaimOwner = {
|
|
3861
3861
|
pid: process.pid,
|
|
3862
3862
|
hostname: os3.hostname(),
|
|
@@ -3865,19 +3865,19 @@ function reclaimDeadOwner(indexPath, lockPath, expectedOwner) {
|
|
|
3865
3865
|
expectedOwnerToken: expectedOwner.token
|
|
3866
3866
|
};
|
|
3867
3867
|
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
3868
|
-
if (publishJsonDirectory(
|
|
3868
|
+
if (publishJsonDirectory(reclaimPath2, reclaimOwner)) break;
|
|
3869
3869
|
if (attempt === 0 && removeDeadReclaimMarker(lockPath, expectedOwner)) continue;
|
|
3870
3870
|
return false;
|
|
3871
3871
|
}
|
|
3872
3872
|
try {
|
|
3873
|
-
const currentReclaimer = readReclaimOwner(
|
|
3873
|
+
const currentReclaimer = readReclaimOwner(reclaimPath2);
|
|
3874
3874
|
const currentOwner = readDirectoryOwner(lockPath);
|
|
3875
3875
|
if (!currentReclaimer || !sameReclaimOwner(currentReclaimer, reclaimOwner) || !currentOwner || !sameOwner(currentOwner, expectedOwner) || getOwnerLiveness(currentOwner) !== "dead") {
|
|
3876
3876
|
return false;
|
|
3877
3877
|
}
|
|
3878
3878
|
publishRecoveryMarker(indexPath, expectedOwner);
|
|
3879
3879
|
const ownerBeforeQuarantine = readDirectoryOwner(lockPath);
|
|
3880
|
-
const reclaimerBeforeQuarantine = readReclaimOwner(
|
|
3880
|
+
const reclaimerBeforeQuarantine = readReclaimOwner(reclaimPath2);
|
|
3881
3881
|
if (!ownerBeforeQuarantine || !sameOwner(ownerBeforeQuarantine, expectedOwner) || getOwnerLiveness(ownerBeforeQuarantine) !== "dead" || !reclaimerBeforeQuarantine || !sameReclaimOwner(reclaimerBeforeQuarantine, reclaimOwner)) {
|
|
3882
3882
|
return false;
|
|
3883
3883
|
}
|
|
@@ -4047,10 +4047,893 @@ function completeLeaseRecovery(lease) {
|
|
|
4047
4047
|
}
|
|
4048
4048
|
}
|
|
4049
4049
|
|
|
4050
|
+
// src/utils/background-worker.ts
|
|
4051
|
+
import { createHash, randomUUID as randomUUID2 } from "crypto";
|
|
4052
|
+
import {
|
|
4053
|
+
existsSync as existsSync7,
|
|
4054
|
+
lstatSync as lstatSync2,
|
|
4055
|
+
mkdirSync as mkdirSync2,
|
|
4056
|
+
readFileSync as readFileSync6,
|
|
4057
|
+
realpathSync as realpathSync3,
|
|
4058
|
+
renameSync as renameSync2,
|
|
4059
|
+
rmSync as rmSync2,
|
|
4060
|
+
writeFileSync as writeFileSync2
|
|
4061
|
+
} from "fs";
|
|
4062
|
+
import * as os4 from "os";
|
|
4063
|
+
import * as path11 from "path";
|
|
4064
|
+
var OWNER_FILE_NAME2 = "owner.json";
|
|
4065
|
+
var HEARTBEAT_FILE_PREFIX = "heartbeat.";
|
|
4066
|
+
var RECLAIM_DIRECTORY_NAME2 = "reclaim";
|
|
4067
|
+
var REFRESH_REQUEST_FILE_NAME = "refresh-request.json";
|
|
4068
|
+
var HEARTBEAT_INTERVAL_MS = 5e3;
|
|
4069
|
+
var STALE_LEASE_MS = 3e4;
|
|
4070
|
+
var RETRY_DELAY_MS = 5e3;
|
|
4071
|
+
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;
|
|
4072
|
+
var BackgroundWorkerStopError = class extends Error {
|
|
4073
|
+
constructor(watcherError, autoIndexError) {
|
|
4074
|
+
super("Failed to stop background worker");
|
|
4075
|
+
this.watcherError = watcherError;
|
|
4076
|
+
this.autoIndexError = autoIndexError;
|
|
4077
|
+
this.name = "BackgroundWorkerStopError";
|
|
4078
|
+
}
|
|
4079
|
+
watcherError;
|
|
4080
|
+
autoIndexError;
|
|
4081
|
+
};
|
|
4082
|
+
var workers = /* @__PURE__ */ new Map();
|
|
4083
|
+
var workerKeysByProject = /* @__PURE__ */ new Map();
|
|
4084
|
+
var workerReplacementBarriers = /* @__PURE__ */ new Map();
|
|
4085
|
+
function getErrorCode2(error) {
|
|
4086
|
+
return typeof error === "object" && error !== null && "code" in error ? String(error.code) : void 0;
|
|
4087
|
+
}
|
|
4088
|
+
function canonicalizePath(targetPath) {
|
|
4089
|
+
const resolved = path11.resolve(targetPath);
|
|
4090
|
+
if (existsSync7(resolved)) {
|
|
4091
|
+
try {
|
|
4092
|
+
return realpathSync3.native(resolved);
|
|
4093
|
+
} catch {
|
|
4094
|
+
return resolved;
|
|
4095
|
+
}
|
|
4096
|
+
}
|
|
4097
|
+
const parent = path11.dirname(resolved);
|
|
4098
|
+
if (parent === resolved) return resolved;
|
|
4099
|
+
return path11.join(canonicalizePath(parent), path11.basename(resolved));
|
|
4100
|
+
}
|
|
4101
|
+
function projectLookupKey(projectRoot3, host) {
|
|
4102
|
+
return `${host}::${canonicalizePath(projectRoot3)}`;
|
|
4103
|
+
}
|
|
4104
|
+
function resolveIdentity(projectRoot3, config, host) {
|
|
4105
|
+
const canonicalProjectRoot = canonicalizePath(projectRoot3);
|
|
4106
|
+
const canonicalIndexPath = canonicalizePath(resolveProjectIndexPath(projectRoot3, config.scope, host));
|
|
4107
|
+
return {
|
|
4108
|
+
canonicalIndexPath,
|
|
4109
|
+
canonicalProjectRoot,
|
|
4110
|
+
key: `${canonicalIndexPath}::${canonicalProjectRoot}`
|
|
4111
|
+
};
|
|
4112
|
+
}
|
|
4113
|
+
function controllerKey(identity, host) {
|
|
4114
|
+
return `${identity.key}::${host}`;
|
|
4115
|
+
}
|
|
4116
|
+
function leaseDirectoryName(identity) {
|
|
4117
|
+
const hash = createHash("sha256").update(identity.key).digest("hex").slice(0, 32);
|
|
4118
|
+
return `background-worker.${hash}.lease`;
|
|
4119
|
+
}
|
|
4120
|
+
function leasePathFor(identity) {
|
|
4121
|
+
return path11.join(identity.canonicalIndexPath, leaseDirectoryName(identity));
|
|
4122
|
+
}
|
|
4123
|
+
function parseOwner2(value) {
|
|
4124
|
+
if (typeof value !== "object" || value === null) return null;
|
|
4125
|
+
const candidate = value;
|
|
4126
|
+
if (candidate.version !== 1) return null;
|
|
4127
|
+
if (!Number.isInteger(candidate.pid) || (candidate.pid ?? 0) <= 0) return null;
|
|
4128
|
+
if (typeof candidate.hostname !== "string" || candidate.hostname.length === 0) return null;
|
|
4129
|
+
if (typeof candidate.startedAt !== "string" || Number.isNaN(Date.parse(candidate.startedAt))) return null;
|
|
4130
|
+
if (typeof candidate.heartbeatAt !== "string" || Number.isNaN(Date.parse(candidate.heartbeatAt))) return null;
|
|
4131
|
+
if (typeof candidate.projectRoot !== "string" || candidate.projectRoot.length === 0) return null;
|
|
4132
|
+
if (typeof candidate.indexPath !== "string" || candidate.indexPath.length === 0) return null;
|
|
4133
|
+
if (typeof candidate.token !== "string" || !UUID_PATTERN2.test(candidate.token)) return null;
|
|
4134
|
+
return candidate;
|
|
4135
|
+
}
|
|
4136
|
+
function parseHeartbeat(value, expectedToken) {
|
|
4137
|
+
if (typeof value !== "object" || value === null) return null;
|
|
4138
|
+
const candidate = value;
|
|
4139
|
+
if (candidate.version !== 1 || candidate.token !== expectedToken) return null;
|
|
4140
|
+
if (typeof candidate.heartbeatAt !== "string" || Number.isNaN(Date.parse(candidate.heartbeatAt))) return null;
|
|
4141
|
+
return candidate;
|
|
4142
|
+
}
|
|
4143
|
+
function parseReclaimOwner2(value) {
|
|
4144
|
+
if (typeof value !== "object" || value === null) return null;
|
|
4145
|
+
const candidate = value;
|
|
4146
|
+
if (candidate.version !== 1) return null;
|
|
4147
|
+
if (!Number.isInteger(candidate.pid) || (candidate.pid ?? 0) <= 0) return null;
|
|
4148
|
+
if (typeof candidate.hostname !== "string" || candidate.hostname.length === 0) return null;
|
|
4149
|
+
if (typeof candidate.startedAt !== "string" || Number.isNaN(Date.parse(candidate.startedAt))) return null;
|
|
4150
|
+
if (typeof candidate.token !== "string" || !UUID_PATTERN2.test(candidate.token)) return null;
|
|
4151
|
+
if (candidate.expectedOwnerToken !== null && (typeof candidate.expectedOwnerToken !== "string" || !UUID_PATTERN2.test(candidate.expectedOwnerToken))) return null;
|
|
4152
|
+
return candidate;
|
|
4153
|
+
}
|
|
4154
|
+
function heartbeatPath(leasePath, token) {
|
|
4155
|
+
return path11.join(leasePath, `${HEARTBEAT_FILE_PREFIX}${token}.json`);
|
|
4156
|
+
}
|
|
4157
|
+
function reclaimPath(leasePath) {
|
|
4158
|
+
return path11.join(leasePath, RECLAIM_DIRECTORY_NAME2);
|
|
4159
|
+
}
|
|
4160
|
+
function refreshRequestPath(leasePath) {
|
|
4161
|
+
return path11.join(leasePath, REFRESH_REQUEST_FILE_NAME);
|
|
4162
|
+
}
|
|
4163
|
+
function readLeaseOwner(leasePath) {
|
|
4164
|
+
try {
|
|
4165
|
+
return parseOwner2(JSON.parse(readFileSync6(path11.join(leasePath, OWNER_FILE_NAME2), "utf-8")));
|
|
4166
|
+
} catch {
|
|
4167
|
+
return null;
|
|
4168
|
+
}
|
|
4169
|
+
}
|
|
4170
|
+
function readOwner(leasePath) {
|
|
4171
|
+
const owner = readLeaseOwner(leasePath);
|
|
4172
|
+
if (!owner) return null;
|
|
4173
|
+
try {
|
|
4174
|
+
const heartbeat = parseHeartbeat(
|
|
4175
|
+
JSON.parse(readFileSync6(heartbeatPath(leasePath, owner.token), "utf-8")),
|
|
4176
|
+
owner.token
|
|
4177
|
+
);
|
|
4178
|
+
return heartbeat ? { ...owner, heartbeatAt: heartbeat.heartbeatAt } : owner;
|
|
4179
|
+
} catch {
|
|
4180
|
+
return owner;
|
|
4181
|
+
}
|
|
4182
|
+
}
|
|
4183
|
+
function readReclaimOwner2(leasePath) {
|
|
4184
|
+
try {
|
|
4185
|
+
return parseReclaimOwner2(JSON.parse(readFileSync6(path11.join(reclaimPath(leasePath), OWNER_FILE_NAME2), "utf-8")));
|
|
4186
|
+
} catch {
|
|
4187
|
+
return null;
|
|
4188
|
+
}
|
|
4189
|
+
}
|
|
4190
|
+
function ownerLiveness(owner) {
|
|
4191
|
+
if (owner.hostname !== os4.hostname()) return "unknown";
|
|
4192
|
+
try {
|
|
4193
|
+
process.kill(owner.pid, 0);
|
|
4194
|
+
return "alive";
|
|
4195
|
+
} catch (error) {
|
|
4196
|
+
const code = getErrorCode2(error);
|
|
4197
|
+
if (code === "ESRCH") return "dead";
|
|
4198
|
+
if (code === "EPERM") return "alive";
|
|
4199
|
+
return "unknown";
|
|
4200
|
+
}
|
|
4201
|
+
}
|
|
4202
|
+
function isHeartbeatExpired(owner) {
|
|
4203
|
+
return Date.now() - Date.parse(owner.heartbeatAt) >= STALE_LEASE_MS;
|
|
4204
|
+
}
|
|
4205
|
+
function sameOwner2(left, right) {
|
|
4206
|
+
return left.pid === right.pid && left.hostname === right.hostname && left.token === right.token;
|
|
4207
|
+
}
|
|
4208
|
+
function writeHeartbeat(leasePath, owner) {
|
|
4209
|
+
const targetPath = heartbeatPath(leasePath, owner.token);
|
|
4210
|
+
const temporaryPath = `${targetPath}.tmp.${process.pid}.${owner.token}.${randomUUID2()}`;
|
|
4211
|
+
const heartbeat = {
|
|
4212
|
+
version: 1,
|
|
4213
|
+
token: owner.token,
|
|
4214
|
+
heartbeatAt: owner.heartbeatAt
|
|
4215
|
+
};
|
|
4216
|
+
try {
|
|
4217
|
+
writeFileSync2(temporaryPath, JSON.stringify(heartbeat), {
|
|
4218
|
+
encoding: "utf-8",
|
|
4219
|
+
flag: "wx",
|
|
4220
|
+
mode: 384
|
|
4221
|
+
});
|
|
4222
|
+
renameSync2(temporaryPath, targetPath);
|
|
4223
|
+
const currentOwner = readLeaseOwner(leasePath);
|
|
4224
|
+
return currentOwner !== null && sameOwner2(currentOwner, owner);
|
|
4225
|
+
} finally {
|
|
4226
|
+
if (existsSync7(temporaryPath)) rmSync2(temporaryPath, { force: true });
|
|
4227
|
+
}
|
|
4228
|
+
}
|
|
4229
|
+
function requestRefreshFromLeader(leasePath, allowDisabledAutoIndex) {
|
|
4230
|
+
const requestPath = refreshRequestPath(leasePath);
|
|
4231
|
+
const temporaryPath = `${requestPath}.tmp.${process.pid}.${randomUUID2()}`;
|
|
4232
|
+
try {
|
|
4233
|
+
const request = {
|
|
4234
|
+
allowDisabledAutoIndex,
|
|
4235
|
+
requestedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4236
|
+
version: 1
|
|
4237
|
+
};
|
|
4238
|
+
writeFileSync2(temporaryPath, JSON.stringify(request), {
|
|
4239
|
+
encoding: "utf-8",
|
|
4240
|
+
flag: "wx",
|
|
4241
|
+
mode: 384
|
|
4242
|
+
});
|
|
4243
|
+
renameSync2(temporaryPath, requestPath);
|
|
4244
|
+
} catch (error) {
|
|
4245
|
+
if (getErrorCode2(error) !== "ENOENT") {
|
|
4246
|
+
console.error("[codebase-index] Failed to request background index refresh from the project worker:", error);
|
|
4247
|
+
}
|
|
4248
|
+
} finally {
|
|
4249
|
+
if (existsSync7(temporaryPath)) rmSync2(temporaryPath, { force: true });
|
|
4250
|
+
}
|
|
4251
|
+
}
|
|
4252
|
+
function consumeRefreshRequest(leasePath) {
|
|
4253
|
+
const requestPath = refreshRequestPath(leasePath);
|
|
4254
|
+
const claimedPath = `${requestPath}.handling.${process.pid}.${randomUUID2()}`;
|
|
4255
|
+
try {
|
|
4256
|
+
renameSync2(requestPath, claimedPath);
|
|
4257
|
+
} catch (error) {
|
|
4258
|
+
if (getErrorCode2(error) === "ENOENT") return null;
|
|
4259
|
+
throw error;
|
|
4260
|
+
}
|
|
4261
|
+
try {
|
|
4262
|
+
const value = JSON.parse(readFileSync6(claimedPath, "utf-8"));
|
|
4263
|
+
return {
|
|
4264
|
+
allowDisabledAutoIndex: value.version === 1 && value.allowDisabledAutoIndex === true,
|
|
4265
|
+
requestedAt: typeof value.requestedAt === "string" ? value.requestedAt : (/* @__PURE__ */ new Date()).toISOString(),
|
|
4266
|
+
version: 1
|
|
4267
|
+
};
|
|
4268
|
+
} catch {
|
|
4269
|
+
return { allowDisabledAutoIndex: false, requestedAt: (/* @__PURE__ */ new Date()).toISOString(), version: 1 };
|
|
4270
|
+
} finally {
|
|
4271
|
+
rmSync2(claimedPath, { force: true });
|
|
4272
|
+
}
|
|
4273
|
+
}
|
|
4274
|
+
function publishLease(leasePath, owner) {
|
|
4275
|
+
const candidatePath = `${leasePath}.candidate.${process.pid}.${owner.token}`;
|
|
4276
|
+
try {
|
|
4277
|
+
mkdirSync2(candidatePath, { mode: 448 });
|
|
4278
|
+
} catch (error) {
|
|
4279
|
+
if (getErrorCode2(error) === "ENOENT") return false;
|
|
4280
|
+
throw error;
|
|
4281
|
+
}
|
|
4282
|
+
try {
|
|
4283
|
+
writeFileSync2(path11.join(candidatePath, OWNER_FILE_NAME2), JSON.stringify(owner), {
|
|
4284
|
+
encoding: "utf-8",
|
|
4285
|
+
flag: "wx",
|
|
4286
|
+
mode: 384
|
|
4287
|
+
});
|
|
4288
|
+
if (existsSync7(leasePath)) return false;
|
|
4289
|
+
try {
|
|
4290
|
+
renameSync2(candidatePath, leasePath);
|
|
4291
|
+
return true;
|
|
4292
|
+
} catch (error) {
|
|
4293
|
+
if (existsSync7(leasePath) || getErrorCode2(error) === "ENOENT") return false;
|
|
4294
|
+
throw error;
|
|
4295
|
+
}
|
|
4296
|
+
} finally {
|
|
4297
|
+
if (existsSync7(candidatePath)) rmSync2(candidatePath, { recursive: true, force: true });
|
|
4298
|
+
}
|
|
4299
|
+
}
|
|
4300
|
+
function sameReclaimOwner2(left, right) {
|
|
4301
|
+
return left.pid === right.pid && left.hostname === right.hostname && left.token === right.token && left.expectedOwnerToken === right.expectedOwnerToken;
|
|
4302
|
+
}
|
|
4303
|
+
function reclaimerLiveness(owner) {
|
|
4304
|
+
return ownerLiveness(owner);
|
|
4305
|
+
}
|
|
4306
|
+
function isReclaimMarkerExpired(leasePath, owner) {
|
|
4307
|
+
const startedAt = owner ? Date.parse(owner.startedAt) : (() => {
|
|
4308
|
+
try {
|
|
4309
|
+
return lstatSync2(reclaimPath(leasePath)).mtimeMs;
|
|
4310
|
+
} catch {
|
|
4311
|
+
return Date.now();
|
|
4312
|
+
}
|
|
4313
|
+
})();
|
|
4314
|
+
return Date.now() - startedAt >= STALE_LEASE_MS;
|
|
4315
|
+
}
|
|
4316
|
+
function hasActiveReclaimMarker(leasePath, owner) {
|
|
4317
|
+
const marker = readReclaimOwner2(leasePath);
|
|
4318
|
+
return marker !== null && marker.expectedOwnerToken === owner.token && (marker.hostname !== os4.hostname() || ownerLiveness(owner) !== "alive");
|
|
4319
|
+
}
|
|
4320
|
+
function publishReclaimMarker(leasePath, expectedOwner) {
|
|
4321
|
+
const markerPath = reclaimPath(leasePath);
|
|
4322
|
+
const owner = {
|
|
4323
|
+
version: 1,
|
|
4324
|
+
pid: process.pid,
|
|
4325
|
+
hostname: os4.hostname(),
|
|
4326
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4327
|
+
token: randomUUID2(),
|
|
4328
|
+
expectedOwnerToken: expectedOwner?.token ?? null
|
|
4329
|
+
};
|
|
4330
|
+
try {
|
|
4331
|
+
mkdirSync2(markerPath, { mode: 448 });
|
|
4332
|
+
} catch (error) {
|
|
4333
|
+
if (getErrorCode2(error) === "EEXIST" || getErrorCode2(error) === "ENOENT") return null;
|
|
4334
|
+
throw error;
|
|
4335
|
+
}
|
|
4336
|
+
try {
|
|
4337
|
+
writeFileSync2(path11.join(markerPath, OWNER_FILE_NAME2), JSON.stringify(owner), {
|
|
4338
|
+
encoding: "utf-8",
|
|
4339
|
+
flag: "wx",
|
|
4340
|
+
mode: 384
|
|
4341
|
+
});
|
|
4342
|
+
return owner;
|
|
4343
|
+
} catch (error) {
|
|
4344
|
+
rmSync2(markerPath, { recursive: true, force: true });
|
|
4345
|
+
throw error;
|
|
4346
|
+
}
|
|
4347
|
+
}
|
|
4348
|
+
function removeExpiredReclaimMarker(leasePath, expectedOwner) {
|
|
4349
|
+
const marker = readReclaimOwner2(leasePath);
|
|
4350
|
+
const markerPath = reclaimPath(leasePath);
|
|
4351
|
+
if (!existsSync7(markerPath)) return false;
|
|
4352
|
+
if (marker && marker.expectedOwnerToken !== (expectedOwner?.token ?? null)) return false;
|
|
4353
|
+
if (marker && (reclaimerLiveness(marker) === "alive" || !isReclaimMarkerExpired(leasePath, marker))) return false;
|
|
4354
|
+
if (!marker && !isReclaimMarkerExpired(leasePath, null)) return false;
|
|
4355
|
+
const staleMarkerPath = `${markerPath}.stale.${marker?.pid ?? process.pid}.${marker?.token ?? randomUUID2()}.${randomUUID2()}`;
|
|
4356
|
+
try {
|
|
4357
|
+
renameSync2(markerPath, staleMarkerPath);
|
|
4358
|
+
} catch (error) {
|
|
4359
|
+
if (getErrorCode2(error) === "ENOENT") return false;
|
|
4360
|
+
throw error;
|
|
4361
|
+
}
|
|
4362
|
+
try {
|
|
4363
|
+
let claimedMarker = null;
|
|
4364
|
+
try {
|
|
4365
|
+
claimedMarker = parseReclaimOwner2(
|
|
4366
|
+
JSON.parse(readFileSync6(path11.join(staleMarkerPath, OWNER_FILE_NAME2), "utf-8"))
|
|
4367
|
+
);
|
|
4368
|
+
} catch {
|
|
4369
|
+
claimedMarker = null;
|
|
4370
|
+
}
|
|
4371
|
+
const markerMatches = marker ? claimedMarker !== null && sameReclaimOwner2(claimedMarker, marker) : claimedMarker === null;
|
|
4372
|
+
if (!markerMatches || !canReclaimLease(leasePath, expectedOwner)) {
|
|
4373
|
+
if (!existsSync7(markerPath) && existsSync7(staleMarkerPath)) renameSync2(staleMarkerPath, markerPath);
|
|
4374
|
+
return false;
|
|
4375
|
+
}
|
|
4376
|
+
rmSync2(staleMarkerPath, { recursive: true, force: true });
|
|
4377
|
+
return true;
|
|
4378
|
+
} catch (error) {
|
|
4379
|
+
if (getErrorCode2(error) === "ENOENT") return false;
|
|
4380
|
+
throw error;
|
|
4381
|
+
}
|
|
4382
|
+
}
|
|
4383
|
+
function canReclaimLease(leasePath, expectedOwner) {
|
|
4384
|
+
if (!existsSync7(leasePath)) return false;
|
|
4385
|
+
if (!expectedOwner) return false;
|
|
4386
|
+
const currentOwner = readOwner(leasePath);
|
|
4387
|
+
if (!currentOwner || !sameOwner2(currentOwner, expectedOwner)) return false;
|
|
4388
|
+
if (currentOwner.hostname === os4.hostname()) {
|
|
4389
|
+
return ownerLiveness(currentOwner) === "dead";
|
|
4390
|
+
}
|
|
4391
|
+
return isHeartbeatExpired(currentOwner);
|
|
4392
|
+
}
|
|
4393
|
+
function reclaimLease(leasePath, expectedOwner) {
|
|
4394
|
+
let marker = null;
|
|
4395
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
4396
|
+
marker = publishReclaimMarker(leasePath, expectedOwner);
|
|
4397
|
+
if (marker) break;
|
|
4398
|
+
if (attempt === 0 && removeExpiredReclaimMarker(leasePath, expectedOwner)) continue;
|
|
4399
|
+
return false;
|
|
4400
|
+
}
|
|
4401
|
+
if (!marker) return false;
|
|
4402
|
+
const markerPath = reclaimPath(leasePath);
|
|
4403
|
+
try {
|
|
4404
|
+
const currentMarker = readReclaimOwner2(leasePath);
|
|
4405
|
+
if (!currentMarker || !sameReclaimOwner2(currentMarker, marker) || !canReclaimLease(leasePath, expectedOwner)) {
|
|
4406
|
+
return false;
|
|
4407
|
+
}
|
|
4408
|
+
const stalePath = `${leasePath}.stale.${process.pid}.${marker.token}`;
|
|
4409
|
+
renameSync2(leasePath, stalePath);
|
|
4410
|
+
const quarantinedOwner = readOwner(stalePath);
|
|
4411
|
+
const quarantinedMarker = readReclaimOwner2(stalePath);
|
|
4412
|
+
if (!quarantinedMarker || !sameReclaimOwner2(quarantinedMarker, marker) || expectedOwner !== null && (!quarantinedOwner || !sameOwner2(quarantinedOwner, expectedOwner))) {
|
|
4413
|
+
if (!existsSync7(leasePath) && existsSync7(stalePath)) renameSync2(stalePath, leasePath);
|
|
4414
|
+
return false;
|
|
4415
|
+
}
|
|
4416
|
+
rmSync2(stalePath, { recursive: true, force: true });
|
|
4417
|
+
return true;
|
|
4418
|
+
} catch (error) {
|
|
4419
|
+
if (getErrorCode2(error) === "ENOENT") return false;
|
|
4420
|
+
throw error;
|
|
4421
|
+
} finally {
|
|
4422
|
+
const currentMarker = readReclaimOwner2(leasePath);
|
|
4423
|
+
if (currentMarker && sameReclaimOwner2(currentMarker, marker)) {
|
|
4424
|
+
rmSync2(markerPath, { recursive: true, force: true });
|
|
4425
|
+
}
|
|
4426
|
+
}
|
|
4427
|
+
}
|
|
4428
|
+
function acquireLease(identity) {
|
|
4429
|
+
mkdirSync2(identity.canonicalIndexPath, { recursive: true, mode: 448 });
|
|
4430
|
+
const canonicalIndexPath = realpathSync3.native(identity.canonicalIndexPath);
|
|
4431
|
+
const leasePath = path11.join(canonicalIndexPath, leaseDirectoryName({ ...identity, canonicalIndexPath }));
|
|
4432
|
+
for (let attempt = 0; attempt < 4; attempt += 1) {
|
|
4433
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
4434
|
+
const owner = {
|
|
4435
|
+
version: 1,
|
|
4436
|
+
pid: process.pid,
|
|
4437
|
+
hostname: os4.hostname(),
|
|
4438
|
+
startedAt: timestamp,
|
|
4439
|
+
heartbeatAt: timestamp,
|
|
4440
|
+
projectRoot: identity.canonicalProjectRoot,
|
|
4441
|
+
indexPath: canonicalIndexPath,
|
|
4442
|
+
token: randomUUID2()
|
|
4443
|
+
};
|
|
4444
|
+
if (publishLease(leasePath, owner)) {
|
|
4445
|
+
return { leasePath, owner };
|
|
4446
|
+
}
|
|
4447
|
+
const existingOwner = readOwner(leasePath);
|
|
4448
|
+
if (existingOwner) {
|
|
4449
|
+
if (canReclaimLease(leasePath, existingOwner) && reclaimLease(leasePath, existingOwner)) continue;
|
|
4450
|
+
return null;
|
|
4451
|
+
}
|
|
4452
|
+
return null;
|
|
4453
|
+
}
|
|
4454
|
+
return null;
|
|
4455
|
+
}
|
|
4456
|
+
function releaseLease(lease) {
|
|
4457
|
+
const currentOwner = readOwner(lease.leasePath);
|
|
4458
|
+
if (!currentOwner || !sameOwner2(currentOwner, lease.owner)) return false;
|
|
4459
|
+
const releasePath = `${lease.leasePath}.release.${lease.owner.pid}.${lease.owner.token}`;
|
|
4460
|
+
try {
|
|
4461
|
+
renameSync2(lease.leasePath, releasePath);
|
|
4462
|
+
} catch (error) {
|
|
4463
|
+
if (getErrorCode2(error) === "ENOENT") return false;
|
|
4464
|
+
throw error;
|
|
4465
|
+
}
|
|
4466
|
+
const claimedOwner = readOwner(releasePath);
|
|
4467
|
+
if (!claimedOwner || !sameOwner2(claimedOwner, lease.owner)) {
|
|
4468
|
+
if (!existsSync7(lease.leasePath) && existsSync7(releasePath)) {
|
|
4469
|
+
renameSync2(releasePath, lease.leasePath);
|
|
4470
|
+
}
|
|
4471
|
+
return false;
|
|
4472
|
+
}
|
|
4473
|
+
rmSync2(releasePath, { recursive: true, force: true });
|
|
4474
|
+
return true;
|
|
4475
|
+
}
|
|
4476
|
+
var BackgroundWorkerController = class {
|
|
4477
|
+
constructor(projectRoot3, host, config, hooks, identity) {
|
|
4478
|
+
this.projectRoot = projectRoot3;
|
|
4479
|
+
this.host = host;
|
|
4480
|
+
this.config = config;
|
|
4481
|
+
this.hooks = hooks;
|
|
4482
|
+
this.identity = identity;
|
|
4483
|
+
}
|
|
4484
|
+
projectRoot;
|
|
4485
|
+
host;
|
|
4486
|
+
config;
|
|
4487
|
+
hooks;
|
|
4488
|
+
identity;
|
|
4489
|
+
lease = null;
|
|
4490
|
+
watcher = null;
|
|
4491
|
+
leaderReady = Promise.resolve();
|
|
4492
|
+
heartbeatTimer = null;
|
|
4493
|
+
retryTimer = null;
|
|
4494
|
+
teardownRetryTimer = null;
|
|
4495
|
+
transition = Promise.resolve();
|
|
4496
|
+
stopPromise = null;
|
|
4497
|
+
stopped = false;
|
|
4498
|
+
stopping = false;
|
|
4499
|
+
losingLeadership = false;
|
|
4500
|
+
restartAfterStop = false;
|
|
4501
|
+
leaderWorkStopped = false;
|
|
4502
|
+
startingLeaderWork = false;
|
|
4503
|
+
stopAutoIndexOnTeardown = true;
|
|
4504
|
+
autoIndexStarted = false;
|
|
4505
|
+
reportedError = null;
|
|
4506
|
+
update(config, hooks, options) {
|
|
4507
|
+
const autoIndexWasEnabled = this.config.indexing.autoIndex;
|
|
4508
|
+
const shouldReplaceWatcher = this.watcher !== null && hooks.watcherFactory !== void 0 && (hooks.watcherFactory === null || hooks.replaceWatcher === true);
|
|
4509
|
+
this.config = config;
|
|
4510
|
+
this.hooks = {
|
|
4511
|
+
...this.hooks,
|
|
4512
|
+
...hooks,
|
|
4513
|
+
watcherFactory: hooks.watcherFactory === void 0 ? this.hooks.watcherFactory : hooks.watcherFactory,
|
|
4514
|
+
watcherFactoryForConfig: hooks.watcherFactoryForConfig === void 0 ? this.hooks.watcherFactoryForConfig : hooks.watcherFactoryForConfig
|
|
4515
|
+
};
|
|
4516
|
+
if (autoIndexWasEnabled && !config.indexing.autoIndex || options.restartAutoIndex === true && config.indexing.autoIndex && !this.startingLeaderWork) {
|
|
4517
|
+
this.autoIndexStarted = false;
|
|
4518
|
+
}
|
|
4519
|
+
if (!this.canRun()) {
|
|
4520
|
+
void this.stop().catch((error) => {
|
|
4521
|
+
console.error("[codebase-index] Failed to stop background worker after disabling automatic work:", error);
|
|
4522
|
+
});
|
|
4523
|
+
return;
|
|
4524
|
+
}
|
|
4525
|
+
if (shouldReplaceWatcher) {
|
|
4526
|
+
void this.enqueue(async () => {
|
|
4527
|
+
const watcher = this.watcher;
|
|
4528
|
+
if (watcher) {
|
|
4529
|
+
await watcher.stop();
|
|
4530
|
+
if (this.watcher === watcher) this.watcher = null;
|
|
4531
|
+
}
|
|
4532
|
+
if (this.lease && !this.stopped) this.startLeaderWork();
|
|
4533
|
+
}).catch((error) => {
|
|
4534
|
+
console.error("[codebase-index] Failed to replace background file watcher:", error);
|
|
4535
|
+
});
|
|
4536
|
+
}
|
|
4537
|
+
this.start();
|
|
4538
|
+
}
|
|
4539
|
+
startAfter(activation) {
|
|
4540
|
+
this.transition = activation.catch(() => void 0);
|
|
4541
|
+
this.start();
|
|
4542
|
+
}
|
|
4543
|
+
start() {
|
|
4544
|
+
if (!this.canRun() || this.losingLeadership) return;
|
|
4545
|
+
if (this.stopping) {
|
|
4546
|
+
this.restartAfterStop = true;
|
|
4547
|
+
return;
|
|
4548
|
+
}
|
|
4549
|
+
this.stopped = false;
|
|
4550
|
+
void this.enqueue(async () => {
|
|
4551
|
+
if (this.stopped || this.stopping || this.losingLeadership || !this.canRun()) return;
|
|
4552
|
+
if (!this.lease) {
|
|
4553
|
+
try {
|
|
4554
|
+
this.lease = acquireLease(this.identity);
|
|
4555
|
+
this.reportedError = null;
|
|
4556
|
+
} catch (error) {
|
|
4557
|
+
this.reportAcquireError(error);
|
|
4558
|
+
this.scheduleRetry();
|
|
4559
|
+
return;
|
|
4560
|
+
}
|
|
4561
|
+
}
|
|
4562
|
+
if (!this.lease) {
|
|
4563
|
+
this.scheduleRetry();
|
|
4564
|
+
return;
|
|
4565
|
+
}
|
|
4566
|
+
this.startHeartbeat();
|
|
4567
|
+
this.startLeaderWork();
|
|
4568
|
+
});
|
|
4569
|
+
}
|
|
4570
|
+
waitForStart() {
|
|
4571
|
+
return this.transition.catch(() => void 0).then(() => this.leaderReady);
|
|
4572
|
+
}
|
|
4573
|
+
requestRefresh(allowDisabledAutoIndex = false) {
|
|
4574
|
+
this.start();
|
|
4575
|
+
if (!this.isLeader()) {
|
|
4576
|
+
requestRefreshFromLeader(leasePathFor(this.identity), allowDisabledAutoIndex);
|
|
4577
|
+
return;
|
|
4578
|
+
}
|
|
4579
|
+
void this.enqueue(async () => {
|
|
4580
|
+
if (this.stopped || !this.lease) return;
|
|
4581
|
+
this.hooks.startAutoIndex("retrieval", allowDisabledAutoIndex);
|
|
4582
|
+
});
|
|
4583
|
+
}
|
|
4584
|
+
isLeader() {
|
|
4585
|
+
return this.lease !== null && !this.stopping && !this.losingLeadership;
|
|
4586
|
+
}
|
|
4587
|
+
isStopping() {
|
|
4588
|
+
return this.stopping;
|
|
4589
|
+
}
|
|
4590
|
+
getHooksForConfig(config) {
|
|
4591
|
+
const watcherFactoryForConfig = this.hooks.watcherFactoryForConfig;
|
|
4592
|
+
if (!watcherFactoryForConfig) return this.hooks;
|
|
4593
|
+
return {
|
|
4594
|
+
...this.hooks,
|
|
4595
|
+
watcherFactory: watcherFactoryForConfig(config),
|
|
4596
|
+
replaceWatcher: true
|
|
4597
|
+
};
|
|
4598
|
+
}
|
|
4599
|
+
attachWatcher(watcherFactory, watcherFactoryForConfig) {
|
|
4600
|
+
if (this.hooks.watcherFactory !== void 0) return;
|
|
4601
|
+
this.hooks = {
|
|
4602
|
+
...this.hooks,
|
|
4603
|
+
watcherFactory,
|
|
4604
|
+
watcherFactoryForConfig: watcherFactoryForConfig ?? this.hooks.watcherFactoryForConfig
|
|
4605
|
+
};
|
|
4606
|
+
this.start();
|
|
4607
|
+
}
|
|
4608
|
+
async stop(stopAutoIndex = true) {
|
|
4609
|
+
if (this.stopPromise) return this.stopPromise;
|
|
4610
|
+
this.stopped = true;
|
|
4611
|
+
this.stopping = true;
|
|
4612
|
+
this.stopAutoIndexOnTeardown &&= stopAutoIndex;
|
|
4613
|
+
this.clearRetryTimer();
|
|
4614
|
+
const attempt = this.enqueue(async () => {
|
|
4615
|
+
try {
|
|
4616
|
+
const lease = this.lease;
|
|
4617
|
+
if (this.leaderWorkStopped) {
|
|
4618
|
+
if (lease) {
|
|
4619
|
+
this.releaseStoppedLease(lease);
|
|
4620
|
+
} else {
|
|
4621
|
+
this.finishStoppedLease();
|
|
4622
|
+
}
|
|
4623
|
+
return;
|
|
4624
|
+
}
|
|
4625
|
+
const hadLeaderWork = lease !== null || this.watcher !== null || this.autoIndexStarted;
|
|
4626
|
+
const stopped = await this.stopLeaderWork(hadLeaderWork && this.stopAutoIndexOnTeardown);
|
|
4627
|
+
if (!lease) {
|
|
4628
|
+
this.finishStoppedLease();
|
|
4629
|
+
return;
|
|
4630
|
+
}
|
|
4631
|
+
if (!stopped.completed) {
|
|
4632
|
+
this.releaseLeaseWhenAutoIndexStops(lease, stopped.completion);
|
|
4633
|
+
return;
|
|
4634
|
+
}
|
|
4635
|
+
this.leaderWorkStopped = true;
|
|
4636
|
+
this.releaseStoppedLease(lease);
|
|
4637
|
+
} catch (error) {
|
|
4638
|
+
this.scheduleTeardownRetry();
|
|
4639
|
+
throw error;
|
|
4640
|
+
}
|
|
4641
|
+
});
|
|
4642
|
+
const completion = attempt.finally(() => {
|
|
4643
|
+
if (this.stopPromise === completion) this.stopPromise = null;
|
|
4644
|
+
});
|
|
4645
|
+
this.stopPromise = completion;
|
|
4646
|
+
return completion;
|
|
4647
|
+
}
|
|
4648
|
+
canRun() {
|
|
4649
|
+
return this.config.indexing.autoIndex || this.hooks.watcherFactory != null;
|
|
4650
|
+
}
|
|
4651
|
+
enqueue(operation) {
|
|
4652
|
+
const next = this.transition.catch(() => void 0).then(operation);
|
|
4653
|
+
this.transition = next;
|
|
4654
|
+
return next;
|
|
4655
|
+
}
|
|
4656
|
+
startLeaderWork() {
|
|
4657
|
+
if (this.stopped || this.stopping || this.losingLeadership) return;
|
|
4658
|
+
this.startingLeaderWork = true;
|
|
4659
|
+
try {
|
|
4660
|
+
if (this.config.indexing.autoIndex && !this.autoIndexStarted) {
|
|
4661
|
+
this.autoIndexStarted = true;
|
|
4662
|
+
this.hooks.startAutoIndex("startup");
|
|
4663
|
+
}
|
|
4664
|
+
if (!this.watcher && this.hooks.watcherFactory) {
|
|
4665
|
+
try {
|
|
4666
|
+
const watcher = this.hooks.watcherFactory();
|
|
4667
|
+
this.watcher = watcher;
|
|
4668
|
+
this.leaderReady = watcher.whenReady?.().catch((error) => {
|
|
4669
|
+
console.error("[codebase-index] Failed while waiting for background file watcher startup:", error);
|
|
4670
|
+
}) ?? Promise.resolve();
|
|
4671
|
+
} catch (error) {
|
|
4672
|
+
console.error("[codebase-index] Failed to start background file watcher:", error);
|
|
4673
|
+
this.leaderReady = Promise.resolve();
|
|
4674
|
+
}
|
|
4675
|
+
}
|
|
4676
|
+
} finally {
|
|
4677
|
+
this.startingLeaderWork = false;
|
|
4678
|
+
}
|
|
4679
|
+
}
|
|
4680
|
+
async stopLeaderWork(stopAutoIndex) {
|
|
4681
|
+
const watcher = this.watcher;
|
|
4682
|
+
let watcherError;
|
|
4683
|
+
if (watcher) {
|
|
4684
|
+
try {
|
|
4685
|
+
await watcher.stop();
|
|
4686
|
+
if (this.watcher === watcher) this.watcher = null;
|
|
4687
|
+
} catch (error) {
|
|
4688
|
+
watcherError = error;
|
|
4689
|
+
}
|
|
4690
|
+
}
|
|
4691
|
+
let autoIndexError;
|
|
4692
|
+
let autoIndexStop = {
|
|
4693
|
+
completed: true,
|
|
4694
|
+
completion: Promise.resolve()
|
|
4695
|
+
};
|
|
4696
|
+
if (stopAutoIndex) {
|
|
4697
|
+
try {
|
|
4698
|
+
autoIndexStop = await this.hooks.stopAutoIndex();
|
|
4699
|
+
this.autoIndexStarted = false;
|
|
4700
|
+
} catch (error) {
|
|
4701
|
+
autoIndexError = error;
|
|
4702
|
+
}
|
|
4703
|
+
}
|
|
4704
|
+
if (watcherError !== void 0 || autoIndexError !== void 0) {
|
|
4705
|
+
throw new BackgroundWorkerStopError(watcherError, autoIndexError);
|
|
4706
|
+
}
|
|
4707
|
+
return autoIndexStop;
|
|
4708
|
+
}
|
|
4709
|
+
releaseLeaseWhenAutoIndexStops(lease, completion) {
|
|
4710
|
+
void completion.then(
|
|
4711
|
+
() => {
|
|
4712
|
+
void this.enqueue(async () => {
|
|
4713
|
+
if (this.lease !== lease || !this.stopping) return;
|
|
4714
|
+
this.leaderWorkStopped = true;
|
|
4715
|
+
this.releaseStoppedLease(lease);
|
|
4716
|
+
}).catch((error) => {
|
|
4717
|
+
console.error("[codebase-index] Failed to release background worker lease after automatic indexing stopped:", error);
|
|
4718
|
+
this.scheduleTeardownRetry();
|
|
4719
|
+
});
|
|
4720
|
+
},
|
|
4721
|
+
(error) => {
|
|
4722
|
+
console.error("[codebase-index] Failed while waiting for automatic indexing to stop:", error);
|
|
4723
|
+
this.scheduleTeardownRetry();
|
|
4724
|
+
}
|
|
4725
|
+
);
|
|
4726
|
+
}
|
|
4727
|
+
releaseStoppedLease(lease) {
|
|
4728
|
+
if (this.lease !== lease) {
|
|
4729
|
+
this.finishStoppedLease();
|
|
4730
|
+
return;
|
|
4731
|
+
}
|
|
4732
|
+
releaseLease(lease);
|
|
4733
|
+
this.lease = null;
|
|
4734
|
+
this.finishStoppedLease();
|
|
4735
|
+
}
|
|
4736
|
+
finishStoppedLease() {
|
|
4737
|
+
this.leaderWorkStopped = false;
|
|
4738
|
+
this.stopAutoIndexOnTeardown = true;
|
|
4739
|
+
this.stopping = false;
|
|
4740
|
+
this.clearTimers();
|
|
4741
|
+
this.restartAfterTeardown();
|
|
4742
|
+
if (!this.stopped || this.stopping) return;
|
|
4743
|
+
const projectKey = projectLookupKey(this.projectRoot, this.host);
|
|
4744
|
+
const key = controllerKey(this.identity, this.host);
|
|
4745
|
+
if (workers.get(key) === this) workers.delete(key);
|
|
4746
|
+
if (workerKeysByProject.get(projectKey) === key) workerKeysByProject.delete(projectKey);
|
|
4747
|
+
}
|
|
4748
|
+
startHeartbeat() {
|
|
4749
|
+
if (this.heartbeatTimer) return;
|
|
4750
|
+
const heartbeat = () => {
|
|
4751
|
+
void this.heartbeat();
|
|
4752
|
+
};
|
|
4753
|
+
this.heartbeatTimer = setInterval(heartbeat, HEARTBEAT_INTERVAL_MS);
|
|
4754
|
+
this.heartbeatTimer.unref?.();
|
|
4755
|
+
}
|
|
4756
|
+
async heartbeat() {
|
|
4757
|
+
const lease = this.lease;
|
|
4758
|
+
if (!lease || this.losingLeadership || this.stopped && !this.stopping) return;
|
|
4759
|
+
if (hasActiveReclaimMarker(lease.leasePath, lease.owner)) {
|
|
4760
|
+
await this.loseLeadership();
|
|
4761
|
+
return;
|
|
4762
|
+
}
|
|
4763
|
+
const currentOwner = readOwner(lease.leasePath);
|
|
4764
|
+
if (!currentOwner || !sameOwner2(currentOwner, lease.owner)) {
|
|
4765
|
+
await this.loseLeadership();
|
|
4766
|
+
return;
|
|
4767
|
+
}
|
|
4768
|
+
try {
|
|
4769
|
+
const nextOwner = { ...lease.owner, heartbeatAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
4770
|
+
if (!writeHeartbeat(lease.leasePath, nextOwner)) {
|
|
4771
|
+
await this.loseLeadership();
|
|
4772
|
+
return;
|
|
4773
|
+
}
|
|
4774
|
+
lease.owner = nextOwner;
|
|
4775
|
+
const refreshRequest = !this.stopping ? consumeRefreshRequest(lease.leasePath) : null;
|
|
4776
|
+
if (refreshRequest) {
|
|
4777
|
+
this.hooks.startAutoIndex("retrieval", refreshRequest.allowDisabledAutoIndex);
|
|
4778
|
+
}
|
|
4779
|
+
} catch (error) {
|
|
4780
|
+
const ownerAfterError = readOwner(lease.leasePath);
|
|
4781
|
+
if (hasActiveReclaimMarker(lease.leasePath, lease.owner) || !ownerAfterError || !sameOwner2(ownerAfterError, lease.owner)) {
|
|
4782
|
+
await this.loseLeadership();
|
|
4783
|
+
return;
|
|
4784
|
+
}
|
|
4785
|
+
console.error("[codebase-index] Failed to renew background worker lease:", error);
|
|
4786
|
+
}
|
|
4787
|
+
}
|
|
4788
|
+
async loseLeadership() {
|
|
4789
|
+
if (this.losingLeadership) return;
|
|
4790
|
+
this.losingLeadership = true;
|
|
4791
|
+
this.clearHeartbeat();
|
|
4792
|
+
await this.enqueue(async () => this.stopAfterLeadershipLoss());
|
|
4793
|
+
}
|
|
4794
|
+
async stopAfterLeadershipLoss() {
|
|
4795
|
+
const lease = this.lease;
|
|
4796
|
+
if (!lease) {
|
|
4797
|
+
this.losingLeadership = false;
|
|
4798
|
+
return;
|
|
4799
|
+
}
|
|
4800
|
+
try {
|
|
4801
|
+
const stopped = await this.stopLeaderWork(true);
|
|
4802
|
+
this.lease = null;
|
|
4803
|
+
this.losingLeadership = false;
|
|
4804
|
+
if (stopped.completed) {
|
|
4805
|
+
this.scheduleRetry();
|
|
4806
|
+
} else {
|
|
4807
|
+
void stopped.completion.then(() => this.scheduleRetry());
|
|
4808
|
+
}
|
|
4809
|
+
} catch (error) {
|
|
4810
|
+
console.error("[codebase-index] Failed to stop background work after losing its lease:", error);
|
|
4811
|
+
this.scheduleLostLeadershipTeardownRetry();
|
|
4812
|
+
}
|
|
4813
|
+
}
|
|
4814
|
+
scheduleRetry() {
|
|
4815
|
+
if (this.stopped || !this.canRun() || this.retryTimer) return;
|
|
4816
|
+
this.retryTimer = setTimeout(() => {
|
|
4817
|
+
this.retryTimer = null;
|
|
4818
|
+
this.start();
|
|
4819
|
+
}, RETRY_DELAY_MS);
|
|
4820
|
+
this.retryTimer.unref?.();
|
|
4821
|
+
}
|
|
4822
|
+
scheduleTeardownRetry() {
|
|
4823
|
+
if (!this.stopping || this.teardownRetryTimer) return;
|
|
4824
|
+
this.teardownRetryTimer = setTimeout(() => {
|
|
4825
|
+
this.teardownRetryTimer = null;
|
|
4826
|
+
void this.stop(this.stopAutoIndexOnTeardown).catch((error) => {
|
|
4827
|
+
console.error("[codebase-index] Failed to retry background worker teardown:", error);
|
|
4828
|
+
});
|
|
4829
|
+
}, RETRY_DELAY_MS);
|
|
4830
|
+
this.teardownRetryTimer.unref?.();
|
|
4831
|
+
}
|
|
4832
|
+
restartAfterTeardown() {
|
|
4833
|
+
if (!this.restartAfterStop || !this.canRun() || this.losingLeadership) return;
|
|
4834
|
+
this.restartAfterStop = false;
|
|
4835
|
+
this.stopped = false;
|
|
4836
|
+
this.start();
|
|
4837
|
+
}
|
|
4838
|
+
scheduleLostLeadershipTeardownRetry() {
|
|
4839
|
+
if (this.stopped || !this.losingLeadership || this.retryTimer) return;
|
|
4840
|
+
this.retryTimer = setTimeout(() => {
|
|
4841
|
+
this.retryTimer = null;
|
|
4842
|
+
void this.enqueue(async () => this.stopAfterLeadershipLoss());
|
|
4843
|
+
}, RETRY_DELAY_MS);
|
|
4844
|
+
this.retryTimer.unref?.();
|
|
4845
|
+
}
|
|
4846
|
+
clearHeartbeat() {
|
|
4847
|
+
if (!this.heartbeatTimer) return;
|
|
4848
|
+
clearInterval(this.heartbeatTimer);
|
|
4849
|
+
this.heartbeatTimer = null;
|
|
4850
|
+
}
|
|
4851
|
+
clearTimers() {
|
|
4852
|
+
this.clearHeartbeat();
|
|
4853
|
+
this.clearRetryTimer();
|
|
4854
|
+
if (this.teardownRetryTimer) {
|
|
4855
|
+
clearTimeout(this.teardownRetryTimer);
|
|
4856
|
+
this.teardownRetryTimer = null;
|
|
4857
|
+
}
|
|
4858
|
+
}
|
|
4859
|
+
clearRetryTimer() {
|
|
4860
|
+
if (!this.retryTimer) return;
|
|
4861
|
+
clearTimeout(this.retryTimer);
|
|
4862
|
+
this.retryTimer = null;
|
|
4863
|
+
}
|
|
4864
|
+
reportAcquireError(error) {
|
|
4865
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
4866
|
+
if (this.reportedError === message) return;
|
|
4867
|
+
this.reportedError = message;
|
|
4868
|
+
console.error("[codebase-index] Failed to acquire background worker lease:", error);
|
|
4869
|
+
}
|
|
4870
|
+
};
|
|
4871
|
+
function configureBackgroundWorker(projectRoot3, host, config, hooks, options = {}) {
|
|
4872
|
+
const projectKey = projectLookupKey(projectRoot3, host);
|
|
4873
|
+
const identity = resolveIdentity(projectRoot3, config, host);
|
|
4874
|
+
const key = controllerKey(identity, host);
|
|
4875
|
+
const previousKey = workerKeysByProject.get(projectKey);
|
|
4876
|
+
if (previousKey && previousKey !== key) {
|
|
4877
|
+
const previous = workers.get(previousKey);
|
|
4878
|
+
const previousBarrier = workerReplacementBarriers.get(projectKey) ?? Promise.resolve();
|
|
4879
|
+
const stopPrevious = previous?.stop(options.stopPreviousAutoIndex ?? true) ?? Promise.resolve();
|
|
4880
|
+
const activation = Promise.all([previousBarrier, stopPrevious]).then(() => void 0);
|
|
4881
|
+
workerReplacementBarriers.set(projectKey, activation);
|
|
4882
|
+
workers.delete(previousKey);
|
|
4883
|
+
const worker2 = new BackgroundWorkerController(projectRoot3, host, config, hooks, identity);
|
|
4884
|
+
worker2.startAfter(activation);
|
|
4885
|
+
workers.set(key, worker2);
|
|
4886
|
+
workerKeysByProject.set(projectKey, key);
|
|
4887
|
+
return;
|
|
4888
|
+
}
|
|
4889
|
+
let worker = workers.get(key);
|
|
4890
|
+
if (!worker) {
|
|
4891
|
+
worker = new BackgroundWorkerController(projectRoot3, host, config, hooks, identity);
|
|
4892
|
+
workers.set(key, worker);
|
|
4893
|
+
} else {
|
|
4894
|
+
worker.update(config, hooks, options);
|
|
4895
|
+
}
|
|
4896
|
+
workerKeysByProject.set(projectKey, key);
|
|
4897
|
+
worker.start();
|
|
4898
|
+
}
|
|
4899
|
+
function updateBackgroundWorkerConfig(projectRoot3, host, config) {
|
|
4900
|
+
const projectKey = projectLookupKey(projectRoot3, host);
|
|
4901
|
+
const key = workerKeysByProject.get(projectKey);
|
|
4902
|
+
const worker = key ? workers.get(key) : void 0;
|
|
4903
|
+
if (!worker) return;
|
|
4904
|
+
configureBackgroundWorker(projectRoot3, host, config, worker.getHooksForConfig(config), {
|
|
4905
|
+
stopPreviousAutoIndex: false,
|
|
4906
|
+
restartAutoIndex: true
|
|
4907
|
+
});
|
|
4908
|
+
}
|
|
4909
|
+
function waitForBackgroundWorkerStart(projectRoot3, host) {
|
|
4910
|
+
const key = workerKeysByProject.get(projectLookupKey(projectRoot3, host));
|
|
4911
|
+
return workers.get(key ?? "")?.waitForStart() ?? Promise.resolve();
|
|
4912
|
+
}
|
|
4913
|
+
function requestBackgroundWorkerRefresh(projectRoot3, host, allowDisabledAutoIndex = false) {
|
|
4914
|
+
const key = workerKeysByProject.get(projectLookupKey(projectRoot3, host));
|
|
4915
|
+
workers.get(key ?? "")?.requestRefresh(allowDisabledAutoIndex);
|
|
4916
|
+
}
|
|
4917
|
+
function isBackgroundWorkerManaged(projectRoot3, host) {
|
|
4918
|
+
const key = workerKeysByProject.get(projectLookupKey(projectRoot3, host));
|
|
4919
|
+
return key !== void 0 && workers.has(key);
|
|
4920
|
+
}
|
|
4921
|
+
function isBackgroundWorkerLeader(projectRoot3, host) {
|
|
4922
|
+
const key = workerKeysByProject.get(projectLookupKey(projectRoot3, host));
|
|
4923
|
+
return key !== void 0 && workers.get(key)?.isLeader() === true;
|
|
4924
|
+
}
|
|
4925
|
+
async function stopBackgroundWorker(projectRoot3, host) {
|
|
4926
|
+
const projectKey = projectLookupKey(projectRoot3, host);
|
|
4927
|
+
const key = workerKeysByProject.get(projectKey);
|
|
4928
|
+
const worker = key ? workers.get(key) : void 0;
|
|
4929
|
+
if (!worker) return;
|
|
4930
|
+
await worker.stop();
|
|
4931
|
+
}
|
|
4932
|
+
|
|
4050
4933
|
// src/utils/files.ts
|
|
4051
4934
|
var import_ignore = __toESM(require_ignore(), 1);
|
|
4052
|
-
import { existsSync as
|
|
4053
|
-
import * as
|
|
4935
|
+
import { existsSync as existsSync8, readFileSync as readFileSync7, promises as fsPromises } from "fs";
|
|
4936
|
+
import * as path12 from "path";
|
|
4054
4937
|
var PROJECT_MARKERS = [
|
|
4055
4938
|
".git",
|
|
4056
4939
|
"package.json",
|
|
@@ -4068,7 +4951,7 @@ var PROJECT_MARKERS = [
|
|
|
4068
4951
|
];
|
|
4069
4952
|
function hasProjectMarker(projectRoot3) {
|
|
4070
4953
|
for (const marker of PROJECT_MARKERS) {
|
|
4071
|
-
if (
|
|
4954
|
+
if (existsSync8(path12.join(projectRoot3, marker))) {
|
|
4072
4955
|
return true;
|
|
4073
4956
|
}
|
|
4074
4957
|
}
|
|
@@ -4095,33 +4978,53 @@ function createIgnoreFilter(projectRoot3) {
|
|
|
4095
4978
|
"**/*build*/**"
|
|
4096
4979
|
];
|
|
4097
4980
|
ig.add(defaultIgnores);
|
|
4098
|
-
const gitignorePath =
|
|
4099
|
-
if (
|
|
4100
|
-
const gitignoreContent =
|
|
4981
|
+
const gitignorePath = path12.join(projectRoot3, ".gitignore");
|
|
4982
|
+
if (existsSync8(gitignorePath)) {
|
|
4983
|
+
const gitignoreContent = readFileSync7(gitignorePath, "utf-8");
|
|
4101
4984
|
ig.add(gitignoreContent);
|
|
4102
4985
|
}
|
|
4103
4986
|
return ig;
|
|
4104
4987
|
}
|
|
4105
|
-
function
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4988
|
+
function toPosixRelativePath(relativePath) {
|
|
4989
|
+
return relativePath.split(path12.sep).join("/");
|
|
4990
|
+
}
|
|
4991
|
+
function matchesAnyGlob(filePath, patterns) {
|
|
4992
|
+
const normalized = toPosixRelativePath(filePath);
|
|
4993
|
+
return patterns.some((pattern) => matchGlob(normalized, pattern));
|
|
4994
|
+
}
|
|
4995
|
+
function isExcludedByPatterns(relativePath, excludePatterns) {
|
|
4996
|
+
return matchesAnyGlob(relativePath, excludePatterns);
|
|
4997
|
+
}
|
|
4998
|
+
function isExcludedDirectory(relativePath, excludePatterns) {
|
|
4999
|
+
const normalized = toPosixRelativePath(relativePath);
|
|
5000
|
+
if (matchesAnyGlob(normalized, excludePatterns)) {
|
|
5001
|
+
return true;
|
|
4112
5002
|
}
|
|
4113
5003
|
for (const pattern of excludePatterns) {
|
|
4114
|
-
|
|
4115
|
-
|
|
5004
|
+
const posixPattern = toPosixRelativePath(pattern).replace(/\/+$/, "");
|
|
5005
|
+
if (!posixPattern.endsWith("/**")) {
|
|
5006
|
+
continue;
|
|
4116
5007
|
}
|
|
4117
|
-
|
|
4118
|
-
|
|
4119
|
-
if (matchGlob(relativePath, pattern)) {
|
|
5008
|
+
const directoryPattern = posixPattern.slice(0, -3);
|
|
5009
|
+
if (directoryPattern && matchesAnyGlob(normalized, [directoryPattern])) {
|
|
4120
5010
|
return true;
|
|
4121
5011
|
}
|
|
4122
5012
|
}
|
|
4123
5013
|
return false;
|
|
4124
5014
|
}
|
|
5015
|
+
function shouldIncludeFile(filePath, projectRoot3, includePatterns, excludePatterns, ignoreFilter) {
|
|
5016
|
+
const relativePath = toPosixRelativePath(path12.relative(projectRoot3, filePath));
|
|
5017
|
+
if (hasFilteredPathSegment(relativePath, "/")) {
|
|
5018
|
+
return false;
|
|
5019
|
+
}
|
|
5020
|
+
if (ignoreFilter.ignores(relativePath)) {
|
|
5021
|
+
return false;
|
|
5022
|
+
}
|
|
5023
|
+
if (isExcludedByPatterns(relativePath, excludePatterns)) {
|
|
5024
|
+
return false;
|
|
5025
|
+
}
|
|
5026
|
+
return matchesAnyGlob(relativePath, includePatterns);
|
|
5027
|
+
}
|
|
4125
5028
|
function matchGlob(filePath, pattern) {
|
|
4126
5029
|
if (pattern.startsWith("**/")) {
|
|
4127
5030
|
const withoutPrefix = pattern.slice(3);
|
|
@@ -4142,8 +5045,8 @@ async function* walkDirectory(dir, projectRoot3, includePatterns, excludePattern
|
|
|
4142
5045
|
const filesInDir = [];
|
|
4143
5046
|
const subdirs = [];
|
|
4144
5047
|
for (const entry of entries) {
|
|
4145
|
-
const fullPath =
|
|
4146
|
-
const relativePath =
|
|
5048
|
+
const fullPath = path12.join(dir, entry.name);
|
|
5049
|
+
const relativePath = toPosixRelativePath(path12.relative(projectRoot3, fullPath));
|
|
4147
5050
|
if (isHiddenPathSegment(entry.name)) {
|
|
4148
5051
|
if (entry.isDirectory()) {
|
|
4149
5052
|
skipped.push({ path: relativePath, reason: "excluded" });
|
|
@@ -4161,6 +5064,10 @@ async function* walkDirectory(dir, projectRoot3, includePatterns, excludePattern
|
|
|
4161
5064
|
continue;
|
|
4162
5065
|
}
|
|
4163
5066
|
if (entry.isDirectory()) {
|
|
5067
|
+
if (isExcludedDirectory(relativePath, excludePatterns)) {
|
|
5068
|
+
skipped.push({ path: relativePath, reason: "excluded" });
|
|
5069
|
+
continue;
|
|
5070
|
+
}
|
|
4164
5071
|
subdirs.push({ fullPath, relativePath });
|
|
4165
5072
|
} else if (entry.isFile()) {
|
|
4166
5073
|
const stat5 = await fsPromises.stat(fullPath);
|
|
@@ -4168,20 +5075,11 @@ async function* walkDirectory(dir, projectRoot3, includePatterns, excludePattern
|
|
|
4168
5075
|
skipped.push({ path: relativePath, reason: "too_large" });
|
|
4169
5076
|
continue;
|
|
4170
5077
|
}
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
continue;
|
|
4175
|
-
}
|
|
4176
|
-
}
|
|
4177
|
-
let matched = false;
|
|
4178
|
-
for (const pattern of includePatterns) {
|
|
4179
|
-
if (matchGlob(relativePath, pattern)) {
|
|
4180
|
-
matched = true;
|
|
4181
|
-
break;
|
|
4182
|
-
}
|
|
5078
|
+
if (isExcludedByPatterns(relativePath, excludePatterns)) {
|
|
5079
|
+
skipped.push({ path: relativePath, reason: "excluded" });
|
|
5080
|
+
continue;
|
|
4183
5081
|
}
|
|
4184
|
-
if (
|
|
5082
|
+
if (matchesAnyGlob(relativePath, includePatterns)) {
|
|
4185
5083
|
filesInDir.push({ path: fullPath, size: stat5.size });
|
|
4186
5084
|
}
|
|
4187
5085
|
}
|
|
@@ -4192,7 +5090,7 @@ async function* walkDirectory(dir, projectRoot3, includePatterns, excludePattern
|
|
|
4192
5090
|
yield f;
|
|
4193
5091
|
}
|
|
4194
5092
|
for (let i = options.maxFilesPerDirectory; i < filesInDir.length; i++) {
|
|
4195
|
-
skipped.push({ path:
|
|
5093
|
+
skipped.push({ path: toPosixRelativePath(path12.relative(projectRoot3, filesInDir[i].path)), reason: "excluded" });
|
|
4196
5094
|
}
|
|
4197
5095
|
const canRecurse = options.maxDepth === -1 || currentDepth < options.maxDepth;
|
|
4198
5096
|
if (canRecurse) {
|
|
@@ -4232,8 +5130,8 @@ async function collectFiles(projectRoot3, includePatterns, excludePatterns, maxF
|
|
|
4232
5130
|
if (additionalRoots && additionalRoots.length > 0) {
|
|
4233
5131
|
const normalizedRoots = /* @__PURE__ */ new Set();
|
|
4234
5132
|
for (const kbRoot of additionalRoots) {
|
|
4235
|
-
const resolved =
|
|
4236
|
-
|
|
5133
|
+
const resolved = path12.normalize(
|
|
5134
|
+
path12.isAbsolute(kbRoot) ? kbRoot : path12.resolve(projectRoot3, kbRoot)
|
|
4237
5135
|
);
|
|
4238
5136
|
normalizedRoots.add(resolved);
|
|
4239
5137
|
}
|
|
@@ -4274,7 +5172,7 @@ function getErrorMessage(error) {
|
|
|
4274
5172
|
return error instanceof Error ? error.message : String(error);
|
|
4275
5173
|
}
|
|
4276
5174
|
function runCommand(file, args, options) {
|
|
4277
|
-
return new Promise((
|
|
5175
|
+
return new Promise((resolve18, reject) => {
|
|
4278
5176
|
childProcess.execFile(
|
|
4279
5177
|
file,
|
|
4280
5178
|
args,
|
|
@@ -4284,7 +5182,7 @@ function runCommand(file, args, options) {
|
|
|
4284
5182
|
reject(error);
|
|
4285
5183
|
return;
|
|
4286
5184
|
}
|
|
4287
|
-
|
|
5185
|
+
resolve18(stdout);
|
|
4288
5186
|
}
|
|
4289
5187
|
);
|
|
4290
5188
|
});
|
|
@@ -4376,29 +5274,29 @@ var AutoIndexCancelledError = class extends Error {
|
|
|
4376
5274
|
function now() {
|
|
4377
5275
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
4378
5276
|
}
|
|
4379
|
-
function
|
|
4380
|
-
const resolved =
|
|
4381
|
-
if (
|
|
5277
|
+
function canonicalizePath2(targetPath) {
|
|
5278
|
+
const resolved = path13.resolve(targetPath);
|
|
5279
|
+
if (existsSync9(resolved)) {
|
|
4382
5280
|
try {
|
|
4383
|
-
return
|
|
5281
|
+
return realpathSync4.native(resolved);
|
|
4384
5282
|
} catch {
|
|
4385
5283
|
return resolved;
|
|
4386
5284
|
}
|
|
4387
5285
|
}
|
|
4388
|
-
const parent =
|
|
5286
|
+
const parent = path13.dirname(resolved);
|
|
4389
5287
|
if (parent === resolved) return resolved;
|
|
4390
|
-
return
|
|
5288
|
+
return path13.join(canonicalizePath2(parent), path13.basename(resolved));
|
|
4391
5289
|
}
|
|
4392
5290
|
function isHomeDirectory(projectRoot3) {
|
|
4393
|
-
return
|
|
5291
|
+
return canonicalizePath2(projectRoot3) === canonicalizePath2(os5.homedir());
|
|
4394
5292
|
}
|
|
4395
|
-
function
|
|
4396
|
-
return `${host}::${
|
|
5293
|
+
function projectLookupKey2(projectRoot3, host) {
|
|
5294
|
+
return `${host}::${canonicalizePath2(projectRoot3)}`;
|
|
4397
5295
|
}
|
|
4398
5296
|
function coordinatorKey(projectRoot3, config, host) {
|
|
4399
|
-
const canonicalProjectRoot =
|
|
5297
|
+
const canonicalProjectRoot = canonicalizePath2(projectRoot3);
|
|
4400
5298
|
const indexPath = resolveProjectIndexPath(projectRoot3, config.scope, host);
|
|
4401
|
-
return `${
|
|
5299
|
+
return `${canonicalizePath2(indexPath)}::${canonicalProjectRoot}`;
|
|
4402
5300
|
}
|
|
4403
5301
|
function getProjectSafety(projectRoot3, config) {
|
|
4404
5302
|
if (isHomeDirectory(projectRoot3)) {
|
|
@@ -4429,10 +5327,10 @@ function safeFailureMessage(error) {
|
|
|
4429
5327
|
}
|
|
4430
5328
|
function cancellableDelay(delayMs, signal) {
|
|
4431
5329
|
if (signal.aborted) return Promise.reject(new AutoIndexCancelledError());
|
|
4432
|
-
return new Promise((
|
|
5330
|
+
return new Promise((resolve18, reject) => {
|
|
4433
5331
|
const timer = setTimeout(() => {
|
|
4434
5332
|
signal.removeEventListener("abort", onAbort);
|
|
4435
|
-
|
|
5333
|
+
resolve18();
|
|
4436
5334
|
}, delayMs);
|
|
4437
5335
|
timer.unref?.();
|
|
4438
5336
|
const onAbort = () => {
|
|
@@ -4444,18 +5342,44 @@ function cancellableDelay(delayMs, signal) {
|
|
|
4444
5342
|
}
|
|
4445
5343
|
function withTimeout(promise, timeoutMs) {
|
|
4446
5344
|
if (timeoutMs <= 0) return Promise.resolve(void 0);
|
|
4447
|
-
return new Promise((
|
|
4448
|
-
const timer = setTimeout(() =>
|
|
5345
|
+
return new Promise((resolve18) => {
|
|
5346
|
+
const timer = setTimeout(() => resolve18(void 0), timeoutMs);
|
|
4449
5347
|
timer.unref?.();
|
|
4450
5348
|
void promise.then((value) => {
|
|
4451
5349
|
clearTimeout(timer);
|
|
4452
|
-
|
|
5350
|
+
resolve18(value);
|
|
4453
5351
|
}, () => {
|
|
4454
5352
|
clearTimeout(timer);
|
|
4455
|
-
|
|
5353
|
+
resolve18(void 0);
|
|
4456
5354
|
});
|
|
4457
5355
|
});
|
|
4458
5356
|
}
|
|
5357
|
+
function settlesWithin(promise, timeoutMs) {
|
|
5358
|
+
if (timeoutMs <= 0) return Promise.resolve(false);
|
|
5359
|
+
return new Promise((resolve18) => {
|
|
5360
|
+
let settled = false;
|
|
5361
|
+
const timer = setTimeout(() => {
|
|
5362
|
+
if (settled) return;
|
|
5363
|
+
settled = true;
|
|
5364
|
+
resolve18(false);
|
|
5365
|
+
}, timeoutMs);
|
|
5366
|
+
timer.unref?.();
|
|
5367
|
+
void promise.then(
|
|
5368
|
+
() => {
|
|
5369
|
+
if (settled) return;
|
|
5370
|
+
settled = true;
|
|
5371
|
+
clearTimeout(timer);
|
|
5372
|
+
resolve18(true);
|
|
5373
|
+
},
|
|
5374
|
+
() => {
|
|
5375
|
+
if (settled) return;
|
|
5376
|
+
settled = true;
|
|
5377
|
+
clearTimeout(timer);
|
|
5378
|
+
resolve18(true);
|
|
5379
|
+
}
|
|
5380
|
+
);
|
|
5381
|
+
});
|
|
5382
|
+
}
|
|
4459
5383
|
function requestPriority(request) {
|
|
4460
5384
|
if (request.force) return 4;
|
|
4461
5385
|
if (request.source === "manual") return 3;
|
|
@@ -4466,6 +5390,7 @@ function mergeRequests(current, next) {
|
|
|
4466
5390
|
if (!current) return next;
|
|
4467
5391
|
const preferred = requestPriority(next) > requestPriority(current) ? next : current;
|
|
4468
5392
|
return {
|
|
5393
|
+
allowDisabledAutoIndex: current.allowDisabledAutoIndex || next.allowDisabledAutoIndex,
|
|
4469
5394
|
checkFreshness: current.checkFreshness && next.checkFreshness,
|
|
4470
5395
|
force: current.force || next.force,
|
|
4471
5396
|
onProgress: next.onProgress ?? current.onProgress,
|
|
@@ -4527,11 +5452,11 @@ var AutoIndexCoordinator = class {
|
|
|
4527
5452
|
progress: this.status.progress ? { ...this.status.progress } : void 0
|
|
4528
5453
|
};
|
|
4529
5454
|
}
|
|
4530
|
-
start(source) {
|
|
5455
|
+
start(source, allowDisabledAutoIndex = false) {
|
|
4531
5456
|
this.refreshSafety();
|
|
4532
|
-
if (!this.registration.config.indexing.autoIndex || !this.registration.safeToRun) return null;
|
|
5457
|
+
if (!this.registration.config.indexing.autoIndex && !allowDisabledAutoIndex || !this.registration.safeToRun) return null;
|
|
4533
5458
|
if (this.status.state === "failed") return this.inFlight;
|
|
4534
|
-
return this.request({ checkFreshness: true, force: false, source });
|
|
5459
|
+
return this.request({ allowDisabledAutoIndex, checkFreshness: true, force: false, source });
|
|
4535
5460
|
}
|
|
4536
5461
|
request(request) {
|
|
4537
5462
|
if (this.stopped) {
|
|
@@ -4606,13 +5531,15 @@ var AutoIndexCoordinator = class {
|
|
|
4606
5531
|
retryAttempt: void 0
|
|
4607
5532
|
});
|
|
4608
5533
|
const inFlight = this.inFlight;
|
|
4609
|
-
|
|
4610
|
-
|
|
4611
|
-
|
|
4612
|
-
} else {
|
|
4613
|
-
await withTimeout(inFlight, SHUTDOWN_WAIT_MS);
|
|
4614
|
-
}
|
|
5534
|
+
const completion = inFlight ? inFlight.then(() => void 0, () => void 0) : Promise.resolve();
|
|
5535
|
+
if (!inFlight) {
|
|
5536
|
+
return { completed: true, completion };
|
|
4615
5537
|
}
|
|
5538
|
+
if (waitForCompletion) {
|
|
5539
|
+
await completion;
|
|
5540
|
+
return { completed: true, completion };
|
|
5541
|
+
}
|
|
5542
|
+
return { completed: await settlesWithin(completion, SHUTDOWN_WAIT_MS), completion };
|
|
4616
5543
|
}
|
|
4617
5544
|
startRequest(request) {
|
|
4618
5545
|
if (this.stopped || !this.canRun(request)) {
|
|
@@ -4801,7 +5728,7 @@ var AutoIndexCoordinator = class {
|
|
|
4801
5728
|
if (request.source === "manual" || request.source === "watcher") {
|
|
4802
5729
|
return true;
|
|
4803
5730
|
}
|
|
4804
|
-
return this.registration.safeToRun && this.registration.config.indexing.autoIndex;
|
|
5731
|
+
return this.registration.safeToRun && (this.registration.config.indexing.autoIndex || request.allowDisabledAutoIndex === true);
|
|
4805
5732
|
}
|
|
4806
5733
|
shouldDeferForBattery(request) {
|
|
4807
5734
|
return this.registration.backgroundIndexingPolicy !== null && (request.source === "startup" || request.source === "watcher");
|
|
@@ -4834,17 +5761,17 @@ var AutoIndexCoordinator = class {
|
|
|
4834
5761
|
}
|
|
4835
5762
|
}
|
|
4836
5763
|
waitForBatteryRetry(delayMs) {
|
|
4837
|
-
return new Promise((
|
|
5764
|
+
return new Promise((resolve18) => {
|
|
4838
5765
|
const timer = setTimeout(() => {
|
|
4839
5766
|
if (this.batteryRetryTimer === timer) {
|
|
4840
5767
|
this.batteryRetryTimer = null;
|
|
4841
5768
|
this.resolveBatteryRetry = null;
|
|
4842
5769
|
}
|
|
4843
|
-
|
|
5770
|
+
resolve18();
|
|
4844
5771
|
}, delayMs);
|
|
4845
5772
|
timer.unref?.();
|
|
4846
5773
|
this.batteryRetryTimer = timer;
|
|
4847
|
-
this.resolveBatteryRetry =
|
|
5774
|
+
this.resolveBatteryRetry = resolve18;
|
|
4848
5775
|
});
|
|
4849
5776
|
}
|
|
4850
5777
|
cancelBatteryRetry() {
|
|
@@ -4852,9 +5779,9 @@ var AutoIndexCoordinator = class {
|
|
|
4852
5779
|
clearTimeout(this.batteryRetryTimer);
|
|
4853
5780
|
this.batteryRetryTimer = null;
|
|
4854
5781
|
}
|
|
4855
|
-
const
|
|
5782
|
+
const resolve18 = this.resolveBatteryRetry;
|
|
4856
5783
|
this.resolveBatteryRetry = null;
|
|
4857
|
-
|
|
5784
|
+
resolve18?.();
|
|
4858
5785
|
}
|
|
4859
5786
|
finishBatteryCheck(batteryCheck) {
|
|
4860
5787
|
if (this.batteryCheck !== batteryCheck) return;
|
|
@@ -4867,12 +5794,25 @@ var AutoIndexCoordinator = class {
|
|
|
4867
5794
|
}
|
|
4868
5795
|
};
|
|
4869
5796
|
function getCoordinator(projectRoot3, host) {
|
|
4870
|
-
const key = coordinatorKeysByProject.get(
|
|
5797
|
+
const key = coordinatorKeysByProject.get(projectLookupKey2(projectRoot3, host));
|
|
4871
5798
|
return key ? coordinators.get(key) ?? null : null;
|
|
4872
5799
|
}
|
|
4873
|
-
function
|
|
4874
|
-
|
|
5800
|
+
function synchronizeBackgroundWorker(projectRoot3, host, config, safeToRun) {
|
|
5801
|
+
if (safeToRun) {
|
|
5802
|
+
updateBackgroundWorkerConfig(projectRoot3, host, config);
|
|
5803
|
+
return;
|
|
5804
|
+
}
|
|
5805
|
+
void stopBackgroundWorker(projectRoot3, host).catch((error) => {
|
|
5806
|
+
console.error("[codebase-index] Failed to stop background worker after project safety changed:", error);
|
|
5807
|
+
});
|
|
5808
|
+
}
|
|
5809
|
+
function configureAutoIndex(projectRoot3, host, config, getIndexer, options = {}) {
|
|
5810
|
+
const projectKey = projectLookupKey2(projectRoot3, host);
|
|
4875
5811
|
const safety = getProjectSafety(projectRoot3, config);
|
|
5812
|
+
const synchronizeWorker = options.synchronizeBackgroundWorker ?? true;
|
|
5813
|
+
if (options.preserveManagedWorker === true && isBackgroundWorkerManaged(projectRoot3, host)) {
|
|
5814
|
+
return;
|
|
5815
|
+
}
|
|
4876
5816
|
const registration = {
|
|
4877
5817
|
backgroundIndexingPolicy: createBackgroundIndexingPolicy(
|
|
4878
5818
|
config.indexing.pauseBackgroundIndexingOnBattery
|
|
@@ -4890,6 +5830,9 @@ function configureAutoIndex(projectRoot3, host, config, getIndexer) {
|
|
|
4890
5830
|
const stopPrevious = previousCoordinator?.stop(true) ?? Promise.resolve();
|
|
4891
5831
|
const activation = Promise.all([previousBarrier, stopPrevious]).then(() => void 0);
|
|
4892
5832
|
coordinatorReplacementBarriers.set(projectKey, activation);
|
|
5833
|
+
if (synchronizeWorker) {
|
|
5834
|
+
synchronizeBackgroundWorker(projectRoot3, host, config, safety.safeToRun);
|
|
5835
|
+
}
|
|
4893
5836
|
coordinators.delete(previousKey);
|
|
4894
5837
|
const coordinator2 = new AutoIndexCoordinator(registration);
|
|
4895
5838
|
coordinator2.activateAfter(activation);
|
|
@@ -4905,8 +5848,17 @@ function configureAutoIndex(projectRoot3, host, config, getIndexer) {
|
|
|
4905
5848
|
coordinator.update(registration);
|
|
4906
5849
|
}
|
|
4907
5850
|
coordinatorKeysByProject.set(projectKey, key);
|
|
5851
|
+
if (synchronizeWorker) {
|
|
5852
|
+
synchronizeBackgroundWorker(projectRoot3, host, config, safety.safeToRun);
|
|
5853
|
+
}
|
|
5854
|
+
}
|
|
5855
|
+
function startAutoIndexForBackgroundWorker(projectRoot3, host, source = "startup", allowDisabledAutoIndex = false) {
|
|
5856
|
+
return getCoordinator(projectRoot3, host)?.start(source, allowDisabledAutoIndex) ?? null;
|
|
4908
5857
|
}
|
|
4909
5858
|
function requestBackgroundIndex(projectRoot3, host) {
|
|
5859
|
+
if (isBackgroundWorkerManaged(projectRoot3, host) && !isBackgroundWorkerLeader(projectRoot3, host)) {
|
|
5860
|
+
return null;
|
|
5861
|
+
}
|
|
4910
5862
|
return getCoordinator(projectRoot3, host)?.request({
|
|
4911
5863
|
checkFreshness: false,
|
|
4912
5864
|
force: false,
|
|
@@ -4946,15 +5898,23 @@ async function waitForAutoIndexForRetrieval(projectRoot3, host) {
|
|
|
4946
5898
|
};
|
|
4947
5899
|
}
|
|
4948
5900
|
try {
|
|
4949
|
-
|
|
5901
|
+
const readiness = await getSearchReadiness(coordinator);
|
|
5902
|
+
if (readiness.searchable) {
|
|
5903
|
+
return { ready: true };
|
|
5904
|
+
}
|
|
5905
|
+
if (readiness.blocked) return unavailableSnapshotResult(readiness.reason);
|
|
4950
5906
|
} catch {
|
|
4951
5907
|
}
|
|
4952
|
-
const job =
|
|
5908
|
+
const job = startRetrievalRefresh(projectRoot3, host, coordinator);
|
|
4953
5909
|
if (job) {
|
|
4954
5910
|
await withTimeout(job, coordinator.getWaitMs());
|
|
5911
|
+
} else if (isBackgroundWorkerManaged(projectRoot3, host)) {
|
|
5912
|
+
await waitForPublishedSnapshot(coordinator, coordinator.getWaitMs());
|
|
4955
5913
|
}
|
|
4956
5914
|
try {
|
|
4957
|
-
|
|
5915
|
+
const readiness = await getSearchReadiness(coordinator);
|
|
5916
|
+
if (readiness.searchable) return { ready: true };
|
|
5917
|
+
if (readiness.blocked) return unavailableSnapshotResult(readiness.reason);
|
|
4958
5918
|
} catch {
|
|
4959
5919
|
}
|
|
4960
5920
|
const status = coordinator.snapshot();
|
|
@@ -4975,21 +5935,52 @@ async function waitForAutoIndexForRetrieval(projectRoot3, host) {
|
|
|
4975
5935
|
text: `Automatic indexing is ${status.state}. Retry shortly or call index_status for progress. You can also run index_codebase explicitly.`
|
|
4976
5936
|
};
|
|
4977
5937
|
}
|
|
4978
|
-
async function
|
|
4979
|
-
|
|
5938
|
+
async function stopAutoIndexForBackgroundWorker(projectRoot3, host, waitForCompletion = false) {
|
|
5939
|
+
const coordinator = getCoordinator(projectRoot3, host);
|
|
5940
|
+
if (!coordinator) {
|
|
5941
|
+
return { completed: true, completion: Promise.resolve() };
|
|
5942
|
+
}
|
|
5943
|
+
return coordinator.stop(waitForCompletion);
|
|
4980
5944
|
}
|
|
4981
|
-
async function
|
|
5945
|
+
async function getSearchReadiness(coordinator) {
|
|
4982
5946
|
const indexer = coordinator.getIndexer();
|
|
4983
5947
|
if (indexer.getIndexFreshness) {
|
|
4984
5948
|
const freshness = await indexer.getIndexFreshness();
|
|
4985
|
-
|
|
5949
|
+
const searchable = freshness.readable && freshness.current && freshness.reason === "current";
|
|
5950
|
+
return {
|
|
5951
|
+
blocked: freshness.reason === "unreadable" || freshness.reason === "incompatible" || freshness.reason === "failed-batches" || freshness.reason === "migration-required",
|
|
5952
|
+
reason: freshness.reason,
|
|
5953
|
+
searchable
|
|
5954
|
+
};
|
|
5955
|
+
}
|
|
5956
|
+
const indexed = (await indexer.getStatus()).indexed;
|
|
5957
|
+
return { blocked: false, searchable: indexed };
|
|
5958
|
+
}
|
|
5959
|
+
function unavailableSnapshotResult(reason) {
|
|
5960
|
+
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.";
|
|
5961
|
+
return {
|
|
5962
|
+
ready: false,
|
|
5963
|
+
text: `${detail} Run index_codebase before retrying retrieval.`
|
|
5964
|
+
};
|
|
5965
|
+
}
|
|
5966
|
+
function startRetrievalRefresh(projectRoot3, host, coordinator) {
|
|
5967
|
+
if (isBackgroundWorkerManaged(projectRoot3, host)) {
|
|
5968
|
+
requestBackgroundWorkerRefresh(projectRoot3, host, true);
|
|
5969
|
+
return isBackgroundWorkerLeader(projectRoot3, host) ? coordinator.currentJob() : null;
|
|
5970
|
+
}
|
|
5971
|
+
return coordinator.start("retrieval") ?? coordinator.currentJob();
|
|
5972
|
+
}
|
|
5973
|
+
async function waitForPublishedSnapshot(coordinator, waitMs) {
|
|
5974
|
+
const deadline = Date.now() + waitMs;
|
|
5975
|
+
while (Date.now() < deadline) {
|
|
5976
|
+
if ((await getSearchReadiness(coordinator)).searchable) return;
|
|
5977
|
+
await new Promise((resolve18) => setTimeout(resolve18, Math.min(250, deadline - Date.now())));
|
|
4986
5978
|
}
|
|
4987
|
-
return (await indexer.getStatus()).indexed;
|
|
4988
5979
|
}
|
|
4989
5980
|
|
|
4990
5981
|
// src/tools/config-state.ts
|
|
4991
|
-
import { existsSync as
|
|
4992
|
-
import * as
|
|
5982
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
5983
|
+
import * as path14 from "path";
|
|
4993
5984
|
function normalizeKnowledgeBasePaths(config, projectRoot3) {
|
|
4994
5985
|
const normalized = { ...config };
|
|
4995
5986
|
if (Array.isArray(normalized.knowledgeBases)) {
|
|
@@ -5016,10 +6007,10 @@ function loadEditableConfig(projectRoot3, host) {
|
|
|
5016
6007
|
}
|
|
5017
6008
|
function saveConfig(projectRoot3, config, host) {
|
|
5018
6009
|
const configPath = getConfigPath(projectRoot3, host);
|
|
5019
|
-
const configDir =
|
|
5020
|
-
const configBaseDir =
|
|
5021
|
-
if (!
|
|
5022
|
-
|
|
6010
|
+
const configDir = path14.dirname(configPath);
|
|
6011
|
+
const configBaseDir = path14.dirname(configDir);
|
|
6012
|
+
if (!existsSync10(configDir)) {
|
|
6013
|
+
mkdirSync3(configDir, { recursive: true });
|
|
5023
6014
|
}
|
|
5024
6015
|
const serializableConfig = { ...config };
|
|
5025
6016
|
if (Array.isArray(serializableConfig.knowledgeBases)) {
|
|
@@ -5027,12 +6018,12 @@ function saveConfig(projectRoot3, config, host) {
|
|
|
5027
6018
|
(kb) => serializeConfigPathValue(kb, configBaseDir)
|
|
5028
6019
|
);
|
|
5029
6020
|
}
|
|
5030
|
-
|
|
6021
|
+
writeFileSync3(configPath, JSON.stringify(serializableConfig, null, 2) + "\n", "utf-8");
|
|
5031
6022
|
}
|
|
5032
6023
|
|
|
5033
6024
|
// src/indexer/index.ts
|
|
5034
|
-
import { existsSync as
|
|
5035
|
-
import * as
|
|
6025
|
+
import { existsSync as existsSync12, readFileSync as readFileSync9, statSync as statSync4, writeFileSync as writeFileSync4, renameSync as renameSync4, unlinkSync as unlinkSync2, mkdirSync as mkdirSync5, promises as fsPromises3 } from "fs";
|
|
6026
|
+
import * as path20 from "path";
|
|
5036
6027
|
import { performance as performance2 } from "perf_hooks";
|
|
5037
6028
|
import { execFile as execFile5 } from "child_process";
|
|
5038
6029
|
import { promisify as promisify4 } from "util";
|
|
@@ -5059,7 +6050,7 @@ function pTimeout(promise, options) {
|
|
|
5059
6050
|
} = options;
|
|
5060
6051
|
let timer;
|
|
5061
6052
|
let abortHandler;
|
|
5062
|
-
const wrappedPromise = new Promise((
|
|
6053
|
+
const wrappedPromise = new Promise((resolve18, reject) => {
|
|
5063
6054
|
if (typeof milliseconds !== "number" || Math.sign(milliseconds) !== 1) {
|
|
5064
6055
|
throw new TypeError(`Expected \`milliseconds\` to be a positive number, got \`${milliseconds}\``);
|
|
5065
6056
|
}
|
|
@@ -5073,7 +6064,7 @@ function pTimeout(promise, options) {
|
|
|
5073
6064
|
};
|
|
5074
6065
|
signal.addEventListener("abort", abortHandler, { once: true });
|
|
5075
6066
|
}
|
|
5076
|
-
promise.then(
|
|
6067
|
+
promise.then(resolve18, reject);
|
|
5077
6068
|
if (milliseconds === Number.POSITIVE_INFINITY) {
|
|
5078
6069
|
return;
|
|
5079
6070
|
}
|
|
@@ -5081,7 +6072,7 @@ function pTimeout(promise, options) {
|
|
|
5081
6072
|
timer = customTimers.setTimeout.call(void 0, () => {
|
|
5082
6073
|
if (fallback) {
|
|
5083
6074
|
try {
|
|
5084
|
-
|
|
6075
|
+
resolve18(fallback());
|
|
5085
6076
|
} catch (error) {
|
|
5086
6077
|
reject(error);
|
|
5087
6078
|
}
|
|
@@ -5091,7 +6082,7 @@ function pTimeout(promise, options) {
|
|
|
5091
6082
|
promise.cancel();
|
|
5092
6083
|
}
|
|
5093
6084
|
if (message === false) {
|
|
5094
|
-
|
|
6085
|
+
resolve18();
|
|
5095
6086
|
} else if (message instanceof Error) {
|
|
5096
6087
|
reject(message);
|
|
5097
6088
|
} else {
|
|
@@ -5493,7 +6484,7 @@ var PQueue = class extends import_index.default {
|
|
|
5493
6484
|
// Assign unique ID if not provided
|
|
5494
6485
|
id: options.id ?? (this.#idAssigner++).toString()
|
|
5495
6486
|
};
|
|
5496
|
-
return new Promise((
|
|
6487
|
+
return new Promise((resolve18, reject) => {
|
|
5497
6488
|
const taskSymbol = /* @__PURE__ */ Symbol(`task-${options.id}`);
|
|
5498
6489
|
let cleanupQueueAbortHandler = () => void 0;
|
|
5499
6490
|
const run = async () => {
|
|
@@ -5533,7 +6524,7 @@ var PQueue = class extends import_index.default {
|
|
|
5533
6524
|
})]);
|
|
5534
6525
|
}
|
|
5535
6526
|
const result = await operation;
|
|
5536
|
-
|
|
6527
|
+
resolve18(result);
|
|
5537
6528
|
this.emit("completed", result);
|
|
5538
6529
|
} catch (error) {
|
|
5539
6530
|
reject(error);
|
|
@@ -5721,13 +6712,13 @@ var PQueue = class extends import_index.default {
|
|
|
5721
6712
|
});
|
|
5722
6713
|
}
|
|
5723
6714
|
async #onEvent(event, filter) {
|
|
5724
|
-
return new Promise((
|
|
6715
|
+
return new Promise((resolve18) => {
|
|
5725
6716
|
const listener = () => {
|
|
5726
6717
|
if (filter && !filter()) {
|
|
5727
6718
|
return;
|
|
5728
6719
|
}
|
|
5729
6720
|
this.off(event, listener);
|
|
5730
|
-
|
|
6721
|
+
resolve18();
|
|
5731
6722
|
};
|
|
5732
6723
|
this.on(event, listener);
|
|
5733
6724
|
});
|
|
@@ -6013,7 +7004,7 @@ async function onAttemptFailure({ error, attemptNumber, retriesConsumed, startTi
|
|
|
6013
7004
|
const finalDelay = Math.min(delayTime, remainingTime);
|
|
6014
7005
|
options.signal?.throwIfAborted();
|
|
6015
7006
|
if (finalDelay > 0) {
|
|
6016
|
-
await new Promise((
|
|
7007
|
+
await new Promise((resolve18, reject) => {
|
|
6017
7008
|
const onAbort = () => {
|
|
6018
7009
|
clearTimeout(timeoutToken);
|
|
6019
7010
|
options.signal?.removeEventListener("abort", onAbort);
|
|
@@ -6021,7 +7012,7 @@ async function onAttemptFailure({ error, attemptNumber, retriesConsumed, startTi
|
|
|
6021
7012
|
};
|
|
6022
7013
|
const timeoutToken = setTimeout(() => {
|
|
6023
7014
|
options.signal?.removeEventListener("abort", onAbort);
|
|
6024
|
-
|
|
7015
|
+
resolve18();
|
|
6025
7016
|
}, finalDelay);
|
|
6026
7017
|
if (options.unref) {
|
|
6027
7018
|
timeoutToken.unref?.();
|
|
@@ -6139,17 +7130,17 @@ function validateExternalUrl(urlString) {
|
|
|
6139
7130
|
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
6140
7131
|
return { valid: false, reason: `Blocked protocol: ${parsed.protocol}` };
|
|
6141
7132
|
}
|
|
6142
|
-
const
|
|
6143
|
-
if (BLOCKED_HOSTNAMES.has(
|
|
6144
|
-
return { valid: false, reason: `Blocked: cloud metadata service (${
|
|
7133
|
+
const hostname3 = parsed.hostname.toLowerCase();
|
|
7134
|
+
if (BLOCKED_HOSTNAMES.has(hostname3)) {
|
|
7135
|
+
return { valid: false, reason: `Blocked: cloud metadata service (${hostname3})` };
|
|
6145
7136
|
}
|
|
6146
7137
|
for (const pattern of BLOCKED_METADATA_IPS) {
|
|
6147
|
-
if (pattern.test(
|
|
6148
|
-
return { valid: false, reason: `Blocked: cloud metadata IP (${
|
|
7138
|
+
if (pattern.test(hostname3)) {
|
|
7139
|
+
return { valid: false, reason: `Blocked: cloud metadata IP (${hostname3})` };
|
|
6149
7140
|
}
|
|
6150
7141
|
}
|
|
6151
|
-
if (/^169\.254\./.test(
|
|
6152
|
-
return { valid: false, reason: `Blocked: link-local address (${
|
|
7142
|
+
if (/^169\.254\./.test(hostname3)) {
|
|
7143
|
+
return { valid: false, reason: `Blocked: link-local address (${hostname3})` };
|
|
6153
7144
|
}
|
|
6154
7145
|
return { valid: true };
|
|
6155
7146
|
}
|
|
@@ -7161,8 +8152,8 @@ function extractParamNames(params) {
|
|
|
7161
8152
|
}
|
|
7162
8153
|
|
|
7163
8154
|
// src/native/binding.ts
|
|
7164
|
-
import * as
|
|
7165
|
-
import * as
|
|
8155
|
+
import * as os6 from "os";
|
|
8156
|
+
import * as path15 from "path";
|
|
7166
8157
|
import * as module from "module";
|
|
7167
8158
|
import { fileURLToPath } from "url";
|
|
7168
8159
|
|
|
@@ -7198,7 +8189,7 @@ var MCP_BINARY_CURRENT_NAME = CURRENT_PRODUCT.mcpBinary;
|
|
|
7198
8189
|
var STABLE_NATIVE_BINARY_NAME = IDENTITY_CATALOG.native.binaryName;
|
|
7199
8190
|
|
|
7200
8191
|
// src/native/binding.ts
|
|
7201
|
-
function getNativeBindingFilename(platform2 =
|
|
8192
|
+
function getNativeBindingFilename(platform2 = os6.platform(), arch2 = os6.arch()) {
|
|
7202
8193
|
if (platform2 === "darwin" && arch2 === "arm64") {
|
|
7203
8194
|
return `${STABLE_NATIVE_BINARY_NAME}.darwin-arm64.node`;
|
|
7204
8195
|
}
|
|
@@ -7216,25 +8207,25 @@ function getNativeBindingFilename(platform2 = os5.platform(), arch2 = os5.arch()
|
|
|
7216
8207
|
}
|
|
7217
8208
|
throw new Error(`Unsupported platform: ${platform2}-${arch2}`);
|
|
7218
8209
|
}
|
|
7219
|
-
function resolveNativeBindingPath(packageRoot, platform2 =
|
|
7220
|
-
return
|
|
8210
|
+
function resolveNativeBindingPath(packageRoot, platform2 = os6.platform(), arch2 = os6.arch()) {
|
|
8211
|
+
return path15.join(packageRoot, "native", getNativeBindingFilename(platform2, arch2));
|
|
7221
8212
|
}
|
|
7222
8213
|
function getNativeBinding() {
|
|
7223
8214
|
let currentDir;
|
|
7224
8215
|
let requireTarget;
|
|
7225
8216
|
if (typeof import.meta !== "undefined" && import.meta.url) {
|
|
7226
|
-
currentDir =
|
|
8217
|
+
currentDir = path15.dirname(fileURLToPath(import.meta.url));
|
|
7227
8218
|
requireTarget = import.meta.url;
|
|
7228
8219
|
} else if (typeof __dirname !== "undefined") {
|
|
7229
8220
|
currentDir = __dirname;
|
|
7230
8221
|
requireTarget = __filename;
|
|
7231
8222
|
} else {
|
|
7232
8223
|
currentDir = process.cwd();
|
|
7233
|
-
requireTarget =
|
|
8224
|
+
requireTarget = path15.join(currentDir, "index.js");
|
|
7234
8225
|
}
|
|
7235
8226
|
const normalizedDir = currentDir.replace(/\\/g, "/");
|
|
7236
|
-
const isDevMode = normalizedDir.includes("/src/native") || currentDir.includes(
|
|
7237
|
-
const packageRoot = isDevMode ?
|
|
8227
|
+
const isDevMode = normalizedDir.includes("/src/native") || currentDir.includes(path15.join("src", "native"));
|
|
8228
|
+
const packageRoot = isDevMode ? path15.resolve(currentDir, "../..") : path15.resolve(currentDir, "..");
|
|
7238
8229
|
const nativePath = resolveNativeBindingPath(packageRoot);
|
|
7239
8230
|
const require2 = module.createRequire(requireTarget);
|
|
7240
8231
|
return require2(nativePath);
|
|
@@ -7818,8 +8809,8 @@ var Database = class _Database {
|
|
|
7818
8809
|
|
|
7819
8810
|
// src/git/branch-materialization.ts
|
|
7820
8811
|
import { promises as fsPromises2 } from "fs";
|
|
7821
|
-
import * as
|
|
7822
|
-
import * as
|
|
8812
|
+
import * as os7 from "os";
|
|
8813
|
+
import * as path16 from "path";
|
|
7823
8814
|
|
|
7824
8815
|
// src/git/branch-resolution.ts
|
|
7825
8816
|
import { execFile as execFile2 } from "child_process";
|
|
@@ -8138,13 +9129,13 @@ async function isWorktreeRegistered(projectRoot3, worktreePath) {
|
|
|
8138
9129
|
return false;
|
|
8139
9130
|
}
|
|
8140
9131
|
function isPathWithinRoot(filePath, rootPath) {
|
|
8141
|
-
const relative13 =
|
|
8142
|
-
return relative13 === "" || !relative13.startsWith(`..${
|
|
9132
|
+
const relative13 = path16.relative(path16.resolve(rootPath), path16.resolve(filePath));
|
|
9133
|
+
return relative13 === "" || !relative13.startsWith(`..${path16.sep}`) && relative13 !== ".." && !path16.isAbsolute(relative13);
|
|
8143
9134
|
}
|
|
8144
9135
|
async function pruneExactMissingWorktreeRegistration(projectRoot3, worktreePath) {
|
|
8145
9136
|
if (await pathExists(worktreePath)) return false;
|
|
8146
9137
|
const commonDir = await runGit(projectRoot3, ["rev-parse", "--path-format=absolute", "--git-common-dir"]);
|
|
8147
|
-
const registrationsRoot =
|
|
9138
|
+
const registrationsRoot = path16.join(commonDir, "worktrees");
|
|
8148
9139
|
let entries;
|
|
8149
9140
|
try {
|
|
8150
9141
|
entries = await fsPromises2.readdir(registrationsRoot, { withFileTypes: true });
|
|
@@ -8155,16 +9146,16 @@ async function pruneExactMissingWorktreeRegistration(projectRoot3, worktreePath)
|
|
|
8155
9146
|
const target = canonicalizePathForComparison(worktreePath);
|
|
8156
9147
|
for (const entry of entries) {
|
|
8157
9148
|
if (!entry.isDirectory()) continue;
|
|
8158
|
-
const registrationPath =
|
|
9149
|
+
const registrationPath = path16.join(registrationsRoot, entry.name);
|
|
8159
9150
|
if (!isPathWithinRoot(registrationPath, registrationsRoot)) continue;
|
|
8160
9151
|
let gitdirPath;
|
|
8161
9152
|
try {
|
|
8162
|
-
gitdirPath = (await fsPromises2.readFile(
|
|
9153
|
+
gitdirPath = (await fsPromises2.readFile(path16.join(registrationPath, "gitdir"), "utf8")).trim();
|
|
8163
9154
|
} catch {
|
|
8164
9155
|
continue;
|
|
8165
9156
|
}
|
|
8166
|
-
const resolvedGitdirPath =
|
|
8167
|
-
if (canonicalizePathForComparison(
|
|
9157
|
+
const resolvedGitdirPath = path16.isAbsolute(gitdirPath) ? gitdirPath : path16.resolve(registrationPath, gitdirPath);
|
|
9158
|
+
if (canonicalizePathForComparison(path16.dirname(resolvedGitdirPath)) !== target) continue;
|
|
8168
9159
|
await fsPromises2.rm(registrationPath, { recursive: true, force: true });
|
|
8169
9160
|
return true;
|
|
8170
9161
|
}
|
|
@@ -8182,7 +9173,7 @@ async function removeWorktree(projectRoot3, worktreePath) {
|
|
|
8182
9173
|
registered = await isWorktreeRegistered(projectRoot3, worktreePath);
|
|
8183
9174
|
} catch (error) {
|
|
8184
9175
|
errors.push(asError(error));
|
|
8185
|
-
throw new AggregateError(errors, `Could not verify temporary worktree deregistration; preserved ${
|
|
9176
|
+
throw new AggregateError(errors, `Could not verify temporary worktree deregistration; preserved ${path16.dirname(worktreePath)}`);
|
|
8186
9177
|
}
|
|
8187
9178
|
if (registered) {
|
|
8188
9179
|
try {
|
|
@@ -8198,7 +9189,7 @@ async function removeWorktree(projectRoot3, worktreePath) {
|
|
|
8198
9189
|
registered = await isWorktreeRegistered(projectRoot3, worktreePath);
|
|
8199
9190
|
} catch (error) {
|
|
8200
9191
|
errors.push(asError(error));
|
|
8201
|
-
throw new AggregateError(errors, `Could not verify temporary worktree deregistration; preserved ${
|
|
9192
|
+
throw new AggregateError(errors, `Could not verify temporary worktree deregistration; preserved ${path16.dirname(worktreePath)}`);
|
|
8202
9193
|
}
|
|
8203
9194
|
}
|
|
8204
9195
|
if (registered && !await pathExists(worktreePath)) {
|
|
@@ -8211,13 +9202,13 @@ async function removeWorktree(projectRoot3, worktreePath) {
|
|
|
8211
9202
|
}
|
|
8212
9203
|
if (registered) {
|
|
8213
9204
|
errors.push(new Error(`Temporary worktree remains registered: ${worktreePath}`));
|
|
8214
|
-
throw new AggregateError(errors, `Failed to deregister temporary worktree; preserved ${
|
|
9205
|
+
throw new AggregateError(errors, `Failed to deregister temporary worktree; preserved ${path16.dirname(worktreePath)}`);
|
|
8215
9206
|
}
|
|
8216
9207
|
try {
|
|
8217
|
-
await fsPromises2.rm(
|
|
9208
|
+
await fsPromises2.rm(path16.dirname(worktreePath), { recursive: true, force: true });
|
|
8218
9209
|
} catch (error) {
|
|
8219
9210
|
errors.push(asError(error));
|
|
8220
|
-
throw new AggregateError(errors, `Deregistered the temporary worktree but could not remove ${
|
|
9211
|
+
throw new AggregateError(errors, `Deregistered the temporary worktree but could not remove ${path16.dirname(worktreePath)}`);
|
|
8221
9212
|
}
|
|
8222
9213
|
}
|
|
8223
9214
|
async function cleanupTemporaryWorktree(projectRoot3, worktreePath, temporaryRoot) {
|
|
@@ -8253,9 +9244,9 @@ async function withMaterializedBranch(request, callback) {
|
|
|
8253
9244
|
`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.`
|
|
8254
9245
|
);
|
|
8255
9246
|
}
|
|
8256
|
-
const temporaryRoot = await fsPromises2.mkdtemp(
|
|
8257
|
-
const worktreePath =
|
|
8258
|
-
const hooksPath =
|
|
9247
|
+
const temporaryRoot = await fsPromises2.mkdtemp(path16.join(os7.tmpdir(), "codebase-index-branch-"));
|
|
9248
|
+
const worktreePath = path16.join(temporaryRoot, "worktree");
|
|
9249
|
+
const hooksPath = path16.join(temporaryRoot, "hooks");
|
|
8259
9250
|
await fsPromises2.mkdir(hooksPath);
|
|
8260
9251
|
const info = {
|
|
8261
9252
|
branch: request.branch,
|
|
@@ -8306,8 +9297,8 @@ async function withMaterializedBranch(request, callback) {
|
|
|
8306
9297
|
|
|
8307
9298
|
// src/tools/changed-files.ts
|
|
8308
9299
|
import { execFile as execFile3 } from "child_process";
|
|
8309
|
-
import { realpathSync as
|
|
8310
|
-
import * as
|
|
9300
|
+
import { realpathSync as realpathSync5 } from "fs";
|
|
9301
|
+
import * as path17 from "path";
|
|
8311
9302
|
import { promisify as promisify2 } from "util";
|
|
8312
9303
|
var execFileAsync2 = promisify2(execFile3);
|
|
8313
9304
|
var GH_PR_VIEW_FIELDS = [
|
|
@@ -8449,9 +9440,9 @@ function getHeadRepositoryIdentity(data, host) {
|
|
|
8449
9440
|
return `${host}/${owner.toLowerCase()}/${repository.replace(/\.git$/i, "").toLowerCase()}`;
|
|
8450
9441
|
}
|
|
8451
9442
|
function getLocalRepositoryIdentity(projectRoot3) {
|
|
8452
|
-
let canonicalRoot =
|
|
9443
|
+
let canonicalRoot = path17.resolve(projectRoot3);
|
|
8453
9444
|
try {
|
|
8454
|
-
canonicalRoot =
|
|
9445
|
+
canonicalRoot = realpathSync5.native(canonicalRoot);
|
|
8455
9446
|
} catch {
|
|
8456
9447
|
}
|
|
8457
9448
|
return `local:${canonicalRoot}`;
|
|
@@ -8510,17 +9501,17 @@ async function getMergeBase(projectRoot3, baseCommit, headCommit) {
|
|
|
8510
9501
|
return commit;
|
|
8511
9502
|
}
|
|
8512
9503
|
function normalizeFiles(rawFiles, projectRoot3) {
|
|
8513
|
-
const root =
|
|
9504
|
+
const root = path17.resolve(projectRoot3);
|
|
8514
9505
|
const seen = /* @__PURE__ */ new Set();
|
|
8515
9506
|
const result = [];
|
|
8516
9507
|
for (const raw of rawFiles) {
|
|
8517
9508
|
if (raw.length === 0) continue;
|
|
8518
|
-
const absolute =
|
|
8519
|
-
const relative13 =
|
|
8520
|
-
if (
|
|
9509
|
+
const absolute = path17.resolve(root, raw);
|
|
9510
|
+
const relative13 = path17.relative(root, absolute);
|
|
9511
|
+
if (path17.isAbsolute(raw) || relative13 === ".." || relative13.startsWith(`..${path17.sep}`) || path17.isAbsolute(relative13)) {
|
|
8521
9512
|
throw new Error(`Changed file escapes the project root: ${JSON.stringify(raw)}`);
|
|
8522
9513
|
}
|
|
8523
|
-
const cleaned = relative13.startsWith(`.${
|
|
9514
|
+
const cleaned = relative13.startsWith(`.${path17.sep}`) ? relative13.slice(2) : relative13;
|
|
8524
9515
|
if (!seen.has(cleaned)) {
|
|
8525
9516
|
seen.add(cleaned);
|
|
8526
9517
|
result.push(cleaned);
|
|
@@ -8531,7 +9522,7 @@ function normalizeFiles(rawFiles, projectRoot3) {
|
|
|
8531
9522
|
|
|
8532
9523
|
// src/indexer/git-blame.ts
|
|
8533
9524
|
import { execFile as execFile4 } from "child_process";
|
|
8534
|
-
import * as
|
|
9525
|
+
import * as path18 from "path";
|
|
8535
9526
|
import { promisify as promisify3 } from "util";
|
|
8536
9527
|
var execFileAsync3 = promisify3(execFile4);
|
|
8537
9528
|
function parseGitBlamePorcelain(output) {
|
|
@@ -8569,7 +9560,7 @@ function parseGitBlamePorcelain(output) {
|
|
|
8569
9560
|
return Array.from(commits.values()).filter((commit) => commit.lines > 0).sort((a, b) => b.lines - a.lines || b.committedAt - a.committedAt)[0];
|
|
8570
9561
|
}
|
|
8571
9562
|
async function getChunkGitBlame(projectRoot3, filePath, startLine, endLine) {
|
|
8572
|
-
const relativePath =
|
|
9563
|
+
const relativePath = path18.relative(projectRoot3, filePath);
|
|
8573
9564
|
try {
|
|
8574
9565
|
const { stdout } = await execFileAsync3(
|
|
8575
9566
|
"git",
|
|
@@ -9148,8 +10139,8 @@ function pathSegmentsForAffinityMatch(filePath) {
|
|
|
9148
10139
|
if (segments.length === 0) {
|
|
9149
10140
|
return [];
|
|
9150
10141
|
}
|
|
9151
|
-
const
|
|
9152
|
-
const basenameWithoutExt =
|
|
10142
|
+
const basename8 = segments[segments.length - 1] ?? "";
|
|
10143
|
+
const basenameWithoutExt = basename8.replace(/\.[^/.]+$/u, "");
|
|
9153
10144
|
const normalizedSegments = segments.map((segment) => segment.toLowerCase());
|
|
9154
10145
|
return Array.from(/* @__PURE__ */ new Set([
|
|
9155
10146
|
...normalizedSegments,
|
|
@@ -9458,8 +10449,8 @@ function hasAllEmbeddingParts(parts, expectedPartCount) {
|
|
|
9458
10449
|
|
|
9459
10450
|
// src/indexer/failed-state-persistence.ts
|
|
9460
10451
|
import * as fs2 from "fs";
|
|
9461
|
-
import { createHash, randomBytes as randomBytes3 } from "crypto";
|
|
9462
|
-
import * as
|
|
10452
|
+
import { createHash as createHash2, randomBytes as randomBytes3 } from "crypto";
|
|
10453
|
+
import * as path19 from "path";
|
|
9463
10454
|
import { StringDecoder } from "string_decoder";
|
|
9464
10455
|
var CURRENT_FAILED_BATCH_VERSION = 1;
|
|
9465
10456
|
var DEFAULT_MALFORMED_LINE_ACTION = "skip";
|
|
@@ -9477,7 +10468,7 @@ function* readFailedBatchRecords(filePath, options = {}) {
|
|
|
9477
10468
|
function createFailedBatchWriter(targetPath) {
|
|
9478
10469
|
const temporaryPath = createTemporaryPath(targetPath);
|
|
9479
10470
|
let finalized = false;
|
|
9480
|
-
fs2.mkdirSync(
|
|
10471
|
+
fs2.mkdirSync(path19.dirname(targetPath), { recursive: true });
|
|
9481
10472
|
fs2.closeSync(fs2.openSync(temporaryPath, "w"));
|
|
9482
10473
|
const write = (record) => {
|
|
9483
10474
|
if (finalized) {
|
|
@@ -9496,7 +10487,7 @@ function createFailedBatchWriter(targetPath) {
|
|
|
9496
10487
|
if (lines.length === 0) {
|
|
9497
10488
|
return;
|
|
9498
10489
|
}
|
|
9499
|
-
fs2.mkdirSync(
|
|
10490
|
+
fs2.mkdirSync(path19.dirname(targetPath), { recursive: true });
|
|
9500
10491
|
fs2.appendFileSync(temporaryPath, `${lines.join("\n")}
|
|
9501
10492
|
`, "utf-8");
|
|
9502
10493
|
};
|
|
@@ -9504,7 +10495,7 @@ function createFailedBatchWriter(targetPath) {
|
|
|
9504
10495
|
if (finalized) {
|
|
9505
10496
|
return;
|
|
9506
10497
|
}
|
|
9507
|
-
fs2.mkdirSync(
|
|
10498
|
+
fs2.mkdirSync(path19.dirname(targetPath), { recursive: true });
|
|
9508
10499
|
fs2.renameSync(temporaryPath, targetPath);
|
|
9509
10500
|
finalized = true;
|
|
9510
10501
|
};
|
|
@@ -9650,10 +10641,10 @@ function stripLeadingBomAndWhitespace(value) {
|
|
|
9650
10641
|
return result;
|
|
9651
10642
|
}
|
|
9652
10643
|
function createTemporaryPath(targetPath) {
|
|
9653
|
-
const randomId =
|
|
9654
|
-
const targetDir =
|
|
9655
|
-
const baseName =
|
|
9656
|
-
return
|
|
10644
|
+
const randomId = createHash2("sha1").update(`${Date.now()}:${randomBytes3(8).toString("hex")}`).digest("hex");
|
|
10645
|
+
const targetDir = path19.dirname(targetPath);
|
|
10646
|
+
const baseName = path19.basename(targetPath);
|
|
10647
|
+
return path19.join(targetDir, `.${baseName}.${randomId}.tmp`);
|
|
9657
10648
|
}
|
|
9658
10649
|
function handleMalformedLine(filePath, lineNumber, line, error, options) {
|
|
9659
10650
|
const action = options.malformedLineAction ?? DEFAULT_MALFORMED_LINE_ACTION;
|
|
@@ -9899,9 +10890,9 @@ var SWIFT_PARSER_VERSION = "1";
|
|
|
9899
10890
|
var METAL_PARSER_VERSION = "1";
|
|
9900
10891
|
var SYMBOL_EXTRACTOR_VERSION = "1";
|
|
9901
10892
|
function isPathWithinRoot2(filePath, rootPath) {
|
|
9902
|
-
const normalizedFilePath =
|
|
9903
|
-
const normalizedRoot =
|
|
9904
|
-
return normalizedFilePath === normalizedRoot || normalizedFilePath.startsWith(`${normalizedRoot}${
|
|
10893
|
+
const normalizedFilePath = path20.resolve(filePath);
|
|
10894
|
+
const normalizedRoot = path20.resolve(rootPath);
|
|
10895
|
+
return normalizedFilePath === normalizedRoot || normalizedFilePath.startsWith(`${normalizedRoot}${path20.sep}`);
|
|
9905
10896
|
}
|
|
9906
10897
|
function promoteIdentifierMatches(query, combined, semanticCandidates, keywordCandidates, database, branchChunkIds, prioritizeSourcePaths = classifyQueryIntentRaw(query) === "source") {
|
|
9907
10898
|
if (combined.length === 0) {
|
|
@@ -10232,10 +11223,10 @@ function matchesHardSearchFilters(candidate, options, projectRoot3) {
|
|
|
10232
11223
|
}
|
|
10233
11224
|
if (options?.directory) {
|
|
10234
11225
|
const candidatePath = canonicalizePathForComparison(
|
|
10235
|
-
|
|
11226
|
+
path20.resolve(projectRoot3, candidate.metadata.filePath.replace(/\\/g, path20.sep))
|
|
10236
11227
|
);
|
|
10237
11228
|
const directoryPath = canonicalizePathForComparison(
|
|
10238
|
-
|
|
11229
|
+
path20.resolve(projectRoot3, options.directory.trim().replace(/\\/g, path20.sep))
|
|
10239
11230
|
);
|
|
10240
11231
|
if (!isPathWithinRoot2(candidatePath, directoryPath)) return false;
|
|
10241
11232
|
}
|
|
@@ -10348,26 +11339,37 @@ var Indexer = class _Indexer {
|
|
|
10348
11339
|
return this.indexPathOverride ?? resolveProjectIndexPath(this.projectRoot, this.config.scope, this.host);
|
|
10349
11340
|
}
|
|
10350
11341
|
toCanonicalFilePath(filePath) {
|
|
10351
|
-
if (!
|
|
11342
|
+
if (!path20.isAbsolute(filePath)) {
|
|
10352
11343
|
return this.resolveStoredFilePath(filePath, this.projectRoot);
|
|
10353
11344
|
}
|
|
10354
|
-
if (
|
|
11345
|
+
if (path20.resolve(this.materializedProjectRoot) === path20.resolve(this.projectRoot) || !isPathWithinRoot2(filePath, this.materializedProjectRoot)) {
|
|
10355
11346
|
return filePath;
|
|
10356
11347
|
}
|
|
10357
|
-
return
|
|
11348
|
+
return path20.resolve(this.projectRoot, path20.relative(this.materializedProjectRoot, filePath));
|
|
10358
11349
|
}
|
|
10359
11350
|
toStoredFilePath(filePath) {
|
|
10360
11351
|
const canonicalFilePath = this.toCanonicalFilePath(filePath);
|
|
10361
11352
|
if (this.config.scope !== "project" || !isPathWithinRoot2(canonicalFilePath, this.projectRoot)) {
|
|
10362
11353
|
return canonicalFilePath;
|
|
10363
11354
|
}
|
|
10364
|
-
return
|
|
11355
|
+
return path20.relative(this.projectRoot, canonicalFilePath).split(path20.sep).join("/");
|
|
11356
|
+
}
|
|
11357
|
+
isStoredPathExcluded(storedPath) {
|
|
11358
|
+
let matchPath = storedPath.split(path20.sep).join("/");
|
|
11359
|
+
if (path20.isAbsolute(storedPath)) {
|
|
11360
|
+
const relativePath = path20.relative(this.projectRoot, storedPath).split(path20.sep).join("/");
|
|
11361
|
+
if (relativePath.startsWith("..") || path20.isAbsolute(relativePath)) {
|
|
11362
|
+
return false;
|
|
11363
|
+
}
|
|
11364
|
+
matchPath = relativePath;
|
|
11365
|
+
}
|
|
11366
|
+
return isExcludedByPatterns(matchPath, this.config.exclude);
|
|
10365
11367
|
}
|
|
10366
11368
|
resolveStoredFilePath(filePath, rootPath = this.projectRoot) {
|
|
10367
|
-
if (
|
|
11369
|
+
if (path20.isAbsolute(filePath)) {
|
|
10368
11370
|
return filePath;
|
|
10369
11371
|
}
|
|
10370
|
-
const resolvedPath =
|
|
11372
|
+
const resolvedPath = path20.resolve(rootPath, ...filePath.split("/"));
|
|
10371
11373
|
if (!isPathWithinRoot2(resolvedPath, rootPath)) {
|
|
10372
11374
|
throw new Error(`Stored project path escapes project root: ${JSON.stringify(filePath)}`);
|
|
10373
11375
|
}
|
|
@@ -10391,7 +11393,7 @@ var Indexer = class _Indexer {
|
|
|
10391
11393
|
}
|
|
10392
11394
|
toMaterializedFilePath(filePath) {
|
|
10393
11395
|
const storedFilePath = this.toStoredFilePath(filePath);
|
|
10394
|
-
if (
|
|
11396
|
+
if (path20.isAbsolute(storedFilePath)) {
|
|
10395
11397
|
return storedFilePath;
|
|
10396
11398
|
}
|
|
10397
11399
|
return this.resolveStoredFilePath(storedFilePath, this.materializedProjectRoot);
|
|
@@ -10408,10 +11410,10 @@ var Indexer = class _Indexer {
|
|
|
10408
11410
|
}
|
|
10409
11411
|
getRuntimeArtifactPath(fileName) {
|
|
10410
11412
|
const namespace = this.getRuntimeArtifactNamespace();
|
|
10411
|
-
if (!namespace) return
|
|
10412
|
-
const extension =
|
|
11413
|
+
if (!namespace) return path20.join(this.indexPath, fileName);
|
|
11414
|
+
const extension = path20.extname(fileName);
|
|
10413
11415
|
const baseName = fileName.slice(0, fileName.length - extension.length);
|
|
10414
|
-
return
|
|
11416
|
+
return path20.join(this.indexPath, `${baseName}.${namespace}${extension}`);
|
|
10415
11417
|
}
|
|
10416
11418
|
refreshRuntimeArtifactPaths() {
|
|
10417
11419
|
this.fileHashCachePath = this.getRuntimeArtifactPath("file-hashes.json");
|
|
@@ -10424,14 +11426,14 @@ var Indexer = class _Indexer {
|
|
|
10424
11426
|
getMaterializedKnowledgeBases() {
|
|
10425
11427
|
const canonicalProjectRoot = this.getCanonicalPath(this.projectRoot);
|
|
10426
11428
|
return this.config.knowledgeBases.map((knowledgeBase) => {
|
|
10427
|
-
const configuredPath =
|
|
11429
|
+
const configuredPath = path20.isAbsolute(knowledgeBase) ? knowledgeBase : path20.resolve(this.projectRoot, knowledgeBase);
|
|
10428
11430
|
const canonicalPath = this.getCanonicalPath(configuredPath);
|
|
10429
11431
|
if (!isPathWithinRoot2(canonicalPath, canonicalProjectRoot)) {
|
|
10430
11432
|
return canonicalPath;
|
|
10431
11433
|
}
|
|
10432
|
-
return
|
|
11434
|
+
return path20.resolve(
|
|
10433
11435
|
this.materializedProjectRoot,
|
|
10434
|
-
|
|
11436
|
+
path20.relative(canonicalProjectRoot, canonicalPath)
|
|
10435
11437
|
);
|
|
10436
11438
|
});
|
|
10437
11439
|
}
|
|
@@ -10439,7 +11441,7 @@ var Indexer = class _Indexer {
|
|
|
10439
11441
|
try {
|
|
10440
11442
|
return canonicalizePathForComparison(targetPath);
|
|
10441
11443
|
} catch {
|
|
10442
|
-
return
|
|
11444
|
+
return path20.resolve(targetPath);
|
|
10443
11445
|
}
|
|
10444
11446
|
}
|
|
10445
11447
|
getProjectIdentityHash(projectRoot3) {
|
|
@@ -10520,7 +11522,7 @@ var Indexer = class _Indexer {
|
|
|
10520
11522
|
} catch (error) {
|
|
10521
11523
|
releaseError = error;
|
|
10522
11524
|
this.writerArtifactFingerprint = null;
|
|
10523
|
-
if (!
|
|
11525
|
+
if (!existsSync12(lease.lockPath) && this.activeIndexLease?.owner.token === lease.owner.token) {
|
|
10524
11526
|
this.activeIndexLease = null;
|
|
10525
11527
|
}
|
|
10526
11528
|
}
|
|
@@ -10538,12 +11540,12 @@ var Indexer = class _Indexer {
|
|
|
10538
11540
|
return this.activeIndexLease;
|
|
10539
11541
|
}
|
|
10540
11542
|
loadFileHashCache() {
|
|
10541
|
-
if (!
|
|
11543
|
+
if (!existsSync12(this.fileHashCachePath)) {
|
|
10542
11544
|
this.fileHashCache = /* @__PURE__ */ new Map();
|
|
10543
11545
|
return;
|
|
10544
11546
|
}
|
|
10545
11547
|
try {
|
|
10546
|
-
const data =
|
|
11548
|
+
const data = readFileSync9(this.fileHashCachePath, "utf-8");
|
|
10547
11549
|
const parsed = JSON.parse(data);
|
|
10548
11550
|
this.fileHashCache = new Map(Object.entries(parsed));
|
|
10549
11551
|
} catch (error) {
|
|
@@ -10565,24 +11567,24 @@ var Indexer = class _Indexer {
|
|
|
10565
11567
|
atomicWriteSync(targetPath, data) {
|
|
10566
11568
|
const lease = this.requireActiveLease();
|
|
10567
11569
|
const tempPath = createLeaseTemporaryPath(targetPath, lease.owner, "tmp");
|
|
10568
|
-
|
|
11570
|
+
mkdirSync5(path20.dirname(targetPath), { recursive: true });
|
|
10569
11571
|
try {
|
|
10570
|
-
|
|
10571
|
-
|
|
11572
|
+
writeFileSync4(tempPath, data);
|
|
11573
|
+
renameSync4(tempPath, targetPath);
|
|
10572
11574
|
} finally {
|
|
10573
11575
|
removeLeaseTemporaryPath(tempPath);
|
|
10574
11576
|
}
|
|
10575
11577
|
}
|
|
10576
11578
|
saveInvertedIndex(invertedIndex) {
|
|
10577
11579
|
this.atomicWriteSync(
|
|
10578
|
-
|
|
11580
|
+
path20.join(this.indexPath, "inverted-index.json"),
|
|
10579
11581
|
invertedIndex.serialize()
|
|
10580
11582
|
);
|
|
10581
11583
|
}
|
|
10582
11584
|
getScopedRoots(projectRoot3 = this.projectRoot) {
|
|
10583
11585
|
const roots = /* @__PURE__ */ new Set([this.getCanonicalPath(projectRoot3)]);
|
|
10584
11586
|
for (const kbRoot of this.config.knowledgeBases) {
|
|
10585
|
-
roots.add(this.getCanonicalPath(
|
|
11587
|
+
roots.add(this.getCanonicalPath(path20.resolve(projectRoot3, kbRoot)));
|
|
10586
11588
|
}
|
|
10587
11589
|
return Array.from(roots);
|
|
10588
11590
|
}
|
|
@@ -10999,7 +12001,7 @@ var Indexer = class _Indexer {
|
|
|
10999
12001
|
return configuredProviderInfo !== null && recovery.embeddingProvider === configuredProviderInfo.provider && recovery.embeddingModel === configuredProviderInfo.modelInfo.model && recovery.embeddingDimensions === configuredProviderInfo.modelInfo.dimensions && recovery.embeddingStrategyVersion === EMBEDDING_STRATEGY_VERSION;
|
|
11000
12002
|
}
|
|
11001
12003
|
hasUnknownLegacyForceIndexClear(owner) {
|
|
11002
|
-
return owner.operation === "force-index" && owner.clearRecovery === void 0 && owner.recoveryProtocolVersion !== 1 &&
|
|
12004
|
+
return owner.operation === "force-index" && owner.clearRecovery === void 0 && owner.recoveryProtocolVersion !== 1 && existsSync12(path20.join(this.indexPath, "force-index-phase"));
|
|
11003
12005
|
}
|
|
11004
12006
|
async recoverFromInterruptedIndexingUnlocked(owners) {
|
|
11005
12007
|
for (const owner of owners) {
|
|
@@ -11185,7 +12187,7 @@ var Indexer = class _Indexer {
|
|
|
11185
12187
|
}
|
|
11186
12188
|
}
|
|
11187
12189
|
clearFailedBatchState() {
|
|
11188
|
-
if (
|
|
12190
|
+
if (existsSync12(this.failedBatchesPath)) {
|
|
11189
12191
|
try {
|
|
11190
12192
|
unlinkSync2(this.failedBatchesPath);
|
|
11191
12193
|
} catch {
|
|
@@ -11387,7 +12389,7 @@ var Indexer = class _Indexer {
|
|
|
11387
12389
|
await options.queue.onSizeLessThan(Math.max(1, options.providerRateLimits.concurrency));
|
|
11388
12390
|
const task = options.queue.add(async () => {
|
|
11389
12391
|
if (options.rateLimitState.backoffMs > 0) {
|
|
11390
|
-
await new Promise((
|
|
12392
|
+
await new Promise((resolve18) => setTimeout(resolve18, options.rateLimitState.backoffMs));
|
|
11391
12393
|
}
|
|
11392
12394
|
try {
|
|
11393
12395
|
const embeddingResult = await pRetry(
|
|
@@ -11806,12 +12808,12 @@ var Indexer = class _Indexer {
|
|
|
11806
12808
|
}
|
|
11807
12809
|
}
|
|
11808
12810
|
captureReaderArtifactFingerprint() {
|
|
11809
|
-
const storePath =
|
|
12811
|
+
const storePath = path20.join(this.indexPath, "vectors");
|
|
11810
12812
|
return {
|
|
11811
12813
|
vectors: `${this.getReaderFileFingerprint(storePath)}|${this.getReaderFileFingerprint(`${storePath}.meta.json`)}`,
|
|
11812
|
-
keyword: this.getReaderFileFingerprint(
|
|
11813
|
-
database: this.getReaderFileFingerprint(
|
|
11814
|
-
databaseIdentity: this.getReaderFileFingerprint(
|
|
12814
|
+
keyword: this.getReaderFileFingerprint(path20.join(this.indexPath, "inverted-index.json")),
|
|
12815
|
+
database: this.getReaderFileFingerprint(path20.join(this.indexPath, "codebase.db")),
|
|
12816
|
+
databaseIdentity: this.getReaderFileFingerprint(path20.join(this.indexPath, "codebase.db"), true)
|
|
11815
12817
|
};
|
|
11816
12818
|
}
|
|
11817
12819
|
refreshReaderArtifacts() {
|
|
@@ -11836,13 +12838,13 @@ var Indexer = class _Indexer {
|
|
|
11836
12838
|
issues.set(component, this.createReadIssue(component, message));
|
|
11837
12839
|
this.readerArtifactRetryAfter.set(component, Date.now() + READER_ARTIFACT_RETRY_INTERVAL_MS);
|
|
11838
12840
|
};
|
|
11839
|
-
const storePath =
|
|
12841
|
+
const storePath = path20.join(this.indexPath, "vectors");
|
|
11840
12842
|
const vectorMetadataPath = `${storePath}.meta.json`;
|
|
11841
|
-
const invertedIndexPath =
|
|
11842
|
-
const dbPath =
|
|
12843
|
+
const invertedIndexPath = path20.join(this.indexPath, "inverted-index.json");
|
|
12844
|
+
const dbPath = path20.join(this.indexPath, "codebase.db");
|
|
11843
12845
|
if (vectorsChanged || retryDue("vectors")) {
|
|
11844
|
-
const vectorStoreExists =
|
|
11845
|
-
const vectorMetadataExists =
|
|
12846
|
+
const vectorStoreExists = existsSync12(storePath);
|
|
12847
|
+
const vectorMetadataExists = existsSync12(vectorMetadataPath);
|
|
11846
12848
|
if (vectorStoreExists && vectorMetadataExists) {
|
|
11847
12849
|
try {
|
|
11848
12850
|
const store = new VectorStore(storePath, this.configuredProviderInfo.modelInfo.dimensions);
|
|
@@ -11857,8 +12859,8 @@ var Indexer = class _Indexer {
|
|
|
11857
12859
|
setIssue("vectors", this.getVectorReadIssueMessage());
|
|
11858
12860
|
}
|
|
11859
12861
|
}
|
|
11860
|
-
if (keywordChanged || retryDue("keyword") || !
|
|
11861
|
-
if (
|
|
12862
|
+
if (keywordChanged || retryDue("keyword") || !existsSync12(invertedIndexPath) && (this.store?.count() ?? 0) > 0) {
|
|
12863
|
+
if (existsSync12(invertedIndexPath)) {
|
|
11862
12864
|
try {
|
|
11863
12865
|
const invertedIndex = new InvertedIndex(invertedIndexPath);
|
|
11864
12866
|
invertedIndex.load();
|
|
@@ -11873,7 +12875,7 @@ var Indexer = class _Indexer {
|
|
|
11873
12875
|
}
|
|
11874
12876
|
}
|
|
11875
12877
|
if (databaseReplaced || databaseChanged && issues.has("database") || retryDue("database")) {
|
|
11876
|
-
if (
|
|
12878
|
+
if (existsSync12(dbPath)) {
|
|
11877
12879
|
try {
|
|
11878
12880
|
const database = Database.openReadOnly(dbPath);
|
|
11879
12881
|
if (this.database) {
|
|
@@ -11955,11 +12957,11 @@ var Indexer = class _Indexer {
|
|
|
11955
12957
|
});
|
|
11956
12958
|
this.provider = createEmbeddingProvider(this.configuredProviderInfo);
|
|
11957
12959
|
const dimensions = this.configuredProviderInfo.modelInfo.dimensions;
|
|
11958
|
-
const storePath =
|
|
12960
|
+
const storePath = path20.join(this.indexPath, "vectors");
|
|
11959
12961
|
const vectorMetadataPath = `${storePath}.meta.json`;
|
|
11960
|
-
const invertedIndexPath =
|
|
11961
|
-
const dbPath =
|
|
11962
|
-
let dbIsNew = !
|
|
12962
|
+
const invertedIndexPath = path20.join(this.indexPath, "inverted-index.json");
|
|
12963
|
+
const dbPath = path20.join(this.indexPath, "codebase.db");
|
|
12964
|
+
let dbIsNew = !existsSync12(dbPath);
|
|
11963
12965
|
const readerArtifactFingerprint = mode === "reader" ? this.captureReaderArtifactFingerprint() : null;
|
|
11964
12966
|
if (mode === "writer") {
|
|
11965
12967
|
await fsPromises3.mkdir(this.indexPath, { recursive: true });
|
|
@@ -11991,14 +12993,14 @@ var Indexer = class _Indexer {
|
|
|
11991
12993
|
}
|
|
11992
12994
|
}
|
|
11993
12995
|
this.store = new VectorStore(storePath, dimensions);
|
|
11994
|
-
if (
|
|
12996
|
+
if (existsSync12(storePath) || existsSync12(vectorMetadataPath)) {
|
|
11995
12997
|
this.store.load();
|
|
11996
12998
|
}
|
|
11997
12999
|
this.invertedIndex = new InvertedIndex(invertedIndexPath);
|
|
11998
13000
|
try {
|
|
11999
13001
|
this.invertedIndex.load();
|
|
12000
13002
|
} catch {
|
|
12001
|
-
if (
|
|
13003
|
+
if (existsSync12(invertedIndexPath)) {
|
|
12002
13004
|
await fsPromises3.unlink(invertedIndexPath);
|
|
12003
13005
|
}
|
|
12004
13006
|
this.invertedIndex = new InvertedIndex(invertedIndexPath);
|
|
@@ -12016,8 +13018,8 @@ var Indexer = class _Indexer {
|
|
|
12016
13018
|
}
|
|
12017
13019
|
} else {
|
|
12018
13020
|
this.store = new VectorStore(storePath, dimensions);
|
|
12019
|
-
const vectorStoreExists =
|
|
12020
|
-
const vectorMetadataExists =
|
|
13021
|
+
const vectorStoreExists = existsSync12(storePath);
|
|
13022
|
+
const vectorMetadataExists = existsSync12(vectorMetadataPath);
|
|
12021
13023
|
const vectorReadFailureMessage = this.getVectorReadIssueMessage();
|
|
12022
13024
|
if (vectorStoreExists !== vectorMetadataExists) {
|
|
12023
13025
|
this.recordReadIssue("vectors", vectorReadFailureMessage);
|
|
@@ -12030,7 +13032,7 @@ var Indexer = class _Indexer {
|
|
|
12030
13032
|
}
|
|
12031
13033
|
}
|
|
12032
13034
|
this.invertedIndex = new InvertedIndex(invertedIndexPath);
|
|
12033
|
-
if (
|
|
13035
|
+
if (existsSync12(invertedIndexPath)) {
|
|
12034
13036
|
try {
|
|
12035
13037
|
this.invertedIndex.load();
|
|
12036
13038
|
} catch (error) {
|
|
@@ -12044,7 +13046,7 @@ var Indexer = class _Indexer {
|
|
|
12044
13046
|
} else if (this.store.count() > 0) {
|
|
12045
13047
|
this.recordReadIssue("keyword", this.getKeywordReadIssueMessage());
|
|
12046
13048
|
}
|
|
12047
|
-
if (
|
|
13049
|
+
if (existsSync12(dbPath)) {
|
|
12048
13050
|
try {
|
|
12049
13051
|
this.database = Database.openReadOnly(dbPath);
|
|
12050
13052
|
} catch (error) {
|
|
@@ -12136,7 +13138,7 @@ var Indexer = class _Indexer {
|
|
|
12136
13138
|
if (await this.tryResetCorruptedIndex("running automatic orphan garbage collection", error)) {
|
|
12137
13139
|
return {
|
|
12138
13140
|
resetCorruptedIndex: true,
|
|
12139
|
-
warning: this.getCorruptedIndexWarning(
|
|
13141
|
+
warning: this.getCorruptedIndexWarning(path20.join(this.indexPath, "codebase.db"))
|
|
12140
13142
|
};
|
|
12141
13143
|
}
|
|
12142
13144
|
throw error;
|
|
@@ -12151,7 +13153,7 @@ var Indexer = class _Indexer {
|
|
|
12151
13153
|
return;
|
|
12152
13154
|
}
|
|
12153
13155
|
const retainedEntries = store.getAllMetadata().filter(({ key }) => !excludedSet.has(key));
|
|
12154
|
-
const storeBasePath =
|
|
13156
|
+
const storeBasePath = path20.join(this.indexPath, "vectors");
|
|
12155
13157
|
const storeIndexPath = storeBasePath;
|
|
12156
13158
|
const storeMetadataPath = `${storeBasePath}.meta.json`;
|
|
12157
13159
|
const lease = this.requireActiveLease();
|
|
@@ -12161,19 +13163,19 @@ var Indexer = class _Indexer {
|
|
|
12161
13163
|
let backedUpMetadata = false;
|
|
12162
13164
|
let rebuiltCount = 0;
|
|
12163
13165
|
let skippedCount = 0;
|
|
12164
|
-
if (
|
|
13166
|
+
if (existsSync12(backupIndexPath)) {
|
|
12165
13167
|
unlinkSync2(backupIndexPath);
|
|
12166
13168
|
}
|
|
12167
|
-
if (
|
|
13169
|
+
if (existsSync12(backupMetadataPath)) {
|
|
12168
13170
|
unlinkSync2(backupMetadataPath);
|
|
12169
13171
|
}
|
|
12170
13172
|
try {
|
|
12171
|
-
if (
|
|
12172
|
-
|
|
13173
|
+
if (existsSync12(storeIndexPath)) {
|
|
13174
|
+
renameSync4(storeIndexPath, backupIndexPath);
|
|
12173
13175
|
backedUpIndex = true;
|
|
12174
13176
|
}
|
|
12175
|
-
if (
|
|
12176
|
-
|
|
13177
|
+
if (existsSync12(storeMetadataPath)) {
|
|
13178
|
+
renameSync4(storeMetadataPath, backupMetadataPath);
|
|
12177
13179
|
backedUpMetadata = true;
|
|
12178
13180
|
}
|
|
12179
13181
|
store.clear();
|
|
@@ -12193,10 +13195,10 @@ var Indexer = class _Indexer {
|
|
|
12193
13195
|
rebuiltCount += 1;
|
|
12194
13196
|
}
|
|
12195
13197
|
store.save();
|
|
12196
|
-
if (backedUpIndex &&
|
|
13198
|
+
if (backedUpIndex && existsSync12(backupIndexPath)) {
|
|
12197
13199
|
unlinkSync2(backupIndexPath);
|
|
12198
13200
|
}
|
|
12199
|
-
if (backedUpMetadata &&
|
|
13201
|
+
if (backedUpMetadata && existsSync12(backupMetadataPath)) {
|
|
12200
13202
|
unlinkSync2(backupMetadataPath);
|
|
12201
13203
|
}
|
|
12202
13204
|
this.logger.gc("info", "Rebuilt vector store to avoid native remove", {
|
|
@@ -12209,17 +13211,17 @@ var Indexer = class _Indexer {
|
|
|
12209
13211
|
store.clear();
|
|
12210
13212
|
} catch {
|
|
12211
13213
|
}
|
|
12212
|
-
if (
|
|
13214
|
+
if (existsSync12(storeIndexPath)) {
|
|
12213
13215
|
unlinkSync2(storeIndexPath);
|
|
12214
13216
|
}
|
|
12215
|
-
if (
|
|
13217
|
+
if (existsSync12(storeMetadataPath)) {
|
|
12216
13218
|
unlinkSync2(storeMetadataPath);
|
|
12217
13219
|
}
|
|
12218
|
-
if (backedUpIndex &&
|
|
12219
|
-
|
|
13220
|
+
if (backedUpIndex && existsSync12(backupIndexPath)) {
|
|
13221
|
+
renameSync4(backupIndexPath, storeIndexPath);
|
|
12220
13222
|
}
|
|
12221
|
-
if (backedUpMetadata &&
|
|
12222
|
-
|
|
13223
|
+
if (backedUpMetadata && existsSync12(backupMetadataPath)) {
|
|
13224
|
+
renameSync4(backupMetadataPath, storeMetadataPath);
|
|
12223
13225
|
}
|
|
12224
13226
|
if (backedUpIndex || backedUpMetadata) {
|
|
12225
13227
|
store.load();
|
|
@@ -12234,11 +13236,11 @@ var Indexer = class _Indexer {
|
|
|
12234
13236
|
return `Detected a corrupted local SQLite index at ${dbPath} and reset the local index. Run index_codebase to rebuild search data.`;
|
|
12235
13237
|
}
|
|
12236
13238
|
async removeProjectRuntimeStateArtifacts() {
|
|
12237
|
-
if (!
|
|
13239
|
+
if (!existsSync12(this.indexPath)) return;
|
|
12238
13240
|
const names = await fsPromises3.readdir(this.indexPath);
|
|
12239
13241
|
const runtimeStatePattern = /^(?:file-hashes|failed-batches)(?:\.[a-f0-9]{16})?\.json$/;
|
|
12240
13242
|
await Promise.all(
|
|
12241
|
-
names.filter((name) => runtimeStatePattern.test(name)).map((name) => fsPromises3.rm(
|
|
13243
|
+
names.filter((name) => runtimeStatePattern.test(name)).map((name) => fsPromises3.rm(path20.join(this.indexPath, name), { force: true }))
|
|
12242
13244
|
);
|
|
12243
13245
|
}
|
|
12244
13246
|
async resetLocalIndexArtifacts() {
|
|
@@ -12254,13 +13256,13 @@ var Indexer = class _Indexer {
|
|
|
12254
13256
|
this.readerArtifactRetryAfter.clear();
|
|
12255
13257
|
this.fileHashCache.clear();
|
|
12256
13258
|
const resetPaths = [
|
|
12257
|
-
|
|
12258
|
-
|
|
12259
|
-
|
|
12260
|
-
|
|
12261
|
-
|
|
12262
|
-
|
|
12263
|
-
|
|
13259
|
+
path20.join(this.indexPath, "codebase.db"),
|
|
13260
|
+
path20.join(this.indexPath, "codebase.db-shm"),
|
|
13261
|
+
path20.join(this.indexPath, "codebase.db-wal"),
|
|
13262
|
+
path20.join(this.indexPath, "vectors"),
|
|
13263
|
+
path20.join(this.indexPath, "vectors.usearch"),
|
|
13264
|
+
path20.join(this.indexPath, "vectors.meta.json"),
|
|
13265
|
+
path20.join(this.indexPath, "inverted-index.json")
|
|
12264
13266
|
];
|
|
12265
13267
|
await Promise.all(resetPaths.map((targetPath) => fsPromises3.rm(targetPath, { recursive: true, force: true })));
|
|
12266
13268
|
await this.removeProjectRuntimeStateArtifacts();
|
|
@@ -12270,7 +13272,7 @@ var Indexer = class _Indexer {
|
|
|
12270
13272
|
if (!isSqliteCorruptionError(error)) {
|
|
12271
13273
|
return false;
|
|
12272
13274
|
}
|
|
12273
|
-
const dbPath =
|
|
13275
|
+
const dbPath = path20.join(this.indexPath, "codebase.db");
|
|
12274
13276
|
const warning = this.getCorruptedIndexWarning(dbPath);
|
|
12275
13277
|
const errorMessage = getErrorMessage4(error);
|
|
12276
13278
|
if (this.config.scope === "global") {
|
|
@@ -12657,10 +13659,10 @@ var Indexer = class _Indexer {
|
|
|
12657
13659
|
const reparseCachedMetalFiles = database.getMetadata(metalParserMetadataKey) !== METAL_PARSER_VERSION;
|
|
12658
13660
|
const symbolExtractorMetadataKey = this.getSymbolExtractorVersionMetadataKey();
|
|
12659
13661
|
const refreshCachedSymbols = database.getMetadata(symbolExtractorMetadataKey) !== SYMBOL_EXTRACTOR_VERSION;
|
|
12660
|
-
if (reparseCachedSwiftFiles && Array.from(this.fileHashCache.keys()).some((filePath) =>
|
|
13662
|
+
if (reparseCachedSwiftFiles && Array.from(this.fileHashCache.keys()).some((filePath) => path20.extname(filePath).toLowerCase() === ".swift")) {
|
|
12661
13663
|
this.logger.info("Reindexing cached Swift files for parser support");
|
|
12662
13664
|
}
|
|
12663
|
-
if (reparseCachedMetalFiles && Array.from(this.fileHashCache.keys()).some((filePath) =>
|
|
13665
|
+
if (reparseCachedMetalFiles && Array.from(this.fileHashCache.keys()).some((filePath) => path20.extname(filePath).toLowerCase() === ".metal")) {
|
|
12664
13666
|
this.logger.info("Reindexing cached Metal files for parser support");
|
|
12665
13667
|
}
|
|
12666
13668
|
const includePatterns = [...this.config.include, ...this.config.additionalInclude];
|
|
@@ -12704,8 +13706,8 @@ var Indexer = class _Indexer {
|
|
|
12704
13706
|
const needsCallGraphRefresh = cachedHashMatches && needsCallGraphResolutionMigration && database.getChunksByFile(storedPath).some(
|
|
12705
13707
|
(chunk) => chunk.language === "php" || chunk.language === "c" || chunk.language === "cpp"
|
|
12706
13708
|
);
|
|
12707
|
-
const requiresSwiftParserUpgrade = reparseCachedSwiftFiles &&
|
|
12708
|
-
const requiresMetalParserUpgrade = reparseCachedMetalFiles &&
|
|
13709
|
+
const requiresSwiftParserUpgrade = reparseCachedSwiftFiles && path20.extname(storedPath).toLowerCase() === ".swift";
|
|
13710
|
+
const requiresMetalParserUpgrade = reparseCachedMetalFiles && path20.extname(storedPath).toLowerCase() === ".metal";
|
|
12709
13711
|
const inMigrationScope = forceScopedReembed && scopedRoots !== null && this.isFileInCurrentScope(storedPath, scopedRoots);
|
|
12710
13712
|
if (cachedHashMatches && !inMigrationScope && !needsCallGraphRefresh && !requiresSwiftParserUpgrade && !requiresMetalParserUpgrade && !refreshCachedSymbols) {
|
|
12711
13713
|
unchangedFilePaths.add(storedPath);
|
|
@@ -12764,7 +13766,7 @@ var Indexer = class _Indexer {
|
|
|
12764
13766
|
}
|
|
12765
13767
|
}
|
|
12766
13768
|
}
|
|
12767
|
-
const shouldRetryFailedPath = (filePath) => filePath !== null && currentFileHashes.has(filePath) && unchangedFilePaths.has(filePath);
|
|
13769
|
+
const shouldRetryFailedPath = (filePath) => filePath !== null && !this.isStoredPathExcluded(filePath) && currentFileHashes.has(filePath) && unchangedFilePaths.has(filePath);
|
|
12768
13770
|
const failedProcessing = this.prepareFailedBatchProcessing(scopedRoots, shouldRetryFailedPath);
|
|
12769
13771
|
const maxChunkTokens = getSafeEmbeddingChunkTokenLimit(configuredProviderInfo);
|
|
12770
13772
|
const providerRateLimits = this.getProviderRateLimits(configuredProviderInfo.provider);
|
|
@@ -12868,7 +13870,7 @@ var Indexer = class _Indexer {
|
|
|
12868
13870
|
throw new Error(`Parsed file was not present in its source batch: ${parsed.path}`);
|
|
12869
13871
|
}
|
|
12870
13872
|
if (parsed.chunks.length === 0) {
|
|
12871
|
-
stats.parseFailures.push(
|
|
13873
|
+
stats.parseFailures.push(path20.isAbsolute(parsed.path) ? path20.relative(this.projectRoot, parsed.path) : parsed.path);
|
|
12872
13874
|
}
|
|
12873
13875
|
let chunksToProcess = parsed.chunks;
|
|
12874
13876
|
if (this.config.indexing.fallbackToTextOnMaxChunks && chunksToProcess.length > this.config.indexing.maxChunksPerFile) {
|
|
@@ -13203,8 +14205,8 @@ var Indexer = class _Indexer {
|
|
|
13203
14205
|
previousBranchSymbolIds,
|
|
13204
14206
|
Array.from(allSymbolIds)
|
|
13205
14207
|
);
|
|
13206
|
-
const vectorPath =
|
|
13207
|
-
const shouldFingerprintLegacyPair = !store.hasFingerprint() &&
|
|
14208
|
+
const vectorPath = path20.join(this.indexPath, "vectors");
|
|
14209
|
+
const shouldFingerprintLegacyPair = !store.hasFingerprint() && existsSync12(vectorPath) && existsSync12(`${vectorPath}.meta.json`);
|
|
13208
14210
|
if (backfilledBlameMetadata || shouldFingerprintLegacyPair || removedStoredChunks) {
|
|
13209
14211
|
store.save();
|
|
13210
14212
|
}
|
|
@@ -13999,7 +15001,7 @@ var Indexer = class _Indexer {
|
|
|
13999
15001
|
const missingChunkKeys = [];
|
|
14000
15002
|
const chunkKeysByRemovedFile = /* @__PURE__ */ new Map();
|
|
14001
15003
|
for (const [filePath, chunkKeys] of filePathsToChunkKeys) {
|
|
14002
|
-
if (!
|
|
15004
|
+
if (!existsSync12(this.toMaterializedFilePath(filePath))) {
|
|
14003
15005
|
chunkKeysByRemovedFile.set(filePath, chunkKeys);
|
|
14004
15006
|
for (const key of chunkKeys) {
|
|
14005
15007
|
missingChunkKeys.push(key);
|
|
@@ -14062,7 +15064,7 @@ var Indexer = class _Indexer {
|
|
|
14062
15064
|
gcOrphanSymbols: 0,
|
|
14063
15065
|
gcOrphanCallEdges: 0,
|
|
14064
15066
|
resetCorruptedIndex: true,
|
|
14065
|
-
warning: this.getCorruptedIndexWarning(
|
|
15067
|
+
warning: this.getCorruptedIndexWarning(path20.join(this.indexPath, "codebase.db"))
|
|
14066
15068
|
};
|
|
14067
15069
|
}
|
|
14068
15070
|
this.logger.recordGc(removedCount, gcOrphanChunks, gcOrphanEmbeddings);
|
|
@@ -14092,7 +15094,8 @@ var Indexer = class _Indexer {
|
|
|
14092
15094
|
const maxChunkTokens = getSafeEmbeddingChunkTokenLimit(configuredProviderInfo);
|
|
14093
15095
|
const providerRateLimits = this.getProviderRateLimits(configuredProviderInfo.provider);
|
|
14094
15096
|
const roots = this.config.scope === "global" ? this.getScopedRoots() : null;
|
|
14095
|
-
const
|
|
15097
|
+
const shouldProcessFailedPath = (filePath) => filePath === null || !this.isStoredPathExcluded(filePath);
|
|
15098
|
+
const failedProcessing = this.prepareFailedBatchProcessing(roots, shouldProcessFailedPath);
|
|
14096
15099
|
if (failedProcessing.latestById.size === 0) {
|
|
14097
15100
|
this.finalizeFailedBatchWriteState(failedProcessing.state);
|
|
14098
15101
|
return { succeeded: 0, failed: 0, remaining: 0 };
|
|
@@ -14105,7 +15108,7 @@ var Indexer = class _Indexer {
|
|
|
14105
15108
|
const retryableChunks = this.iterateLatestFailedChunks(
|
|
14106
15109
|
failedProcessing.latestById,
|
|
14107
15110
|
roots,
|
|
14108
|
-
|
|
15111
|
+
shouldProcessFailedPath,
|
|
14109
15112
|
maxChunkTokens
|
|
14110
15113
|
);
|
|
14111
15114
|
for (const retryBatch of iterateOrderedFileBatches(
|
|
@@ -14375,9 +15378,9 @@ var Indexer = class _Indexer {
|
|
|
14375
15378
|
this.requireReadableComponents(readIssues, "database");
|
|
14376
15379
|
let shortest = [];
|
|
14377
15380
|
for (const branchKey of this.getBranchCatalogKeys()) {
|
|
14378
|
-
const
|
|
14379
|
-
if (
|
|
14380
|
-
shortest =
|
|
15381
|
+
const path26 = database.findShortestPath(fromName, toName, branchKey, maxDepth);
|
|
15382
|
+
if (path26.length > 0 && (shortest.length === 0 || path26.length < shortest.length)) {
|
|
15383
|
+
shortest = path26;
|
|
14381
15384
|
}
|
|
14382
15385
|
}
|
|
14383
15386
|
return shortest.map((hop) => this.resolveFilePathRecord(hop));
|
|
@@ -14425,13 +15428,13 @@ var Indexer = class _Indexer {
|
|
|
14425
15428
|
}
|
|
14426
15429
|
}
|
|
14427
15430
|
if (!found) continue;
|
|
14428
|
-
const
|
|
15431
|
+
const path26 = [];
|
|
14429
15432
|
let currentSymbolId = toSymbolId;
|
|
14430
15433
|
while (true) {
|
|
14431
15434
|
const symbol = symbolsById.get(currentSymbolId);
|
|
14432
15435
|
if (!symbol) break;
|
|
14433
15436
|
const parent = parentBySymbolId.get(currentSymbolId);
|
|
14434
|
-
|
|
15437
|
+
path26.push({
|
|
14435
15438
|
symbolId: symbol.id,
|
|
14436
15439
|
symbolName: symbol.name,
|
|
14437
15440
|
filePath: symbol.filePath,
|
|
@@ -14441,9 +15444,9 @@ var Indexer = class _Indexer {
|
|
|
14441
15444
|
if (!parent) break;
|
|
14442
15445
|
currentSymbolId = parent.parentId;
|
|
14443
15446
|
}
|
|
14444
|
-
|
|
14445
|
-
if (
|
|
14446
|
-
shortest =
|
|
15447
|
+
path26.reverse();
|
|
15448
|
+
if (path26.length > 0 && (shortest.length === 0 || path26.length < shortest.length)) {
|
|
15449
|
+
shortest = path26;
|
|
14447
15450
|
}
|
|
14448
15451
|
}
|
|
14449
15452
|
return shortest.map((hop) => this.resolveFilePathRecord(hop));
|
|
@@ -14594,7 +15597,7 @@ var Indexer = class _Indexer {
|
|
|
14594
15597
|
);
|
|
14595
15598
|
}
|
|
14596
15599
|
}
|
|
14597
|
-
const toStoredChangedFiles = (filePaths) => filePaths.map((filePath) => this.toStoredFilePath(
|
|
15600
|
+
const toStoredChangedFiles = (filePaths) => filePaths.map((filePath) => this.toStoredFilePath(path20.resolve(this.projectRoot, filePath)));
|
|
14598
15601
|
const storedChangedFiles = toStoredChangedFiles(changedFiles);
|
|
14599
15602
|
const directSymbols = database.getSymbolsForFiles(storedChangedFiles, branchKey);
|
|
14600
15603
|
const directIds = directSymbols.map((s) => s.id);
|
|
@@ -14743,12 +15746,12 @@ var Indexer = class _Indexer {
|
|
|
14743
15746
|
if (meta.filePath) filePaths.add(meta.filePath);
|
|
14744
15747
|
}
|
|
14745
15748
|
const directory = options?.directory?.replace(/\/$/, "");
|
|
14746
|
-
const absoluteDirectoryFilter = directory ?
|
|
15749
|
+
const absoluteDirectoryFilter = directory ? path20.resolve(this.projectRoot, directory) : void 0;
|
|
14747
15750
|
for (const filePath of filePaths) {
|
|
14748
15751
|
if (directory) {
|
|
14749
15752
|
const absoluteFilePath = this.resolveStoredFilePath(filePath);
|
|
14750
15753
|
const matchesRelative = filePath === directory || filePath.startsWith(directory + "/");
|
|
14751
|
-
const matchesProjectRelative = absoluteDirectoryFilter !== void 0 && (absoluteFilePath === absoluteDirectoryFilter || absoluteFilePath.startsWith(absoluteDirectoryFilter +
|
|
15754
|
+
const matchesProjectRelative = absoluteDirectoryFilter !== void 0 && (absoluteFilePath === absoluteDirectoryFilter || absoluteFilePath.startsWith(absoluteDirectoryFilter + path20.sep));
|
|
14752
15755
|
if (!matchesRelative && !matchesProjectRelative) {
|
|
14753
15756
|
continue;
|
|
14754
15757
|
}
|
|
@@ -14865,7 +15868,10 @@ function getOrCreateIndexer(projectRoot3, host) {
|
|
|
14865
15868
|
}
|
|
14866
15869
|
const indexer = new Indexer(projectRoot3, config, host);
|
|
14867
15870
|
indexerCache.set(key, indexer);
|
|
14868
|
-
configureAutoIndex(projectRoot3, host, config, () => getOrCreateIndexer(projectRoot3, host)
|
|
15871
|
+
configureAutoIndex(projectRoot3, host, config, () => getOrCreateIndexer(projectRoot3, host), {
|
|
15872
|
+
preserveManagedWorker: true,
|
|
15873
|
+
synchronizeBackgroundWorker: false
|
|
15874
|
+
});
|
|
14869
15875
|
return indexer;
|
|
14870
15876
|
}
|
|
14871
15877
|
function getIndexerForProject(projectRoot3, host) {
|
|
@@ -14880,7 +15886,9 @@ function refreshIndexerForDirectory(projectRoot3, host, config = parseConfig(loa
|
|
|
14880
15886
|
const key = getIndexerCacheKey(projectRoot3, host);
|
|
14881
15887
|
configCache.set(key, config);
|
|
14882
15888
|
indexerCache.set(key, new Indexer(projectRoot3, config, host));
|
|
14883
|
-
configureAutoIndex(projectRoot3, host, config, () => getOrCreateIndexer(projectRoot3, host)
|
|
15889
|
+
configureAutoIndex(projectRoot3, host, config, () => getOrCreateIndexer(projectRoot3, host), {
|
|
15890
|
+
synchronizeBackgroundWorker: true
|
|
15891
|
+
});
|
|
14884
15892
|
return config;
|
|
14885
15893
|
}
|
|
14886
15894
|
var AutoIndexRetrievalUnavailableError = class extends Error {
|
|
@@ -14907,7 +15915,7 @@ function trimOrUndefined(value) {
|
|
|
14907
15915
|
return normalized || void 0;
|
|
14908
15916
|
}
|
|
14909
15917
|
function normalizeCallGraphPath(value) {
|
|
14910
|
-
let normalized =
|
|
15918
|
+
let normalized = path21.posix.normalize(value.trim().replaceAll("\\", "/"));
|
|
14911
15919
|
if (normalized.startsWith("./")) {
|
|
14912
15920
|
normalized = normalized.slice(2);
|
|
14913
15921
|
}
|
|
@@ -15100,12 +16108,12 @@ async function getCallGraphPath(projectRoot3, host, from, to, maxDepth, fromFile
|
|
|
15100
16108
|
if (fromResolution.status !== "resolved" || toResolution.status !== "resolved") {
|
|
15101
16109
|
return { from: fromResolution, to: toResolution, path: [] };
|
|
15102
16110
|
}
|
|
15103
|
-
const
|
|
16111
|
+
const path26 = await indexer.findCallPathBySymbolIds(
|
|
15104
16112
|
fromResolution.symbolId,
|
|
15105
16113
|
toResolution.symbolId,
|
|
15106
16114
|
maxDepth
|
|
15107
16115
|
);
|
|
15108
|
-
return { from: fromResolution, to: toResolution, path:
|
|
16116
|
+
return { from: fromResolution, to: toResolution, path: path26 };
|
|
15109
16117
|
}
|
|
15110
16118
|
async function runIndexCodebase(projectRoot3, host, args, onProgress) {
|
|
15111
16119
|
const root = getProjectRoot(projectRoot3, host);
|
|
@@ -15303,15 +16311,15 @@ async function getIndexLogs(projectRoot3, host, args) {
|
|
|
15303
16311
|
function addKnowledgeBase(projectRoot3, host, knowledgeBasePath) {
|
|
15304
16312
|
const root = getProjectRoot(projectRoot3, host);
|
|
15305
16313
|
const inputPath = knowledgeBasePath.trim();
|
|
15306
|
-
const normalizedPath2 =
|
|
15307
|
-
|
|
16314
|
+
const normalizedPath2 = path21.resolve(
|
|
16315
|
+
path21.isAbsolute(inputPath) ? inputPath : resolveKnowledgeBasePath(inputPath, root)
|
|
15308
16316
|
);
|
|
15309
|
-
if (!
|
|
16317
|
+
if (!existsSync13(normalizedPath2)) {
|
|
15310
16318
|
return `Error: Directory does not exist: ${normalizedPath2}`;
|
|
15311
16319
|
}
|
|
15312
16320
|
let realPath;
|
|
15313
16321
|
try {
|
|
15314
|
-
realPath =
|
|
16322
|
+
realPath = realpathSync6(normalizedPath2);
|
|
15315
16323
|
} catch {
|
|
15316
16324
|
return `Error: Cannot resolve path: ${normalizedPath2}`;
|
|
15317
16325
|
}
|
|
@@ -15340,7 +16348,7 @@ function addKnowledgeBase(projectRoot3, host, knowledgeBasePath) {
|
|
|
15340
16348
|
}
|
|
15341
16349
|
}
|
|
15342
16350
|
for (const dotDir of sensitiveDotDirs) {
|
|
15343
|
-
const sensitiveDir =
|
|
16351
|
+
const sensitiveDir = path21.join(homeDir, dotDir);
|
|
15344
16352
|
if (sensitiveDir && (realPath === sensitiveDir || realPath.startsWith(`${sensitiveDir}/`))) {
|
|
15345
16353
|
return `Error: Adding sensitive directory as knowledge base is not allowed: ${normalizedPath2}`;
|
|
15346
16354
|
}
|
|
@@ -15386,7 +16394,7 @@ function listKnowledgeBases(projectRoot3, host) {
|
|
|
15386
16394
|
for (let i = 0; i < knowledgeBases.length; i++) {
|
|
15387
16395
|
const kb = knowledgeBases[i];
|
|
15388
16396
|
const resolvedPath = resolveKnowledgeBasePath(kb, root);
|
|
15389
|
-
const exists =
|
|
16397
|
+
const exists = existsSync13(resolvedPath);
|
|
15390
16398
|
result += `[${i + 1}] ${kb}
|
|
15391
16399
|
`;
|
|
15392
16400
|
result += ` Resolved: ${resolvedPath}
|
|
@@ -15403,7 +16411,7 @@ function listKnowledgeBases(projectRoot3, host) {
|
|
|
15403
16411
|
}
|
|
15404
16412
|
result += "\n";
|
|
15405
16413
|
}
|
|
15406
|
-
const hasHostConfig =
|
|
16414
|
+
const hasHostConfig = existsSync13(path21.join(root, getHostProjectConfigRelativePath(host)));
|
|
15407
16415
|
if (hasHostConfig) {
|
|
15408
16416
|
result += `
|
|
15409
16417
|
Config sources: 1 file(s).`;
|
|
@@ -15876,7 +16884,7 @@ async function resolveCodebaseContextUnmeasured(projectRoot3, host, input) {
|
|
|
15876
16884
|
const directory = input.directory ?? void 0;
|
|
15877
16885
|
const tokenBudget = input.tokenBudget ?? void 0;
|
|
15878
16886
|
if (from && to) {
|
|
15879
|
-
const
|
|
16887
|
+
const path26 = await getCallGraphPath(
|
|
15880
16888
|
projectRoot3,
|
|
15881
16889
|
host,
|
|
15882
16890
|
from,
|
|
@@ -15885,25 +16893,25 @@ async function resolveCodebaseContextUnmeasured(projectRoot3, host, input) {
|
|
|
15885
16893
|
fromFilePath,
|
|
15886
16894
|
toFilePath
|
|
15887
16895
|
);
|
|
15888
|
-
const pathText = formatCallGraphPathResult(
|
|
15889
|
-
if (
|
|
16896
|
+
const pathText = formatCallGraphPathResult(path26);
|
|
16897
|
+
if (path26.path.length > 0) {
|
|
15890
16898
|
const fitted2 = fitTextToContextBudget(
|
|
15891
16899
|
pathText,
|
|
15892
16900
|
tokenBudget
|
|
15893
16901
|
);
|
|
15894
16902
|
return {
|
|
15895
16903
|
text: fitted2.text,
|
|
15896
|
-
details: fittedDetails("path", fitted2,
|
|
16904
|
+
details: fittedDetails("path", fitted2, path26.path.length)
|
|
15897
16905
|
};
|
|
15898
16906
|
}
|
|
15899
|
-
if (
|
|
16907
|
+
if (path26.from.status !== "resolved" || path26.to.status !== "resolved") {
|
|
15900
16908
|
const fitted2 = fitTextToContextBudget(pathText, tokenBudget);
|
|
15901
16909
|
return {
|
|
15902
16910
|
text: fitted2.text,
|
|
15903
16911
|
details: fittedDetails("path", fitted2, 0)
|
|
15904
16912
|
};
|
|
15905
16913
|
}
|
|
15906
|
-
const resolvedFrom =
|
|
16914
|
+
const resolvedFrom = path26.from;
|
|
15907
16915
|
const { callers } = await getCallGraphData(projectRoot3, host, {
|
|
15908
16916
|
name: to,
|
|
15909
16917
|
direction: "callers",
|
|
@@ -16344,7 +17352,7 @@ function registerPiCallGraphTools(pi) {
|
|
|
16344
17352
|
}
|
|
16345
17353
|
|
|
16346
17354
|
// src/watcher/file-watcher.ts
|
|
16347
|
-
import { existsSync as
|
|
17355
|
+
import { existsSync as existsSync14, statSync as statSync6 } from "fs";
|
|
16348
17356
|
|
|
16349
17357
|
// node_modules/chokidar/index.js
|
|
16350
17358
|
import { EventEmitter as EventEmitter2 } from "events";
|
|
@@ -16436,7 +17444,7 @@ var ReaddirpStream = class extends Readable {
|
|
|
16436
17444
|
this._directoryFilter = normalizeFilter(opts.directoryFilter);
|
|
16437
17445
|
const statMethod = opts.lstat ? lstat : stat;
|
|
16438
17446
|
if (wantBigintFsStats) {
|
|
16439
|
-
this._stat = (
|
|
17447
|
+
this._stat = (path26) => statMethod(path26, { bigint: true });
|
|
16440
17448
|
} else {
|
|
16441
17449
|
this._stat = statMethod;
|
|
16442
17450
|
}
|
|
@@ -16461,8 +17469,8 @@ var ReaddirpStream = class extends Readable {
|
|
|
16461
17469
|
const par = this.parent;
|
|
16462
17470
|
const fil = par && par.files;
|
|
16463
17471
|
if (fil && fil.length > 0) {
|
|
16464
|
-
const { path:
|
|
16465
|
-
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent,
|
|
17472
|
+
const { path: path26, depth } = par;
|
|
17473
|
+
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path26));
|
|
16466
17474
|
const awaited = await Promise.all(slice);
|
|
16467
17475
|
for (const entry of awaited) {
|
|
16468
17476
|
if (!entry)
|
|
@@ -16502,21 +17510,21 @@ var ReaddirpStream = class extends Readable {
|
|
|
16502
17510
|
this.reading = false;
|
|
16503
17511
|
}
|
|
16504
17512
|
}
|
|
16505
|
-
async _exploreDir(
|
|
17513
|
+
async _exploreDir(path26, depth) {
|
|
16506
17514
|
let files;
|
|
16507
17515
|
try {
|
|
16508
|
-
files = await readdir(
|
|
17516
|
+
files = await readdir(path26, this._rdOptions);
|
|
16509
17517
|
} catch (error) {
|
|
16510
17518
|
this._onError(error);
|
|
16511
17519
|
}
|
|
16512
|
-
return { files, depth, path:
|
|
17520
|
+
return { files, depth, path: path26 };
|
|
16513
17521
|
}
|
|
16514
|
-
async _formatEntry(dirent,
|
|
17522
|
+
async _formatEntry(dirent, path26) {
|
|
16515
17523
|
let entry;
|
|
16516
|
-
const
|
|
17524
|
+
const basename8 = this._isDirent ? dirent.name : dirent;
|
|
16517
17525
|
try {
|
|
16518
|
-
const fullPath = presolve(pjoin(
|
|
16519
|
-
entry = { path: prelative(this._root, fullPath), fullPath, basename:
|
|
17526
|
+
const fullPath = presolve(pjoin(path26, basename8));
|
|
17527
|
+
entry = { path: prelative(this._root, fullPath), fullPath, basename: basename8 };
|
|
16520
17528
|
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
16521
17529
|
} catch (err) {
|
|
16522
17530
|
this._onError(err);
|
|
@@ -16915,16 +17923,16 @@ var delFromSet = (main, prop, item) => {
|
|
|
16915
17923
|
};
|
|
16916
17924
|
var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
|
|
16917
17925
|
var FsWatchInstances = /* @__PURE__ */ new Map();
|
|
16918
|
-
function createFsWatchInstance(
|
|
17926
|
+
function createFsWatchInstance(path26, options, listener, errHandler, emitRaw) {
|
|
16919
17927
|
const handleEvent = (rawEvent, evPath) => {
|
|
16920
|
-
listener(
|
|
16921
|
-
emitRaw(rawEvent, evPath, { watchedPath:
|
|
16922
|
-
if (evPath &&
|
|
16923
|
-
fsWatchBroadcast(sp.resolve(
|
|
17928
|
+
listener(path26);
|
|
17929
|
+
emitRaw(rawEvent, evPath, { watchedPath: path26 });
|
|
17930
|
+
if (evPath && path26 !== evPath) {
|
|
17931
|
+
fsWatchBroadcast(sp.resolve(path26, evPath), KEY_LISTENERS, sp.join(path26, evPath));
|
|
16924
17932
|
}
|
|
16925
17933
|
};
|
|
16926
17934
|
try {
|
|
16927
|
-
return fs_watch(
|
|
17935
|
+
return fs_watch(path26, {
|
|
16928
17936
|
persistent: options.persistent
|
|
16929
17937
|
}, handleEvent);
|
|
16930
17938
|
} catch (error) {
|
|
@@ -16940,12 +17948,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
|
|
|
16940
17948
|
listener(val1, val2, val3);
|
|
16941
17949
|
});
|
|
16942
17950
|
};
|
|
16943
|
-
var setFsWatchListener = (
|
|
17951
|
+
var setFsWatchListener = (path26, fullPath, options, handlers) => {
|
|
16944
17952
|
const { listener, errHandler, rawEmitter } = handlers;
|
|
16945
17953
|
let cont = FsWatchInstances.get(fullPath);
|
|
16946
17954
|
let watcher;
|
|
16947
17955
|
if (!options.persistent) {
|
|
16948
|
-
watcher = createFsWatchInstance(
|
|
17956
|
+
watcher = createFsWatchInstance(path26, options, listener, errHandler, rawEmitter);
|
|
16949
17957
|
if (!watcher)
|
|
16950
17958
|
return;
|
|
16951
17959
|
return watcher.close.bind(watcher);
|
|
@@ -16956,7 +17964,7 @@ var setFsWatchListener = (path25, fullPath, options, handlers) => {
|
|
|
16956
17964
|
addAndConvert(cont, KEY_RAW, rawEmitter);
|
|
16957
17965
|
} else {
|
|
16958
17966
|
watcher = createFsWatchInstance(
|
|
16959
|
-
|
|
17967
|
+
path26,
|
|
16960
17968
|
options,
|
|
16961
17969
|
fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
|
|
16962
17970
|
errHandler,
|
|
@@ -16971,7 +17979,7 @@ var setFsWatchListener = (path25, fullPath, options, handlers) => {
|
|
|
16971
17979
|
cont.watcherUnusable = true;
|
|
16972
17980
|
if (isWindows && error.code === "EPERM") {
|
|
16973
17981
|
try {
|
|
16974
|
-
const fd = await open(
|
|
17982
|
+
const fd = await open(path26, "r");
|
|
16975
17983
|
await fd.close();
|
|
16976
17984
|
broadcastErr(error);
|
|
16977
17985
|
} catch (err) {
|
|
@@ -17002,7 +18010,7 @@ var setFsWatchListener = (path25, fullPath, options, handlers) => {
|
|
|
17002
18010
|
};
|
|
17003
18011
|
};
|
|
17004
18012
|
var FsWatchFileInstances = /* @__PURE__ */ new Map();
|
|
17005
|
-
var setFsWatchFileListener = (
|
|
18013
|
+
var setFsWatchFileListener = (path26, fullPath, options, handlers) => {
|
|
17006
18014
|
const { listener, rawEmitter } = handlers;
|
|
17007
18015
|
let cont = FsWatchFileInstances.get(fullPath);
|
|
17008
18016
|
const copts = cont && cont.options;
|
|
@@ -17024,7 +18032,7 @@ var setFsWatchFileListener = (path25, fullPath, options, handlers) => {
|
|
|
17024
18032
|
});
|
|
17025
18033
|
const currmtime = curr.mtimeMs;
|
|
17026
18034
|
if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
|
|
17027
|
-
foreach(cont.listeners, (listener2) => listener2(
|
|
18035
|
+
foreach(cont.listeners, (listener2) => listener2(path26, curr));
|
|
17028
18036
|
}
|
|
17029
18037
|
})
|
|
17030
18038
|
};
|
|
@@ -17054,13 +18062,13 @@ var NodeFsHandler = class {
|
|
|
17054
18062
|
* @param listener on fs change
|
|
17055
18063
|
* @returns closer for the watcher instance
|
|
17056
18064
|
*/
|
|
17057
|
-
_watchWithNodeFs(
|
|
18065
|
+
_watchWithNodeFs(path26, listener) {
|
|
17058
18066
|
const opts = this.fsw.options;
|
|
17059
|
-
const directory = sp.dirname(
|
|
17060
|
-
const
|
|
18067
|
+
const directory = sp.dirname(path26);
|
|
18068
|
+
const basename8 = sp.basename(path26);
|
|
17061
18069
|
const parent = this.fsw._getWatchedDir(directory);
|
|
17062
|
-
parent.add(
|
|
17063
|
-
const absolutePath = sp.resolve(
|
|
18070
|
+
parent.add(basename8);
|
|
18071
|
+
const absolutePath = sp.resolve(path26);
|
|
17064
18072
|
const options = {
|
|
17065
18073
|
persistent: opts.persistent
|
|
17066
18074
|
};
|
|
@@ -17069,13 +18077,13 @@ var NodeFsHandler = class {
|
|
|
17069
18077
|
let closer;
|
|
17070
18078
|
if (opts.usePolling) {
|
|
17071
18079
|
const enableBin = opts.interval !== opts.binaryInterval;
|
|
17072
|
-
options.interval = enableBin && isBinaryPath(
|
|
17073
|
-
closer = setFsWatchFileListener(
|
|
18080
|
+
options.interval = enableBin && isBinaryPath(basename8) ? opts.binaryInterval : opts.interval;
|
|
18081
|
+
closer = setFsWatchFileListener(path26, absolutePath, options, {
|
|
17074
18082
|
listener,
|
|
17075
18083
|
rawEmitter: this.fsw._emitRaw
|
|
17076
18084
|
});
|
|
17077
18085
|
} else {
|
|
17078
|
-
closer = setFsWatchListener(
|
|
18086
|
+
closer = setFsWatchListener(path26, absolutePath, options, {
|
|
17079
18087
|
listener,
|
|
17080
18088
|
errHandler: this._boundHandleError,
|
|
17081
18089
|
rawEmitter: this.fsw._emitRaw
|
|
@@ -17091,13 +18099,13 @@ var NodeFsHandler = class {
|
|
|
17091
18099
|
if (this.fsw.closed) {
|
|
17092
18100
|
return;
|
|
17093
18101
|
}
|
|
17094
|
-
const
|
|
17095
|
-
const
|
|
17096
|
-
const parent = this.fsw._getWatchedDir(
|
|
18102
|
+
const dirname14 = sp.dirname(file);
|
|
18103
|
+
const basename8 = sp.basename(file);
|
|
18104
|
+
const parent = this.fsw._getWatchedDir(dirname14);
|
|
17097
18105
|
let prevStats = stats;
|
|
17098
|
-
if (parent.has(
|
|
18106
|
+
if (parent.has(basename8))
|
|
17099
18107
|
return;
|
|
17100
|
-
const listener = async (
|
|
18108
|
+
const listener = async (path26, newStats) => {
|
|
17101
18109
|
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
|
|
17102
18110
|
return;
|
|
17103
18111
|
if (!newStats || newStats.mtimeMs === 0) {
|
|
@@ -17111,18 +18119,18 @@ var NodeFsHandler = class {
|
|
|
17111
18119
|
this.fsw._emit(EV.CHANGE, file, newStats2);
|
|
17112
18120
|
}
|
|
17113
18121
|
if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
|
|
17114
|
-
this.fsw._closeFile(
|
|
18122
|
+
this.fsw._closeFile(path26);
|
|
17115
18123
|
prevStats = newStats2;
|
|
17116
18124
|
const closer2 = this._watchWithNodeFs(file, listener);
|
|
17117
18125
|
if (closer2)
|
|
17118
|
-
this.fsw._addPathCloser(
|
|
18126
|
+
this.fsw._addPathCloser(path26, closer2);
|
|
17119
18127
|
} else {
|
|
17120
18128
|
prevStats = newStats2;
|
|
17121
18129
|
}
|
|
17122
18130
|
} catch (error) {
|
|
17123
|
-
this.fsw._remove(
|
|
18131
|
+
this.fsw._remove(dirname14, basename8);
|
|
17124
18132
|
}
|
|
17125
|
-
} else if (parent.has(
|
|
18133
|
+
} else if (parent.has(basename8)) {
|
|
17126
18134
|
const at = newStats.atimeMs;
|
|
17127
18135
|
const mt = newStats.mtimeMs;
|
|
17128
18136
|
if (!at || at <= mt || mt !== prevStats.mtimeMs) {
|
|
@@ -17147,7 +18155,7 @@ var NodeFsHandler = class {
|
|
|
17147
18155
|
* @param item basename of this item
|
|
17148
18156
|
* @returns true if no more processing is needed for this entry.
|
|
17149
18157
|
*/
|
|
17150
|
-
async _handleSymlink(entry, directory,
|
|
18158
|
+
async _handleSymlink(entry, directory, path26, item) {
|
|
17151
18159
|
if (this.fsw.closed) {
|
|
17152
18160
|
return;
|
|
17153
18161
|
}
|
|
@@ -17157,7 +18165,7 @@ var NodeFsHandler = class {
|
|
|
17157
18165
|
this.fsw._incrReadyCount();
|
|
17158
18166
|
let linkPath;
|
|
17159
18167
|
try {
|
|
17160
|
-
linkPath = await fsrealpath(
|
|
18168
|
+
linkPath = await fsrealpath(path26);
|
|
17161
18169
|
} catch (e) {
|
|
17162
18170
|
this.fsw._emitReady();
|
|
17163
18171
|
return true;
|
|
@@ -17167,12 +18175,12 @@ var NodeFsHandler = class {
|
|
|
17167
18175
|
if (dir.has(item)) {
|
|
17168
18176
|
if (this.fsw._symlinkPaths.get(full) !== linkPath) {
|
|
17169
18177
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
17170
|
-
this.fsw._emit(EV.CHANGE,
|
|
18178
|
+
this.fsw._emit(EV.CHANGE, path26, entry.stats);
|
|
17171
18179
|
}
|
|
17172
18180
|
} else {
|
|
17173
18181
|
dir.add(item);
|
|
17174
18182
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
17175
|
-
this.fsw._emit(EV.ADD,
|
|
18183
|
+
this.fsw._emit(EV.ADD, path26, entry.stats);
|
|
17176
18184
|
}
|
|
17177
18185
|
this.fsw._emitReady();
|
|
17178
18186
|
return true;
|
|
@@ -17202,9 +18210,9 @@ var NodeFsHandler = class {
|
|
|
17202
18210
|
return;
|
|
17203
18211
|
}
|
|
17204
18212
|
const item = entry.path;
|
|
17205
|
-
let
|
|
18213
|
+
let path26 = sp.join(directory, item);
|
|
17206
18214
|
current.add(item);
|
|
17207
|
-
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory,
|
|
18215
|
+
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path26, item)) {
|
|
17208
18216
|
return;
|
|
17209
18217
|
}
|
|
17210
18218
|
if (this.fsw.closed) {
|
|
@@ -17213,11 +18221,11 @@ var NodeFsHandler = class {
|
|
|
17213
18221
|
}
|
|
17214
18222
|
if (item === target || !target && !previous.has(item)) {
|
|
17215
18223
|
this.fsw._incrReadyCount();
|
|
17216
|
-
|
|
17217
|
-
this._addToNodeFs(
|
|
18224
|
+
path26 = sp.join(dir, sp.relative(dir, path26));
|
|
18225
|
+
this._addToNodeFs(path26, initialAdd, wh, depth + 1);
|
|
17218
18226
|
}
|
|
17219
18227
|
}).on(EV.ERROR, this._boundHandleError);
|
|
17220
|
-
return new Promise((
|
|
18228
|
+
return new Promise((resolve18, reject) => {
|
|
17221
18229
|
if (!stream)
|
|
17222
18230
|
return reject();
|
|
17223
18231
|
stream.once(STR_END, () => {
|
|
@@ -17226,7 +18234,7 @@ var NodeFsHandler = class {
|
|
|
17226
18234
|
return;
|
|
17227
18235
|
}
|
|
17228
18236
|
const wasThrottled = throttler ? throttler.clear() : false;
|
|
17229
|
-
|
|
18237
|
+
resolve18(void 0);
|
|
17230
18238
|
previous.getChildren().filter((item) => {
|
|
17231
18239
|
return item !== directory && !current.has(item);
|
|
17232
18240
|
}).forEach((item) => {
|
|
@@ -17283,13 +18291,13 @@ var NodeFsHandler = class {
|
|
|
17283
18291
|
* @param depth Child path actually targeted for watch
|
|
17284
18292
|
* @param target Child path actually targeted for watch
|
|
17285
18293
|
*/
|
|
17286
|
-
async _addToNodeFs(
|
|
18294
|
+
async _addToNodeFs(path26, initialAdd, priorWh, depth, target) {
|
|
17287
18295
|
const ready = this.fsw._emitReady;
|
|
17288
|
-
if (this.fsw._isIgnored(
|
|
18296
|
+
if (this.fsw._isIgnored(path26) || this.fsw.closed) {
|
|
17289
18297
|
ready();
|
|
17290
18298
|
return false;
|
|
17291
18299
|
}
|
|
17292
|
-
const wh = this.fsw._getWatchHelpers(
|
|
18300
|
+
const wh = this.fsw._getWatchHelpers(path26);
|
|
17293
18301
|
if (priorWh) {
|
|
17294
18302
|
wh.filterPath = (entry) => priorWh.filterPath(entry);
|
|
17295
18303
|
wh.filterDir = (entry) => priorWh.filterDir(entry);
|
|
@@ -17305,8 +18313,8 @@ var NodeFsHandler = class {
|
|
|
17305
18313
|
const follow = this.fsw.options.followSymlinks;
|
|
17306
18314
|
let closer;
|
|
17307
18315
|
if (stats.isDirectory()) {
|
|
17308
|
-
const absPath = sp.resolve(
|
|
17309
|
-
const targetPath = follow ? await fsrealpath(
|
|
18316
|
+
const absPath = sp.resolve(path26);
|
|
18317
|
+
const targetPath = follow ? await fsrealpath(path26) : path26;
|
|
17310
18318
|
if (this.fsw.closed)
|
|
17311
18319
|
return;
|
|
17312
18320
|
closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
|
|
@@ -17316,29 +18324,29 @@ var NodeFsHandler = class {
|
|
|
17316
18324
|
this.fsw._symlinkPaths.set(absPath, targetPath);
|
|
17317
18325
|
}
|
|
17318
18326
|
} else if (stats.isSymbolicLink()) {
|
|
17319
|
-
const targetPath = follow ? await fsrealpath(
|
|
18327
|
+
const targetPath = follow ? await fsrealpath(path26) : path26;
|
|
17320
18328
|
if (this.fsw.closed)
|
|
17321
18329
|
return;
|
|
17322
18330
|
const parent = sp.dirname(wh.watchPath);
|
|
17323
18331
|
this.fsw._getWatchedDir(parent).add(wh.watchPath);
|
|
17324
18332
|
this.fsw._emit(EV.ADD, wh.watchPath, stats);
|
|
17325
|
-
closer = await this._handleDir(parent, stats, initialAdd, depth,
|
|
18333
|
+
closer = await this._handleDir(parent, stats, initialAdd, depth, path26, wh, targetPath);
|
|
17326
18334
|
if (this.fsw.closed)
|
|
17327
18335
|
return;
|
|
17328
18336
|
if (targetPath !== void 0) {
|
|
17329
|
-
this.fsw._symlinkPaths.set(sp.resolve(
|
|
18337
|
+
this.fsw._symlinkPaths.set(sp.resolve(path26), targetPath);
|
|
17330
18338
|
}
|
|
17331
18339
|
} else {
|
|
17332
18340
|
closer = this._handleFile(wh.watchPath, stats, initialAdd);
|
|
17333
18341
|
}
|
|
17334
18342
|
ready();
|
|
17335
18343
|
if (closer)
|
|
17336
|
-
this.fsw._addPathCloser(
|
|
18344
|
+
this.fsw._addPathCloser(path26, closer);
|
|
17337
18345
|
return false;
|
|
17338
18346
|
} catch (error) {
|
|
17339
18347
|
if (this.fsw._handleError(error)) {
|
|
17340
18348
|
ready();
|
|
17341
|
-
return
|
|
18349
|
+
return path26;
|
|
17342
18350
|
}
|
|
17343
18351
|
}
|
|
17344
18352
|
}
|
|
@@ -17381,24 +18389,24 @@ function createPattern(matcher) {
|
|
|
17381
18389
|
}
|
|
17382
18390
|
return () => false;
|
|
17383
18391
|
}
|
|
17384
|
-
function normalizePath2(
|
|
17385
|
-
if (typeof
|
|
18392
|
+
function normalizePath2(path26) {
|
|
18393
|
+
if (typeof path26 !== "string")
|
|
17386
18394
|
throw new Error("string expected");
|
|
17387
|
-
|
|
17388
|
-
|
|
18395
|
+
path26 = sp2.normalize(path26);
|
|
18396
|
+
path26 = path26.replace(/\\/g, "/");
|
|
17389
18397
|
let prepend = false;
|
|
17390
|
-
if (
|
|
18398
|
+
if (path26.startsWith("//"))
|
|
17391
18399
|
prepend = true;
|
|
17392
|
-
|
|
18400
|
+
path26 = path26.replace(DOUBLE_SLASH_RE, "/");
|
|
17393
18401
|
if (prepend)
|
|
17394
|
-
|
|
17395
|
-
return
|
|
18402
|
+
path26 = "/" + path26;
|
|
18403
|
+
return path26;
|
|
17396
18404
|
}
|
|
17397
18405
|
function matchPatterns(patterns, testString, stats) {
|
|
17398
|
-
const
|
|
18406
|
+
const path26 = normalizePath2(testString);
|
|
17399
18407
|
for (let index = 0; index < patterns.length; index++) {
|
|
17400
18408
|
const pattern = patterns[index];
|
|
17401
|
-
if (pattern(
|
|
18409
|
+
if (pattern(path26, stats)) {
|
|
17402
18410
|
return true;
|
|
17403
18411
|
}
|
|
17404
18412
|
}
|
|
@@ -17436,19 +18444,19 @@ var toUnix = (string) => {
|
|
|
17436
18444
|
}
|
|
17437
18445
|
return str;
|
|
17438
18446
|
};
|
|
17439
|
-
var normalizePathToUnix = (
|
|
17440
|
-
var normalizeIgnored = (cwd = "") => (
|
|
17441
|
-
if (typeof
|
|
17442
|
-
return normalizePathToUnix(sp2.isAbsolute(
|
|
18447
|
+
var normalizePathToUnix = (path26) => toUnix(sp2.normalize(toUnix(path26)));
|
|
18448
|
+
var normalizeIgnored = (cwd = "") => (path26) => {
|
|
18449
|
+
if (typeof path26 === "string") {
|
|
18450
|
+
return normalizePathToUnix(sp2.isAbsolute(path26) ? path26 : sp2.join(cwd, path26));
|
|
17443
18451
|
} else {
|
|
17444
|
-
return
|
|
18452
|
+
return path26;
|
|
17445
18453
|
}
|
|
17446
18454
|
};
|
|
17447
|
-
var getAbsolutePath = (
|
|
17448
|
-
if (sp2.isAbsolute(
|
|
17449
|
-
return
|
|
18455
|
+
var getAbsolutePath = (path26, cwd) => {
|
|
18456
|
+
if (sp2.isAbsolute(path26)) {
|
|
18457
|
+
return path26;
|
|
17450
18458
|
}
|
|
17451
|
-
return sp2.join(cwd,
|
|
18459
|
+
return sp2.join(cwd, path26);
|
|
17452
18460
|
};
|
|
17453
18461
|
var EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
|
|
17454
18462
|
var DirEntry = class {
|
|
@@ -17513,10 +18521,10 @@ var WatchHelper = class {
|
|
|
17513
18521
|
dirParts;
|
|
17514
18522
|
followSymlinks;
|
|
17515
18523
|
statMethod;
|
|
17516
|
-
constructor(
|
|
18524
|
+
constructor(path26, follow, fsw) {
|
|
17517
18525
|
this.fsw = fsw;
|
|
17518
|
-
const watchPath =
|
|
17519
|
-
this.path =
|
|
18526
|
+
const watchPath = path26;
|
|
18527
|
+
this.path = path26 = path26.replace(REPLACER_RE, "");
|
|
17520
18528
|
this.watchPath = watchPath;
|
|
17521
18529
|
this.fullWatchPath = sp2.resolve(watchPath);
|
|
17522
18530
|
this.dirParts = [];
|
|
@@ -17656,20 +18664,20 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
17656
18664
|
this._closePromise = void 0;
|
|
17657
18665
|
let paths = unifyPaths(paths_);
|
|
17658
18666
|
if (cwd) {
|
|
17659
|
-
paths = paths.map((
|
|
17660
|
-
const absPath = getAbsolutePath(
|
|
18667
|
+
paths = paths.map((path26) => {
|
|
18668
|
+
const absPath = getAbsolutePath(path26, cwd);
|
|
17661
18669
|
return absPath;
|
|
17662
18670
|
});
|
|
17663
18671
|
}
|
|
17664
|
-
paths.forEach((
|
|
17665
|
-
this._removeIgnoredPath(
|
|
18672
|
+
paths.forEach((path26) => {
|
|
18673
|
+
this._removeIgnoredPath(path26);
|
|
17666
18674
|
});
|
|
17667
18675
|
this._userIgnored = void 0;
|
|
17668
18676
|
if (!this._readyCount)
|
|
17669
18677
|
this._readyCount = 0;
|
|
17670
18678
|
this._readyCount += paths.length;
|
|
17671
|
-
Promise.all(paths.map(async (
|
|
17672
|
-
const res = await this._nodeFsHandler._addToNodeFs(
|
|
18679
|
+
Promise.all(paths.map(async (path26) => {
|
|
18680
|
+
const res = await this._nodeFsHandler._addToNodeFs(path26, !_internal, void 0, 0, _origAdd);
|
|
17673
18681
|
if (res)
|
|
17674
18682
|
this._emitReady();
|
|
17675
18683
|
return res;
|
|
@@ -17691,17 +18699,17 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
17691
18699
|
return this;
|
|
17692
18700
|
const paths = unifyPaths(paths_);
|
|
17693
18701
|
const { cwd } = this.options;
|
|
17694
|
-
paths.forEach((
|
|
17695
|
-
if (!sp2.isAbsolute(
|
|
18702
|
+
paths.forEach((path26) => {
|
|
18703
|
+
if (!sp2.isAbsolute(path26) && !this._closers.has(path26)) {
|
|
17696
18704
|
if (cwd)
|
|
17697
|
-
|
|
17698
|
-
|
|
18705
|
+
path26 = sp2.join(cwd, path26);
|
|
18706
|
+
path26 = sp2.resolve(path26);
|
|
17699
18707
|
}
|
|
17700
|
-
this._closePath(
|
|
17701
|
-
this._addIgnoredPath(
|
|
17702
|
-
if (this._watched.has(
|
|
18708
|
+
this._closePath(path26);
|
|
18709
|
+
this._addIgnoredPath(path26);
|
|
18710
|
+
if (this._watched.has(path26)) {
|
|
17703
18711
|
this._addIgnoredPath({
|
|
17704
|
-
path:
|
|
18712
|
+
path: path26,
|
|
17705
18713
|
recursive: true
|
|
17706
18714
|
});
|
|
17707
18715
|
}
|
|
@@ -17765,38 +18773,38 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
17765
18773
|
* @param stats arguments to be passed with event
|
|
17766
18774
|
* @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
|
|
17767
18775
|
*/
|
|
17768
|
-
async _emit(event,
|
|
18776
|
+
async _emit(event, path26, stats) {
|
|
17769
18777
|
if (this.closed)
|
|
17770
18778
|
return;
|
|
17771
18779
|
const opts = this.options;
|
|
17772
18780
|
if (isWindows)
|
|
17773
|
-
|
|
18781
|
+
path26 = sp2.normalize(path26);
|
|
17774
18782
|
if (opts.cwd)
|
|
17775
|
-
|
|
17776
|
-
const args = [
|
|
18783
|
+
path26 = sp2.relative(opts.cwd, path26);
|
|
18784
|
+
const args = [path26];
|
|
17777
18785
|
if (stats != null)
|
|
17778
18786
|
args.push(stats);
|
|
17779
18787
|
const awf = opts.awaitWriteFinish;
|
|
17780
18788
|
let pw;
|
|
17781
|
-
if (awf && (pw = this._pendingWrites.get(
|
|
18789
|
+
if (awf && (pw = this._pendingWrites.get(path26))) {
|
|
17782
18790
|
pw.lastChange = /* @__PURE__ */ new Date();
|
|
17783
18791
|
return this;
|
|
17784
18792
|
}
|
|
17785
18793
|
if (opts.atomic) {
|
|
17786
18794
|
if (event === EVENTS.UNLINK) {
|
|
17787
|
-
this._pendingUnlinks.set(
|
|
18795
|
+
this._pendingUnlinks.set(path26, [event, ...args]);
|
|
17788
18796
|
setTimeout(() => {
|
|
17789
|
-
this._pendingUnlinks.forEach((entry,
|
|
18797
|
+
this._pendingUnlinks.forEach((entry, path27) => {
|
|
17790
18798
|
this.emit(...entry);
|
|
17791
18799
|
this.emit(EVENTS.ALL, ...entry);
|
|
17792
|
-
this._pendingUnlinks.delete(
|
|
18800
|
+
this._pendingUnlinks.delete(path27);
|
|
17793
18801
|
});
|
|
17794
18802
|
}, typeof opts.atomic === "number" ? opts.atomic : 100);
|
|
17795
18803
|
return this;
|
|
17796
18804
|
}
|
|
17797
|
-
if (event === EVENTS.ADD && this._pendingUnlinks.has(
|
|
18805
|
+
if (event === EVENTS.ADD && this._pendingUnlinks.has(path26)) {
|
|
17798
18806
|
event = EVENTS.CHANGE;
|
|
17799
|
-
this._pendingUnlinks.delete(
|
|
18807
|
+
this._pendingUnlinks.delete(path26);
|
|
17800
18808
|
}
|
|
17801
18809
|
}
|
|
17802
18810
|
if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
|
|
@@ -17814,16 +18822,16 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
17814
18822
|
this.emitWithAll(event, args);
|
|
17815
18823
|
}
|
|
17816
18824
|
};
|
|
17817
|
-
this._awaitWriteFinish(
|
|
18825
|
+
this._awaitWriteFinish(path26, awf.stabilityThreshold, event, awfEmit);
|
|
17818
18826
|
return this;
|
|
17819
18827
|
}
|
|
17820
18828
|
if (event === EVENTS.CHANGE) {
|
|
17821
|
-
const isThrottled = !this._throttle(EVENTS.CHANGE,
|
|
18829
|
+
const isThrottled = !this._throttle(EVENTS.CHANGE, path26, 50);
|
|
17822
18830
|
if (isThrottled)
|
|
17823
18831
|
return this;
|
|
17824
18832
|
}
|
|
17825
18833
|
if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
|
|
17826
|
-
const fullPath = opts.cwd ? sp2.join(opts.cwd,
|
|
18834
|
+
const fullPath = opts.cwd ? sp2.join(opts.cwd, path26) : path26;
|
|
17827
18835
|
let stats2;
|
|
17828
18836
|
try {
|
|
17829
18837
|
stats2 = await stat3(fullPath);
|
|
@@ -17854,23 +18862,23 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
17854
18862
|
* @param timeout duration of time to suppress duplicate actions
|
|
17855
18863
|
* @returns tracking object or false if action should be suppressed
|
|
17856
18864
|
*/
|
|
17857
|
-
_throttle(actionType,
|
|
18865
|
+
_throttle(actionType, path26, timeout) {
|
|
17858
18866
|
if (!this._throttled.has(actionType)) {
|
|
17859
18867
|
this._throttled.set(actionType, /* @__PURE__ */ new Map());
|
|
17860
18868
|
}
|
|
17861
18869
|
const action = this._throttled.get(actionType);
|
|
17862
18870
|
if (!action)
|
|
17863
18871
|
throw new Error("invalid throttle");
|
|
17864
|
-
const actionPath = action.get(
|
|
18872
|
+
const actionPath = action.get(path26);
|
|
17865
18873
|
if (actionPath) {
|
|
17866
18874
|
actionPath.count++;
|
|
17867
18875
|
return false;
|
|
17868
18876
|
}
|
|
17869
18877
|
let timeoutObject;
|
|
17870
18878
|
const clear = () => {
|
|
17871
|
-
const item = action.get(
|
|
18879
|
+
const item = action.get(path26);
|
|
17872
18880
|
const count = item ? item.count : 0;
|
|
17873
|
-
action.delete(
|
|
18881
|
+
action.delete(path26);
|
|
17874
18882
|
clearTimeout(timeoutObject);
|
|
17875
18883
|
if (item)
|
|
17876
18884
|
clearTimeout(item.timeoutObject);
|
|
@@ -17878,7 +18886,7 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
17878
18886
|
};
|
|
17879
18887
|
timeoutObject = setTimeout(clear, timeout);
|
|
17880
18888
|
const thr = { timeoutObject, clear, count: 0 };
|
|
17881
|
-
action.set(
|
|
18889
|
+
action.set(path26, thr);
|
|
17882
18890
|
return thr;
|
|
17883
18891
|
}
|
|
17884
18892
|
_incrReadyCount() {
|
|
@@ -17892,44 +18900,44 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
17892
18900
|
* @param event
|
|
17893
18901
|
* @param awfEmit Callback to be called when ready for event to be emitted.
|
|
17894
18902
|
*/
|
|
17895
|
-
_awaitWriteFinish(
|
|
18903
|
+
_awaitWriteFinish(path26, threshold, event, awfEmit) {
|
|
17896
18904
|
const awf = this.options.awaitWriteFinish;
|
|
17897
18905
|
if (typeof awf !== "object")
|
|
17898
18906
|
return;
|
|
17899
18907
|
const pollInterval = awf.pollInterval;
|
|
17900
18908
|
let timeoutHandler;
|
|
17901
|
-
let fullPath =
|
|
17902
|
-
if (this.options.cwd && !sp2.isAbsolute(
|
|
17903
|
-
fullPath = sp2.join(this.options.cwd,
|
|
18909
|
+
let fullPath = path26;
|
|
18910
|
+
if (this.options.cwd && !sp2.isAbsolute(path26)) {
|
|
18911
|
+
fullPath = sp2.join(this.options.cwd, path26);
|
|
17904
18912
|
}
|
|
17905
18913
|
const now2 = /* @__PURE__ */ new Date();
|
|
17906
18914
|
const writes = this._pendingWrites;
|
|
17907
18915
|
function awaitWriteFinishFn(prevStat) {
|
|
17908
18916
|
statcb(fullPath, (err, curStat) => {
|
|
17909
|
-
if (err || !writes.has(
|
|
18917
|
+
if (err || !writes.has(path26)) {
|
|
17910
18918
|
if (err && err.code !== "ENOENT")
|
|
17911
18919
|
awfEmit(err);
|
|
17912
18920
|
return;
|
|
17913
18921
|
}
|
|
17914
18922
|
const now3 = Number(/* @__PURE__ */ new Date());
|
|
17915
18923
|
if (prevStat && curStat.size !== prevStat.size) {
|
|
17916
|
-
writes.get(
|
|
18924
|
+
writes.get(path26).lastChange = now3;
|
|
17917
18925
|
}
|
|
17918
|
-
const pw = writes.get(
|
|
18926
|
+
const pw = writes.get(path26);
|
|
17919
18927
|
const df = now3 - pw.lastChange;
|
|
17920
18928
|
if (df >= threshold) {
|
|
17921
|
-
writes.delete(
|
|
18929
|
+
writes.delete(path26);
|
|
17922
18930
|
awfEmit(void 0, curStat);
|
|
17923
18931
|
} else {
|
|
17924
18932
|
timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
|
|
17925
18933
|
}
|
|
17926
18934
|
});
|
|
17927
18935
|
}
|
|
17928
|
-
if (!writes.has(
|
|
17929
|
-
writes.set(
|
|
18936
|
+
if (!writes.has(path26)) {
|
|
18937
|
+
writes.set(path26, {
|
|
17930
18938
|
lastChange: now2,
|
|
17931
18939
|
cancelWait: () => {
|
|
17932
|
-
writes.delete(
|
|
18940
|
+
writes.delete(path26);
|
|
17933
18941
|
clearTimeout(timeoutHandler);
|
|
17934
18942
|
return event;
|
|
17935
18943
|
}
|
|
@@ -17940,8 +18948,8 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
17940
18948
|
/**
|
|
17941
18949
|
* Determines whether user has asked to ignore this path.
|
|
17942
18950
|
*/
|
|
17943
|
-
_isIgnored(
|
|
17944
|
-
if (this.options.atomic && DOT_RE.test(
|
|
18951
|
+
_isIgnored(path26, stats) {
|
|
18952
|
+
if (this.options.atomic && DOT_RE.test(path26))
|
|
17945
18953
|
return true;
|
|
17946
18954
|
if (!this._userIgnored) {
|
|
17947
18955
|
const { cwd } = this.options;
|
|
@@ -17951,17 +18959,17 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
17951
18959
|
const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
|
|
17952
18960
|
this._userIgnored = anymatch(list, void 0);
|
|
17953
18961
|
}
|
|
17954
|
-
return this._userIgnored(
|
|
18962
|
+
return this._userIgnored(path26, stats);
|
|
17955
18963
|
}
|
|
17956
|
-
_isntIgnored(
|
|
17957
|
-
return !this._isIgnored(
|
|
18964
|
+
_isntIgnored(path26, stat5) {
|
|
18965
|
+
return !this._isIgnored(path26, stat5);
|
|
17958
18966
|
}
|
|
17959
18967
|
/**
|
|
17960
18968
|
* Provides a set of common helpers and properties relating to symlink handling.
|
|
17961
18969
|
* @param path file or directory pattern being watched
|
|
17962
18970
|
*/
|
|
17963
|
-
_getWatchHelpers(
|
|
17964
|
-
return new WatchHelper(
|
|
18971
|
+
_getWatchHelpers(path26) {
|
|
18972
|
+
return new WatchHelper(path26, this.options.followSymlinks, this);
|
|
17965
18973
|
}
|
|
17966
18974
|
// Directory helpers
|
|
17967
18975
|
// -----------------
|
|
@@ -17993,63 +19001,63 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
17993
19001
|
* @param item base path of item/directory
|
|
17994
19002
|
*/
|
|
17995
19003
|
_remove(directory, item, isDirectory) {
|
|
17996
|
-
const
|
|
17997
|
-
const fullPath = sp2.resolve(
|
|
17998
|
-
isDirectory = isDirectory != null ? isDirectory : this._watched.has(
|
|
17999
|
-
if (!this._throttle("remove",
|
|
19004
|
+
const path26 = sp2.join(directory, item);
|
|
19005
|
+
const fullPath = sp2.resolve(path26);
|
|
19006
|
+
isDirectory = isDirectory != null ? isDirectory : this._watched.has(path26) || this._watched.has(fullPath);
|
|
19007
|
+
if (!this._throttle("remove", path26, 100))
|
|
18000
19008
|
return;
|
|
18001
19009
|
if (!isDirectory && this._watched.size === 1) {
|
|
18002
19010
|
this.add(directory, item, true);
|
|
18003
19011
|
}
|
|
18004
|
-
const wp = this._getWatchedDir(
|
|
19012
|
+
const wp = this._getWatchedDir(path26);
|
|
18005
19013
|
const nestedDirectoryChildren = wp.getChildren();
|
|
18006
|
-
nestedDirectoryChildren.forEach((nested) => this._remove(
|
|
19014
|
+
nestedDirectoryChildren.forEach((nested) => this._remove(path26, nested));
|
|
18007
19015
|
const parent = this._getWatchedDir(directory);
|
|
18008
19016
|
const wasTracked = parent.has(item);
|
|
18009
19017
|
parent.remove(item);
|
|
18010
19018
|
if (this._symlinkPaths.has(fullPath)) {
|
|
18011
19019
|
this._symlinkPaths.delete(fullPath);
|
|
18012
19020
|
}
|
|
18013
|
-
let relPath =
|
|
19021
|
+
let relPath = path26;
|
|
18014
19022
|
if (this.options.cwd)
|
|
18015
|
-
relPath = sp2.relative(this.options.cwd,
|
|
19023
|
+
relPath = sp2.relative(this.options.cwd, path26);
|
|
18016
19024
|
if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
|
|
18017
19025
|
const event = this._pendingWrites.get(relPath).cancelWait();
|
|
18018
19026
|
if (event === EVENTS.ADD)
|
|
18019
19027
|
return;
|
|
18020
19028
|
}
|
|
18021
|
-
this._watched.delete(
|
|
19029
|
+
this._watched.delete(path26);
|
|
18022
19030
|
this._watched.delete(fullPath);
|
|
18023
19031
|
const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
|
|
18024
|
-
if (wasTracked && !this._isIgnored(
|
|
18025
|
-
this._emit(eventName,
|
|
18026
|
-
this._closePath(
|
|
19032
|
+
if (wasTracked && !this._isIgnored(path26))
|
|
19033
|
+
this._emit(eventName, path26);
|
|
19034
|
+
this._closePath(path26);
|
|
18027
19035
|
}
|
|
18028
19036
|
/**
|
|
18029
19037
|
* Closes all watchers for a path
|
|
18030
19038
|
*/
|
|
18031
|
-
_closePath(
|
|
18032
|
-
this._closeFile(
|
|
18033
|
-
const dir = sp2.dirname(
|
|
18034
|
-
this._getWatchedDir(dir).remove(sp2.basename(
|
|
19039
|
+
_closePath(path26) {
|
|
19040
|
+
this._closeFile(path26);
|
|
19041
|
+
const dir = sp2.dirname(path26);
|
|
19042
|
+
this._getWatchedDir(dir).remove(sp2.basename(path26));
|
|
18035
19043
|
}
|
|
18036
19044
|
/**
|
|
18037
19045
|
* Closes only file-specific watchers
|
|
18038
19046
|
*/
|
|
18039
|
-
_closeFile(
|
|
18040
|
-
const closers = this._closers.get(
|
|
19047
|
+
_closeFile(path26) {
|
|
19048
|
+
const closers = this._closers.get(path26);
|
|
18041
19049
|
if (!closers)
|
|
18042
19050
|
return;
|
|
18043
19051
|
closers.forEach((closer) => closer());
|
|
18044
|
-
this._closers.delete(
|
|
19052
|
+
this._closers.delete(path26);
|
|
18045
19053
|
}
|
|
18046
|
-
_addPathCloser(
|
|
19054
|
+
_addPathCloser(path26, closer) {
|
|
18047
19055
|
if (!closer)
|
|
18048
19056
|
return;
|
|
18049
|
-
let list = this._closers.get(
|
|
19057
|
+
let list = this._closers.get(path26);
|
|
18050
19058
|
if (!list) {
|
|
18051
19059
|
list = [];
|
|
18052
|
-
this._closers.set(
|
|
19060
|
+
this._closers.set(path26, list);
|
|
18053
19061
|
}
|
|
18054
19062
|
list.push(closer);
|
|
18055
19063
|
}
|
|
@@ -18079,11 +19087,11 @@ function watch(paths, options = {}) {
|
|
|
18079
19087
|
var chokidar_default = { watch, FSWatcher };
|
|
18080
19088
|
|
|
18081
19089
|
// src/watcher/file-watcher.ts
|
|
18082
|
-
import * as
|
|
19090
|
+
import * as path24 from "path";
|
|
18083
19091
|
|
|
18084
19092
|
// src/watcher/native-recursive-watcher.ts
|
|
18085
19093
|
import { watch as watch2 } from "fs";
|
|
18086
|
-
import * as
|
|
19094
|
+
import * as path22 from "path";
|
|
18087
19095
|
var NativeRecursiveWatcher = class {
|
|
18088
19096
|
constructor(root, onChange, options = {}) {
|
|
18089
19097
|
this.root = root;
|
|
@@ -18131,9 +19139,9 @@ var NativeRecursiveWatcher = class {
|
|
|
18131
19139
|
toAbsolutePath(filename) {
|
|
18132
19140
|
if (filename == null) return null;
|
|
18133
19141
|
const normalizedFilename = typeof filename === "string" ? filename : filename.toString();
|
|
18134
|
-
const absolutePath =
|
|
18135
|
-
const relativePath =
|
|
18136
|
-
const outsideRoot = relativePath === ".." || relativePath.startsWith(`..${
|
|
19142
|
+
const absolutePath = path22.resolve(this.root, normalizedFilename);
|
|
19143
|
+
const relativePath = path22.relative(this.root, absolutePath);
|
|
19144
|
+
const outsideRoot = relativePath === ".." || relativePath.startsWith(`..${path22.sep}`) || path22.isAbsolute(relativePath);
|
|
18137
19145
|
return outsideRoot ? null : absolutePath;
|
|
18138
19146
|
}
|
|
18139
19147
|
defaultWatchFactory = (root, listener, options) => watch2(root, options, listener);
|
|
@@ -18141,16 +19149,16 @@ var NativeRecursiveWatcher = class {
|
|
|
18141
19149
|
|
|
18142
19150
|
// src/watcher/snapshot.ts
|
|
18143
19151
|
import * as fsPromises4 from "fs/promises";
|
|
18144
|
-
import * as
|
|
19152
|
+
import * as path23 from "path";
|
|
18145
19153
|
async function buildFileSnapshotScan(projectRoot3, config, configPaths = []) {
|
|
18146
|
-
const normalizedProjectRoot =
|
|
19154
|
+
const normalizedProjectRoot = path23.resolve(projectRoot3);
|
|
18147
19155
|
const ignoreFilter = createIgnoreFilter(normalizedProjectRoot);
|
|
18148
19156
|
const includePatterns = [...config.include, ...config.additionalInclude ?? []];
|
|
18149
19157
|
const maxDepth = config.indexing?.maxDepth ?? -1;
|
|
18150
19158
|
const snapshot = /* @__PURE__ */ new Map();
|
|
18151
19159
|
const unreadablePrefixes = /* @__PURE__ */ new Set();
|
|
18152
19160
|
const includeFile = async (filePath) => {
|
|
18153
|
-
const normalizedPath2 =
|
|
19161
|
+
const normalizedPath2 = path23.resolve(filePath);
|
|
18154
19162
|
if (!shouldIncludeFile(normalizedPath2, normalizedProjectRoot, includePatterns, config.exclude, ignoreFilter)) return;
|
|
18155
19163
|
const stat5 = await readStatIfFile(normalizedPath2, unreadablePrefixes);
|
|
18156
19164
|
if (stat5) snapshot.set(normalizedPath2, { size: stat5.size, mtimeMs: stat5.mtimeMs });
|
|
@@ -18162,16 +19170,16 @@ async function buildFileSnapshotScan(projectRoot3, config, configPaths = []) {
|
|
|
18162
19170
|
} catch (error) {
|
|
18163
19171
|
if (isMissingFsError(error)) return;
|
|
18164
19172
|
if (isPermissionFsError(error)) {
|
|
18165
|
-
unreadablePrefixes.add(
|
|
19173
|
+
unreadablePrefixes.add(path23.resolve(directoryPath));
|
|
18166
19174
|
return;
|
|
18167
19175
|
}
|
|
18168
19176
|
throw error;
|
|
18169
19177
|
}
|
|
18170
19178
|
for (const entry of entries) {
|
|
18171
|
-
const fullPath =
|
|
18172
|
-
const relativePath =
|
|
19179
|
+
const fullPath = path23.join(directoryPath, entry.name);
|
|
19180
|
+
const relativePath = path23.relative(normalizedProjectRoot, fullPath);
|
|
18173
19181
|
if (entry.isDirectory()) {
|
|
18174
|
-
if (hasFilteredPathSegment(relativePath,
|
|
19182
|
+
if (hasFilteredPathSegment(relativePath, path23.sep) || isRestrictedDirectory(relativePath, path23.sep)) continue;
|
|
18175
19183
|
if (ignoreFilter.ignores(relativePath)) continue;
|
|
18176
19184
|
if (maxDepth === -1 || depth < maxDepth) await walk(fullPath, depth + 1);
|
|
18177
19185
|
} else if (entry.isFile()) {
|
|
@@ -18184,19 +19192,19 @@ async function buildFileSnapshotScan(projectRoot3, config, configPaths = []) {
|
|
|
18184
19192
|
return { entries: snapshot, unreadablePrefixes };
|
|
18185
19193
|
}
|
|
18186
19194
|
async function buildFileSnapshotForPathScan(projectRoot3, config, configPaths, targetPath) {
|
|
18187
|
-
const normalizedProjectRoot =
|
|
18188
|
-
const normalizedTargetPath =
|
|
19195
|
+
const normalizedProjectRoot = path23.resolve(projectRoot3);
|
|
19196
|
+
const normalizedTargetPath = path23.resolve(targetPath);
|
|
18189
19197
|
if (!isWithinPath(normalizedProjectRoot, normalizedTargetPath)) {
|
|
18190
19198
|
return { entries: /* @__PURE__ */ new Map(), unreadablePrefixes: /* @__PURE__ */ new Set() };
|
|
18191
19199
|
}
|
|
18192
19200
|
const ignoreFilter = createIgnoreFilter(normalizedProjectRoot);
|
|
18193
19201
|
const includePatterns = [...config.include, ...config.additionalInclude ?? []];
|
|
18194
19202
|
const maxDepth = config.indexing?.maxDepth ?? -1;
|
|
18195
|
-
const explicitConfigPaths = new Set(configPaths.map((configPath) =>
|
|
19203
|
+
const explicitConfigPaths = new Set(configPaths.map((configPath) => path23.resolve(configPath)));
|
|
18196
19204
|
const snapshot = /* @__PURE__ */ new Map();
|
|
18197
19205
|
const unreadablePrefixes = /* @__PURE__ */ new Set();
|
|
18198
19206
|
const includeFile = async (filePath) => {
|
|
18199
|
-
const normalizedPath2 =
|
|
19207
|
+
const normalizedPath2 = path23.resolve(filePath);
|
|
18200
19208
|
if (!explicitConfigPaths.has(normalizedPath2) && !shouldIncludeFile(
|
|
18201
19209
|
normalizedPath2,
|
|
18202
19210
|
normalizedProjectRoot,
|
|
@@ -18214,16 +19222,16 @@ async function buildFileSnapshotForPathScan(projectRoot3, config, configPaths, t
|
|
|
18214
19222
|
} catch (error) {
|
|
18215
19223
|
if (isMissingFsError(error)) return;
|
|
18216
19224
|
if (isPermissionFsError(error)) {
|
|
18217
|
-
unreadablePrefixes.add(
|
|
19225
|
+
unreadablePrefixes.add(path23.resolve(directoryPath));
|
|
18218
19226
|
return;
|
|
18219
19227
|
}
|
|
18220
19228
|
throw error;
|
|
18221
19229
|
}
|
|
18222
19230
|
for (const entry of entries) {
|
|
18223
|
-
const fullPath =
|
|
18224
|
-
const relativePath =
|
|
19231
|
+
const fullPath = path23.join(directoryPath, entry.name);
|
|
19232
|
+
const relativePath = path23.relative(normalizedProjectRoot, fullPath);
|
|
18225
19233
|
if (entry.isDirectory()) {
|
|
18226
|
-
if (hasFilteredPathSegment(relativePath,
|
|
19234
|
+
if (hasFilteredPathSegment(relativePath, path23.sep) || isRestrictedDirectory(relativePath, path23.sep)) continue;
|
|
18227
19235
|
if (ignoreFilter.ignores(relativePath)) continue;
|
|
18228
19236
|
if (maxDepth === -1 || depth < maxDepth) await walk(fullPath, depth + 1);
|
|
18229
19237
|
} else if (entry.isFile()) {
|
|
@@ -18247,7 +19255,7 @@ function completeFileSnapshot(previous, scan) {
|
|
|
18247
19255
|
return completed;
|
|
18248
19256
|
}
|
|
18249
19257
|
async function includeExplicitConfigPaths(snapshot, unreadablePrefixes, configPaths) {
|
|
18250
|
-
for (const configPath of [...new Set(configPaths.map((value) =>
|
|
19258
|
+
for (const configPath of [...new Set(configPaths.map((value) => path23.resolve(value)))]) {
|
|
18251
19259
|
if (snapshot.has(configPath)) continue;
|
|
18252
19260
|
const stat5 = await readStatIfFile(configPath, unreadablePrefixes);
|
|
18253
19261
|
if (stat5) snapshot.set(configPath, { size: stat5.size, mtimeMs: stat5.mtimeMs });
|
|
@@ -18257,12 +19265,12 @@ async function includeExplicitConfigPathsInPath(snapshot, unreadablePrefixes, co
|
|
|
18257
19265
|
await includeExplicitConfigPaths(
|
|
18258
19266
|
snapshot,
|
|
18259
19267
|
unreadablePrefixes,
|
|
18260
|
-
configPaths.filter((configPath) => isWithinPath(targetPath,
|
|
19268
|
+
configPaths.filter((configPath) => isWithinPath(targetPath, path23.resolve(configPath)))
|
|
18261
19269
|
);
|
|
18262
19270
|
}
|
|
18263
19271
|
function isWithinPath(parentPath, childPath) {
|
|
18264
|
-
const relativePath =
|
|
18265
|
-
return relativePath === "" || !relativePath.startsWith(`..${
|
|
19272
|
+
const relativePath = path23.relative(parentPath, childPath);
|
|
19273
|
+
return relativePath === "" || !relativePath.startsWith(`..${path23.sep}`) && relativePath !== ".." && !path23.isAbsolute(relativePath);
|
|
18266
19274
|
}
|
|
18267
19275
|
async function readStatIfFile(filePath, unreadablePrefixes) {
|
|
18268
19276
|
try {
|
|
@@ -18271,7 +19279,7 @@ async function readStatIfFile(filePath, unreadablePrefixes) {
|
|
|
18271
19279
|
} catch (error) {
|
|
18272
19280
|
if (isMissingFsError(error)) return null;
|
|
18273
19281
|
if (isPermissionFsError(error)) {
|
|
18274
|
-
unreadablePrefixes.add(
|
|
19282
|
+
unreadablePrefixes.add(path23.resolve(filePath));
|
|
18275
19283
|
return null;
|
|
18276
19284
|
}
|
|
18277
19285
|
throw error;
|
|
@@ -18408,8 +19416,8 @@ var FileWatcher = class {
|
|
|
18408
19416
|
this.createWatcher();
|
|
18409
19417
|
}
|
|
18410
19418
|
resetReady() {
|
|
18411
|
-
this.readyPromise = new Promise((
|
|
18412
|
-
this.resolveReady =
|
|
19419
|
+
this.readyPromise = new Promise((resolve18) => {
|
|
19420
|
+
this.resolveReady = resolve18;
|
|
18413
19421
|
});
|
|
18414
19422
|
this.startupReadySignals = 1;
|
|
18415
19423
|
}
|
|
@@ -18440,7 +19448,7 @@ var FileWatcher = class {
|
|
|
18440
19448
|
const resolvedWatchTargets = watchTargets ?? this.getFullChokidarWatchTargets();
|
|
18441
19449
|
const watcherOptions = {
|
|
18442
19450
|
ignored: (filePath) => {
|
|
18443
|
-
const relativePath =
|
|
19451
|
+
const relativePath = path24.relative(this.projectRoot, filePath);
|
|
18444
19452
|
if (!relativePath) return false;
|
|
18445
19453
|
if (this.isProjectConfigPathOrAncestor(relativePath)) {
|
|
18446
19454
|
return false;
|
|
@@ -18448,10 +19456,10 @@ var FileWatcher = class {
|
|
|
18448
19456
|
if (this.isOutsideProjectPath(relativePath)) {
|
|
18449
19457
|
return true;
|
|
18450
19458
|
}
|
|
18451
|
-
if (hasFilteredPathSegment(relativePath,
|
|
19459
|
+
if (hasFilteredPathSegment(relativePath, path24.sep)) {
|
|
18452
19460
|
return true;
|
|
18453
19461
|
}
|
|
18454
|
-
if (isRestrictedDirectory(relativePath,
|
|
19462
|
+
if (isRestrictedDirectory(relativePath, path24.sep)) {
|
|
18455
19463
|
return true;
|
|
18456
19464
|
}
|
|
18457
19465
|
if (ignoreFilter.ignores(relativePath)) {
|
|
@@ -18542,13 +19550,13 @@ var FileWatcher = class {
|
|
|
18542
19550
|
getExternalConfigWatchTargets() {
|
|
18543
19551
|
return [...new Set(
|
|
18544
19552
|
this.projectConfigPaths.filter((projectConfigPath) => {
|
|
18545
|
-
const relativeConfigPath =
|
|
19553
|
+
const relativeConfigPath = path24.relative(this.projectRoot, projectConfigPath);
|
|
18546
19554
|
return this.isOutsideProjectPath(relativeConfigPath);
|
|
18547
19555
|
}).map((projectConfigPath) => {
|
|
18548
|
-
if (
|
|
19556
|
+
if (existsSync14(projectConfigPath)) {
|
|
18549
19557
|
return projectConfigPath;
|
|
18550
19558
|
}
|
|
18551
|
-
return this.getNearestExistingDirectory(
|
|
19559
|
+
return this.getNearestExistingDirectory(path24.dirname(projectConfigPath));
|
|
18552
19560
|
})
|
|
18553
19561
|
)];
|
|
18554
19562
|
}
|
|
@@ -18610,7 +19618,7 @@ var FileWatcher = class {
|
|
|
18610
19618
|
}
|
|
18611
19619
|
scheduleNativeReconciliation(generation, filePath) {
|
|
18612
19620
|
if (!this.isCurrentNativeSetup(generation)) return;
|
|
18613
|
-
const requiresFullReconciliation = filePath ===
|
|
19621
|
+
const requiresFullReconciliation = filePath === path24.join(this.projectRoot, ".gitignore");
|
|
18614
19622
|
const invalidatedPath = requiresFullReconciliation ? null : filePath;
|
|
18615
19623
|
this.nativeInvalidatedPaths.set(invalidatedPath, invalidatedPath !== null);
|
|
18616
19624
|
if (this.nativeReconcileTimer) {
|
|
@@ -18705,23 +19713,23 @@ var FileWatcher = class {
|
|
|
18705
19713
|
this.scheduleFlush();
|
|
18706
19714
|
}
|
|
18707
19715
|
isProjectConfigPath(filePath) {
|
|
18708
|
-
const relativePath =
|
|
18709
|
-
const normalizedRelativePath =
|
|
19716
|
+
const relativePath = path24.relative(this.projectRoot, filePath);
|
|
19717
|
+
const normalizedRelativePath = path24.normalize(relativePath);
|
|
18710
19718
|
return this.getProjectConfigRelativePaths().some((configPath) => configPath === normalizedRelativePath);
|
|
18711
19719
|
}
|
|
18712
19720
|
isProjectConfigPathOrAncestor(relativePath) {
|
|
18713
|
-
const normalizedRelativePath =
|
|
19721
|
+
const normalizedRelativePath = path24.normalize(relativePath);
|
|
18714
19722
|
return this.getProjectConfigRelativePaths().some(
|
|
18715
|
-
(configPath) => configPath === normalizedRelativePath || configPath.startsWith(`${normalizedRelativePath}${
|
|
19723
|
+
(configPath) => configPath === normalizedRelativePath || configPath.startsWith(`${normalizedRelativePath}${path24.sep}`)
|
|
18716
19724
|
);
|
|
18717
19725
|
}
|
|
18718
19726
|
isOutsideProjectPath(relativePath) {
|
|
18719
|
-
return relativePath === ".." || relativePath.startsWith(`..${
|
|
19727
|
+
return relativePath === ".." || relativePath.startsWith(`..${path24.sep}`) || path24.isAbsolute(relativePath);
|
|
18720
19728
|
}
|
|
18721
19729
|
getNearestExistingDirectory(directoryPath) {
|
|
18722
19730
|
let candidate = directoryPath;
|
|
18723
|
-
while (!
|
|
18724
|
-
const parent =
|
|
19731
|
+
while (!existsSync14(candidate)) {
|
|
19732
|
+
const parent = path24.dirname(candidate);
|
|
18725
19733
|
if (parent === candidate) break;
|
|
18726
19734
|
candidate = parent;
|
|
18727
19735
|
}
|
|
@@ -18729,7 +19737,7 @@ var FileWatcher = class {
|
|
|
18729
19737
|
}
|
|
18730
19738
|
getProjectConfigRelativePaths() {
|
|
18731
19739
|
return this.projectConfigPaths.map(
|
|
18732
|
-
(configPath) =>
|
|
19740
|
+
(configPath) => path24.normalize(path24.relative(this.projectRoot, configPath))
|
|
18733
19741
|
);
|
|
18734
19742
|
}
|
|
18735
19743
|
getConfigPathStates() {
|
|
@@ -18787,7 +19795,7 @@ var FileWatcher = class {
|
|
|
18787
19795
|
return;
|
|
18788
19796
|
}
|
|
18789
19797
|
const changes = Array.from(this.pendingChanges.entries()).map(
|
|
18790
|
-
([
|
|
19798
|
+
([path26, type]) => ({ path: path26, type })
|
|
18791
19799
|
);
|
|
18792
19800
|
this.pendingChanges.clear();
|
|
18793
19801
|
try {
|
|
@@ -18833,7 +19841,7 @@ var FileWatcher = class {
|
|
|
18833
19841
|
};
|
|
18834
19842
|
|
|
18835
19843
|
// src/watcher/git-head-watcher.ts
|
|
18836
|
-
import * as
|
|
19844
|
+
import * as path25 from "path";
|
|
18837
19845
|
var GitHeadWatcher = class {
|
|
18838
19846
|
watcher = null;
|
|
18839
19847
|
projectRoot;
|
|
@@ -18855,13 +19863,13 @@ var GitHeadWatcher = class {
|
|
|
18855
19863
|
this.readyPromise = Promise.resolve();
|
|
18856
19864
|
return;
|
|
18857
19865
|
}
|
|
18858
|
-
this.readyPromise = new Promise((
|
|
18859
|
-
this.resolveReady =
|
|
19866
|
+
this.readyPromise = new Promise((resolve18) => {
|
|
19867
|
+
this.resolveReady = resolve18;
|
|
18860
19868
|
});
|
|
18861
19869
|
this.onBranchChange = handler;
|
|
18862
19870
|
this.currentBranch = getCurrentBranch(this.projectRoot);
|
|
18863
19871
|
const headPath = getHeadPath(this.projectRoot);
|
|
18864
|
-
const refsPath =
|
|
19872
|
+
const refsPath = path25.join(this.projectRoot, ".git", "refs", "heads");
|
|
18865
19873
|
this.watcher = chokidar_default.watch([headPath, refsPath], {
|
|
18866
19874
|
persistent: true,
|
|
18867
19875
|
ignoreInitial: true,
|
|
@@ -18929,7 +19937,9 @@ var GitHeadWatcher = class {
|
|
|
18929
19937
|
function createWatcherWithIndexer(getIndexer, projectRoot3, config, host, options = {}) {
|
|
18930
19938
|
const fileWatcher = new FileWatcher(projectRoot3, config, host, options);
|
|
18931
19939
|
const configPaths = getConfigPaths(projectRoot3, host, options);
|
|
18932
|
-
configureAutoIndex(projectRoot3, host, parseConfig(config), getIndexer
|
|
19940
|
+
configureAutoIndex(projectRoot3, host, parseConfig(config), getIndexer, {
|
|
19941
|
+
synchronizeBackgroundWorker: false
|
|
19942
|
+
});
|
|
18933
19943
|
let stopped = false;
|
|
18934
19944
|
const requestReindex = () => {
|
|
18935
19945
|
if (stopped) return;
|
|
@@ -18949,7 +19959,9 @@ function createWatcherWithIndexer(getIndexer, projectRoot3, config, host, option
|
|
|
18949
19959
|
const parsedConfig = options.configPath ? parseConfig(loadConfigFile(options.configPath)) : void 0;
|
|
18950
19960
|
const refreshedConfig = refreshIndexerForDirectory(projectRoot3, host, parsedConfig);
|
|
18951
19961
|
if (refreshedConfig) {
|
|
18952
|
-
configureAutoIndex(projectRoot3, host, refreshedConfig, getIndexer
|
|
19962
|
+
configureAutoIndex(projectRoot3, host, refreshedConfig, getIndexer, {
|
|
19963
|
+
synchronizeBackgroundWorker: false
|
|
19964
|
+
});
|
|
18953
19965
|
}
|
|
18954
19966
|
}
|
|
18955
19967
|
requestReindex();
|
|
@@ -18997,7 +20009,6 @@ function getConfigPaths(projectRoot3, host, options) {
|
|
|
18997
20009
|
|
|
18998
20010
|
// src/adapters/pi/extension.ts
|
|
18999
20011
|
var HOST2 = "pi";
|
|
19000
|
-
var activeWatchers = /* @__PURE__ */ new Map();
|
|
19001
20012
|
var ChunkType = Type2.Union([
|
|
19002
20013
|
Type2.Literal("function"),
|
|
19003
20014
|
Type2.Literal("class"),
|
|
@@ -19016,24 +20027,30 @@ function projectRoot2(ctx) {
|
|
|
19016
20027
|
function isValidProject(projectRoot3, requireProjectMarker) {
|
|
19017
20028
|
return !isHomeDirectory(projectRoot3) && (!requireProjectMarker || hasProjectMarker(projectRoot3));
|
|
19018
20029
|
}
|
|
19019
|
-
function ensureWatcher(projectRoot3) {
|
|
19020
|
-
if (activeWatchers.has(projectRoot3)) return;
|
|
20030
|
+
async function ensureWatcher(projectRoot3) {
|
|
19021
20031
|
const config = parseConfig(loadMergedConfig(projectRoot3, HOST2));
|
|
19022
|
-
if (!
|
|
20032
|
+
if (!isValidProject(projectRoot3, config.indexing.requireProjectMarker)) {
|
|
20033
|
+
await stopBackgroundWorker(projectRoot3, HOST2).catch((error) => {
|
|
20034
|
+
console.error("[codebase-index] Failed to stop Pi background worker:", error);
|
|
20035
|
+
});
|
|
19023
20036
|
return;
|
|
19024
20037
|
}
|
|
19025
|
-
|
|
20038
|
+
getIndexerForProject(projectRoot3, HOST2);
|
|
20039
|
+
const watcherFactoryForConfig = (refreshedConfig) => refreshedConfig.indexing.watchFiles ? () => createWatcherWithIndexer(
|
|
19026
20040
|
() => getIndexerForProject(projectRoot3, HOST2),
|
|
19027
20041
|
projectRoot3,
|
|
19028
|
-
|
|
20042
|
+
refreshedConfig,
|
|
19029
20043
|
HOST2
|
|
19030
|
-
)
|
|
19031
|
-
|
|
19032
|
-
|
|
19033
|
-
|
|
19034
|
-
|
|
19035
|
-
|
|
19036
|
-
|
|
20044
|
+
) : null;
|
|
20045
|
+
configureBackgroundWorker(projectRoot3, HOST2, config, {
|
|
20046
|
+
startAutoIndex: (source, allowDisabledAutoIndex) => {
|
|
20047
|
+
startAutoIndexForBackgroundWorker(projectRoot3, HOST2, source, allowDisabledAutoIndex);
|
|
20048
|
+
},
|
|
20049
|
+
stopAutoIndex: () => stopAutoIndexForBackgroundWorker(projectRoot3, HOST2),
|
|
20050
|
+
watcherFactory: watcherFactoryForConfig(config),
|
|
20051
|
+
watcherFactoryForConfig
|
|
20052
|
+
});
|
|
20053
|
+
await waitForBackgroundWorkerStart(projectRoot3, HOST2);
|
|
19037
20054
|
}
|
|
19038
20055
|
function codebaseIndexPiExtension(pi) {
|
|
19039
20056
|
pi.registerTool({
|
|
@@ -19266,7 +20283,7 @@ function codebaseIndexPiExtension(pi) {
|
|
|
19266
20283
|
});
|
|
19267
20284
|
registerPiCallGraphTools(pi);
|
|
19268
20285
|
pi.on("before_agent_start", async (event, ctx) => {
|
|
19269
|
-
ensureWatcher(projectRoot2(ctx));
|
|
20286
|
+
await ensureWatcher(projectRoot2(ctx));
|
|
19270
20287
|
return {
|
|
19271
20288
|
systemPrompt: `${event.systemPrompt}
|
|
19272
20289
|
|
|
@@ -19275,7 +20292,7 @@ Check index_status first when index readiness is unknown. Use codebase_context o
|
|
|
19275
20292
|
});
|
|
19276
20293
|
pi.on("session_shutdown", async (_event, ctx) => {
|
|
19277
20294
|
const root = projectRoot2(ctx);
|
|
19278
|
-
await
|
|
20295
|
+
await stopBackgroundWorker(root, HOST2);
|
|
19279
20296
|
});
|
|
19280
20297
|
pi.registerTool({
|
|
19281
20298
|
name: TOOL_NAME.PR_IMPACT,
|