open-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/cbi.cjs
CHANGED
|
@@ -334,7 +334,7 @@ var require_ignore = __commonJS({
|
|
|
334
334
|
// path matching.
|
|
335
335
|
// - check `string` either `MODE_IGNORE` or `MODE_CHECK_IGNORE`
|
|
336
336
|
// @returns {TestResult} true if a file is ignored
|
|
337
|
-
test(
|
|
337
|
+
test(path35, checkUnignored, mode) {
|
|
338
338
|
let ignored = false;
|
|
339
339
|
let unignored = false;
|
|
340
340
|
let matchedRule;
|
|
@@ -343,7 +343,7 @@ var require_ignore = __commonJS({
|
|
|
343
343
|
if (unignored === negative && ignored !== unignored || negative && !ignored && !unignored && !checkUnignored) {
|
|
344
344
|
return;
|
|
345
345
|
}
|
|
346
|
-
const matched = rule[mode].test(
|
|
346
|
+
const matched = rule[mode].test(path35);
|
|
347
347
|
if (!matched) {
|
|
348
348
|
return;
|
|
349
349
|
}
|
|
@@ -364,17 +364,17 @@ var require_ignore = __commonJS({
|
|
|
364
364
|
var throwError = (message, Ctor) => {
|
|
365
365
|
throw new Ctor(message);
|
|
366
366
|
};
|
|
367
|
-
var checkPath = (
|
|
368
|
-
if (!isString(
|
|
367
|
+
var checkPath = (path35, originalPath, doThrow) => {
|
|
368
|
+
if (!isString(path35)) {
|
|
369
369
|
return doThrow(
|
|
370
370
|
`path must be a string, but got \`${originalPath}\``,
|
|
371
371
|
TypeError
|
|
372
372
|
);
|
|
373
373
|
}
|
|
374
|
-
if (!
|
|
374
|
+
if (!path35) {
|
|
375
375
|
return doThrow(`path must not be empty`, TypeError);
|
|
376
376
|
}
|
|
377
|
-
if (checkPath.isNotRelative(
|
|
377
|
+
if (checkPath.isNotRelative(path35)) {
|
|
378
378
|
const r = "`path.relative()`d";
|
|
379
379
|
return doThrow(
|
|
380
380
|
`path should be a ${r} string, but got "${originalPath}"`,
|
|
@@ -383,7 +383,7 @@ var require_ignore = __commonJS({
|
|
|
383
383
|
}
|
|
384
384
|
return true;
|
|
385
385
|
};
|
|
386
|
-
var isNotRelative = (
|
|
386
|
+
var isNotRelative = (path35) => REGEX_TEST_INVALID_PATH.test(path35);
|
|
387
387
|
checkPath.isNotRelative = isNotRelative;
|
|
388
388
|
checkPath.convert = (p) => p;
|
|
389
389
|
var Ignore2 = class {
|
|
@@ -413,19 +413,19 @@ var require_ignore = __commonJS({
|
|
|
413
413
|
}
|
|
414
414
|
// @returns {TestResult}
|
|
415
415
|
_test(originalPath, cache, checkUnignored, slices) {
|
|
416
|
-
const
|
|
416
|
+
const path35 = originalPath && checkPath.convert(originalPath);
|
|
417
417
|
checkPath(
|
|
418
|
-
|
|
418
|
+
path35,
|
|
419
419
|
originalPath,
|
|
420
420
|
this._strictPathCheck ? throwError : RETURN_FALSE
|
|
421
421
|
);
|
|
422
|
-
return this._t(
|
|
422
|
+
return this._t(path35, cache, checkUnignored, slices);
|
|
423
423
|
}
|
|
424
|
-
checkIgnore(
|
|
425
|
-
if (!REGEX_TEST_TRAILING_SLASH.test(
|
|
426
|
-
return this.test(
|
|
424
|
+
checkIgnore(path35) {
|
|
425
|
+
if (!REGEX_TEST_TRAILING_SLASH.test(path35)) {
|
|
426
|
+
return this.test(path35);
|
|
427
427
|
}
|
|
428
|
-
const slices =
|
|
428
|
+
const slices = path35.split(SLASH).filter(Boolean);
|
|
429
429
|
slices.pop();
|
|
430
430
|
if (slices.length) {
|
|
431
431
|
const parent = this._t(
|
|
@@ -438,18 +438,18 @@ var require_ignore = __commonJS({
|
|
|
438
438
|
return parent;
|
|
439
439
|
}
|
|
440
440
|
}
|
|
441
|
-
return this._rules.test(
|
|
441
|
+
return this._rules.test(path35, false, MODE_CHECK_IGNORE);
|
|
442
442
|
}
|
|
443
|
-
_t(
|
|
444
|
-
if (
|
|
445
|
-
return cache[
|
|
443
|
+
_t(path35, cache, checkUnignored, slices) {
|
|
444
|
+
if (path35 in cache) {
|
|
445
|
+
return cache[path35];
|
|
446
446
|
}
|
|
447
447
|
if (!slices) {
|
|
448
|
-
slices =
|
|
448
|
+
slices = path35.split(SLASH).filter(Boolean);
|
|
449
449
|
}
|
|
450
450
|
slices.pop();
|
|
451
451
|
if (!slices.length) {
|
|
452
|
-
return cache[
|
|
452
|
+
return cache[path35] = this._rules.test(path35, checkUnignored, MODE_IGNORE);
|
|
453
453
|
}
|
|
454
454
|
const parent = this._t(
|
|
455
455
|
slices.join(SLASH) + SLASH,
|
|
@@ -457,29 +457,29 @@ var require_ignore = __commonJS({
|
|
|
457
457
|
checkUnignored,
|
|
458
458
|
slices
|
|
459
459
|
);
|
|
460
|
-
return cache[
|
|
460
|
+
return cache[path35] = parent.ignored ? parent : this._rules.test(path35, checkUnignored, MODE_IGNORE);
|
|
461
461
|
}
|
|
462
|
-
ignores(
|
|
463
|
-
return this._test(
|
|
462
|
+
ignores(path35) {
|
|
463
|
+
return this._test(path35, this._ignoreCache, false).ignored;
|
|
464
464
|
}
|
|
465
465
|
createFilter() {
|
|
466
|
-
return (
|
|
466
|
+
return (path35) => !this.ignores(path35);
|
|
467
467
|
}
|
|
468
468
|
filter(paths) {
|
|
469
469
|
return makeArray(paths).filter(this.createFilter());
|
|
470
470
|
}
|
|
471
471
|
// @returns {TestResult}
|
|
472
|
-
test(
|
|
473
|
-
return this._test(
|
|
472
|
+
test(path35) {
|
|
473
|
+
return this._test(path35, this._testCache, true);
|
|
474
474
|
}
|
|
475
475
|
};
|
|
476
476
|
var factory = (options) => new Ignore2(options);
|
|
477
|
-
var isPathValid = (
|
|
477
|
+
var isPathValid = (path35) => checkPath(path35 && checkPath.convert(path35), path35, RETURN_FALSE);
|
|
478
478
|
var setupWindows = () => {
|
|
479
479
|
const makePosix = (str) => /^\\\\\?\\/.test(str) || /["<>|\u0000-\u001F]+/u.test(str) ? str : str.replace(/\\/g, "/");
|
|
480
480
|
checkPath.convert = makePosix;
|
|
481
481
|
const REGEX_TEST_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i;
|
|
482
|
-
checkPath.isNotRelative = (
|
|
482
|
+
checkPath.isNotRelative = (path35) => REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path35) || isNotRelative(path35);
|
|
483
483
|
};
|
|
484
484
|
if (
|
|
485
485
|
// Detect `process` so that it can run in browsers.
|
|
@@ -665,8 +665,8 @@ __export(cbi_exports, {
|
|
|
665
665
|
module.exports = __toCommonJS(cbi_exports);
|
|
666
666
|
|
|
667
667
|
// src/adapters/cbi.ts
|
|
668
|
-
var
|
|
669
|
-
var
|
|
668
|
+
var import_node_fs3 = require("fs");
|
|
669
|
+
var path34 = __toESM(require("path"), 1);
|
|
670
670
|
var import_node_url2 = require("url");
|
|
671
671
|
|
|
672
672
|
// src/config/host.ts
|
|
@@ -1734,7 +1734,7 @@ var autoDetectProviders = AUTO_DETECT_PROVIDER_ORDER.filter(
|
|
|
1734
1734
|
|
|
1735
1735
|
// src/tools/operations.ts
|
|
1736
1736
|
var import_fs13 = require("fs");
|
|
1737
|
-
var
|
|
1737
|
+
var path21 = __toESM(require("path"), 1);
|
|
1738
1738
|
|
|
1739
1739
|
// src/tools/knowledge-base-paths.ts
|
|
1740
1740
|
var path8 = __toESM(require("path"), 1);
|
|
@@ -2535,8 +2535,8 @@ ${truncateContent(r.content)}
|
|
|
2535
2535
|
|
|
2536
2536
|
// src/utils/auto-index.ts
|
|
2537
2537
|
var import_fs7 = require("fs");
|
|
2538
|
-
var
|
|
2539
|
-
var
|
|
2538
|
+
var os4 = __toESM(require("os"), 1);
|
|
2539
|
+
var path12 = __toESM(require("path"), 1);
|
|
2540
2540
|
|
|
2541
2541
|
// src/indexer/index-lock.ts
|
|
2542
2542
|
var import_crypto = require("crypto");
|
|
@@ -2783,7 +2783,7 @@ function removeDeadReclaimMarker(lockPath, expectedOwner) {
|
|
|
2783
2783
|
return true;
|
|
2784
2784
|
}
|
|
2785
2785
|
function reclaimDeadOwner(indexPath, lockPath, expectedOwner) {
|
|
2786
|
-
const
|
|
2786
|
+
const reclaimPath2 = path9.join(lockPath, RECLAIM_DIRECTORY_NAME);
|
|
2787
2787
|
const reclaimOwner = {
|
|
2788
2788
|
pid: process.pid,
|
|
2789
2789
|
hostname: os2.hostname(),
|
|
@@ -2792,19 +2792,19 @@ function reclaimDeadOwner(indexPath, lockPath, expectedOwner) {
|
|
|
2792
2792
|
expectedOwnerToken: expectedOwner.token
|
|
2793
2793
|
};
|
|
2794
2794
|
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
2795
|
-
if (publishJsonDirectory(
|
|
2795
|
+
if (publishJsonDirectory(reclaimPath2, reclaimOwner)) break;
|
|
2796
2796
|
if (attempt === 0 && removeDeadReclaimMarker(lockPath, expectedOwner)) continue;
|
|
2797
2797
|
return false;
|
|
2798
2798
|
}
|
|
2799
2799
|
try {
|
|
2800
|
-
const currentReclaimer = readReclaimOwner(
|
|
2800
|
+
const currentReclaimer = readReclaimOwner(reclaimPath2);
|
|
2801
2801
|
const currentOwner = readDirectoryOwner(lockPath);
|
|
2802
2802
|
if (!currentReclaimer || !sameReclaimOwner(currentReclaimer, reclaimOwner) || !currentOwner || !sameOwner(currentOwner, expectedOwner) || getOwnerLiveness(currentOwner) !== "dead") {
|
|
2803
2803
|
return false;
|
|
2804
2804
|
}
|
|
2805
2805
|
publishRecoveryMarker(indexPath, expectedOwner);
|
|
2806
2806
|
const ownerBeforeQuarantine = readDirectoryOwner(lockPath);
|
|
2807
|
-
const reclaimerBeforeQuarantine = readReclaimOwner(
|
|
2807
|
+
const reclaimerBeforeQuarantine = readReclaimOwner(reclaimPath2);
|
|
2808
2808
|
if (!ownerBeforeQuarantine || !sameOwner(ownerBeforeQuarantine, expectedOwner) || getOwnerLiveness(ownerBeforeQuarantine) !== "dead" || !reclaimerBeforeQuarantine || !sameReclaimOwner(reclaimerBeforeQuarantine, reclaimOwner)) {
|
|
2809
2809
|
return false;
|
|
2810
2810
|
}
|
|
@@ -2974,10 +2974,880 @@ function completeLeaseRecovery(lease) {
|
|
|
2974
2974
|
}
|
|
2975
2975
|
}
|
|
2976
2976
|
|
|
2977
|
+
// src/utils/background-worker.ts
|
|
2978
|
+
var import_node_crypto = require("crypto");
|
|
2979
|
+
var import_node_fs = require("fs");
|
|
2980
|
+
var os3 = __toESM(require("os"), 1);
|
|
2981
|
+
var path10 = __toESM(require("path"), 1);
|
|
2982
|
+
var OWNER_FILE_NAME2 = "owner.json";
|
|
2983
|
+
var HEARTBEAT_FILE_PREFIX = "heartbeat.";
|
|
2984
|
+
var RECLAIM_DIRECTORY_NAME2 = "reclaim";
|
|
2985
|
+
var REFRESH_REQUEST_FILE_NAME = "refresh-request.json";
|
|
2986
|
+
var HEARTBEAT_INTERVAL_MS = 5e3;
|
|
2987
|
+
var STALE_LEASE_MS = 3e4;
|
|
2988
|
+
var RETRY_DELAY_MS = 5e3;
|
|
2989
|
+
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;
|
|
2990
|
+
var BackgroundWorkerStopError = class extends Error {
|
|
2991
|
+
constructor(watcherError, autoIndexError) {
|
|
2992
|
+
super("Failed to stop background worker");
|
|
2993
|
+
this.watcherError = watcherError;
|
|
2994
|
+
this.autoIndexError = autoIndexError;
|
|
2995
|
+
this.name = "BackgroundWorkerStopError";
|
|
2996
|
+
}
|
|
2997
|
+
watcherError;
|
|
2998
|
+
autoIndexError;
|
|
2999
|
+
};
|
|
3000
|
+
var workers = /* @__PURE__ */ new Map();
|
|
3001
|
+
var workerKeysByProject = /* @__PURE__ */ new Map();
|
|
3002
|
+
var workerReplacementBarriers = /* @__PURE__ */ new Map();
|
|
3003
|
+
function getErrorCode2(error) {
|
|
3004
|
+
return typeof error === "object" && error !== null && "code" in error ? String(error.code) : void 0;
|
|
3005
|
+
}
|
|
3006
|
+
function canonicalizePath(targetPath) {
|
|
3007
|
+
const resolved = path10.resolve(targetPath);
|
|
3008
|
+
if ((0, import_node_fs.existsSync)(resolved)) {
|
|
3009
|
+
try {
|
|
3010
|
+
return import_node_fs.realpathSync.native(resolved);
|
|
3011
|
+
} catch {
|
|
3012
|
+
return resolved;
|
|
3013
|
+
}
|
|
3014
|
+
}
|
|
3015
|
+
const parent = path10.dirname(resolved);
|
|
3016
|
+
if (parent === resolved) return resolved;
|
|
3017
|
+
return path10.join(canonicalizePath(parent), path10.basename(resolved));
|
|
3018
|
+
}
|
|
3019
|
+
function projectLookupKey(projectRoot, host) {
|
|
3020
|
+
return `${host}::${canonicalizePath(projectRoot)}`;
|
|
3021
|
+
}
|
|
3022
|
+
function resolveIdentity(projectRoot, config, host) {
|
|
3023
|
+
const canonicalProjectRoot = canonicalizePath(projectRoot);
|
|
3024
|
+
const canonicalIndexPath = canonicalizePath(resolveProjectIndexPath(projectRoot, config.scope, host));
|
|
3025
|
+
return {
|
|
3026
|
+
canonicalIndexPath,
|
|
3027
|
+
canonicalProjectRoot,
|
|
3028
|
+
key: `${canonicalIndexPath}::${canonicalProjectRoot}`
|
|
3029
|
+
};
|
|
3030
|
+
}
|
|
3031
|
+
function controllerKey(identity, host) {
|
|
3032
|
+
return `${identity.key}::${host}`;
|
|
3033
|
+
}
|
|
3034
|
+
function leaseDirectoryName(identity) {
|
|
3035
|
+
const hash = (0, import_node_crypto.createHash)("sha256").update(identity.key).digest("hex").slice(0, 32);
|
|
3036
|
+
return `background-worker.${hash}.lease`;
|
|
3037
|
+
}
|
|
3038
|
+
function leasePathFor(identity) {
|
|
3039
|
+
return path10.join(identity.canonicalIndexPath, leaseDirectoryName(identity));
|
|
3040
|
+
}
|
|
3041
|
+
function parseOwner2(value) {
|
|
3042
|
+
if (typeof value !== "object" || value === null) return null;
|
|
3043
|
+
const candidate = value;
|
|
3044
|
+
if (candidate.version !== 1) return null;
|
|
3045
|
+
if (!Number.isInteger(candidate.pid) || (candidate.pid ?? 0) <= 0) return null;
|
|
3046
|
+
if (typeof candidate.hostname !== "string" || candidate.hostname.length === 0) return null;
|
|
3047
|
+
if (typeof candidate.startedAt !== "string" || Number.isNaN(Date.parse(candidate.startedAt))) return null;
|
|
3048
|
+
if (typeof candidate.heartbeatAt !== "string" || Number.isNaN(Date.parse(candidate.heartbeatAt))) return null;
|
|
3049
|
+
if (typeof candidate.projectRoot !== "string" || candidate.projectRoot.length === 0) return null;
|
|
3050
|
+
if (typeof candidate.indexPath !== "string" || candidate.indexPath.length === 0) return null;
|
|
3051
|
+
if (typeof candidate.token !== "string" || !UUID_PATTERN2.test(candidate.token)) return null;
|
|
3052
|
+
return candidate;
|
|
3053
|
+
}
|
|
3054
|
+
function parseHeartbeat(value, expectedToken) {
|
|
3055
|
+
if (typeof value !== "object" || value === null) return null;
|
|
3056
|
+
const candidate = value;
|
|
3057
|
+
if (candidate.version !== 1 || candidate.token !== expectedToken) return null;
|
|
3058
|
+
if (typeof candidate.heartbeatAt !== "string" || Number.isNaN(Date.parse(candidate.heartbeatAt))) return null;
|
|
3059
|
+
return candidate;
|
|
3060
|
+
}
|
|
3061
|
+
function parseReclaimOwner2(value) {
|
|
3062
|
+
if (typeof value !== "object" || value === null) return null;
|
|
3063
|
+
const candidate = value;
|
|
3064
|
+
if (candidate.version !== 1) return null;
|
|
3065
|
+
if (!Number.isInteger(candidate.pid) || (candidate.pid ?? 0) <= 0) return null;
|
|
3066
|
+
if (typeof candidate.hostname !== "string" || candidate.hostname.length === 0) return null;
|
|
3067
|
+
if (typeof candidate.startedAt !== "string" || Number.isNaN(Date.parse(candidate.startedAt))) return null;
|
|
3068
|
+
if (typeof candidate.token !== "string" || !UUID_PATTERN2.test(candidate.token)) return null;
|
|
3069
|
+
if (candidate.expectedOwnerToken !== null && (typeof candidate.expectedOwnerToken !== "string" || !UUID_PATTERN2.test(candidate.expectedOwnerToken))) return null;
|
|
3070
|
+
return candidate;
|
|
3071
|
+
}
|
|
3072
|
+
function heartbeatPath(leasePath, token) {
|
|
3073
|
+
return path10.join(leasePath, `${HEARTBEAT_FILE_PREFIX}${token}.json`);
|
|
3074
|
+
}
|
|
3075
|
+
function reclaimPath(leasePath) {
|
|
3076
|
+
return path10.join(leasePath, RECLAIM_DIRECTORY_NAME2);
|
|
3077
|
+
}
|
|
3078
|
+
function refreshRequestPath(leasePath) {
|
|
3079
|
+
return path10.join(leasePath, REFRESH_REQUEST_FILE_NAME);
|
|
3080
|
+
}
|
|
3081
|
+
function readLeaseOwner(leasePath) {
|
|
3082
|
+
try {
|
|
3083
|
+
return parseOwner2(JSON.parse((0, import_node_fs.readFileSync)(path10.join(leasePath, OWNER_FILE_NAME2), "utf-8")));
|
|
3084
|
+
} catch {
|
|
3085
|
+
return null;
|
|
3086
|
+
}
|
|
3087
|
+
}
|
|
3088
|
+
function readOwner(leasePath) {
|
|
3089
|
+
const owner = readLeaseOwner(leasePath);
|
|
3090
|
+
if (!owner) return null;
|
|
3091
|
+
try {
|
|
3092
|
+
const heartbeat = parseHeartbeat(
|
|
3093
|
+
JSON.parse((0, import_node_fs.readFileSync)(heartbeatPath(leasePath, owner.token), "utf-8")),
|
|
3094
|
+
owner.token
|
|
3095
|
+
);
|
|
3096
|
+
return heartbeat ? { ...owner, heartbeatAt: heartbeat.heartbeatAt } : owner;
|
|
3097
|
+
} catch {
|
|
3098
|
+
return owner;
|
|
3099
|
+
}
|
|
3100
|
+
}
|
|
3101
|
+
function readReclaimOwner2(leasePath) {
|
|
3102
|
+
try {
|
|
3103
|
+
return parseReclaimOwner2(JSON.parse((0, import_node_fs.readFileSync)(path10.join(reclaimPath(leasePath), OWNER_FILE_NAME2), "utf-8")));
|
|
3104
|
+
} catch {
|
|
3105
|
+
return null;
|
|
3106
|
+
}
|
|
3107
|
+
}
|
|
3108
|
+
function ownerLiveness(owner) {
|
|
3109
|
+
if (owner.hostname !== os3.hostname()) return "unknown";
|
|
3110
|
+
try {
|
|
3111
|
+
process.kill(owner.pid, 0);
|
|
3112
|
+
return "alive";
|
|
3113
|
+
} catch (error) {
|
|
3114
|
+
const code = getErrorCode2(error);
|
|
3115
|
+
if (code === "ESRCH") return "dead";
|
|
3116
|
+
if (code === "EPERM") return "alive";
|
|
3117
|
+
return "unknown";
|
|
3118
|
+
}
|
|
3119
|
+
}
|
|
3120
|
+
function isHeartbeatExpired(owner) {
|
|
3121
|
+
return Date.now() - Date.parse(owner.heartbeatAt) >= STALE_LEASE_MS;
|
|
3122
|
+
}
|
|
3123
|
+
function sameOwner2(left, right) {
|
|
3124
|
+
return left.pid === right.pid && left.hostname === right.hostname && left.token === right.token;
|
|
3125
|
+
}
|
|
3126
|
+
function writeHeartbeat(leasePath, owner) {
|
|
3127
|
+
const targetPath = heartbeatPath(leasePath, owner.token);
|
|
3128
|
+
const temporaryPath = `${targetPath}.tmp.${process.pid}.${owner.token}.${(0, import_node_crypto.randomUUID)()}`;
|
|
3129
|
+
const heartbeat = {
|
|
3130
|
+
version: 1,
|
|
3131
|
+
token: owner.token,
|
|
3132
|
+
heartbeatAt: owner.heartbeatAt
|
|
3133
|
+
};
|
|
3134
|
+
try {
|
|
3135
|
+
(0, import_node_fs.writeFileSync)(temporaryPath, JSON.stringify(heartbeat), {
|
|
3136
|
+
encoding: "utf-8",
|
|
3137
|
+
flag: "wx",
|
|
3138
|
+
mode: 384
|
|
3139
|
+
});
|
|
3140
|
+
(0, import_node_fs.renameSync)(temporaryPath, targetPath);
|
|
3141
|
+
const currentOwner = readLeaseOwner(leasePath);
|
|
3142
|
+
return currentOwner !== null && sameOwner2(currentOwner, owner);
|
|
3143
|
+
} finally {
|
|
3144
|
+
if ((0, import_node_fs.existsSync)(temporaryPath)) (0, import_node_fs.rmSync)(temporaryPath, { force: true });
|
|
3145
|
+
}
|
|
3146
|
+
}
|
|
3147
|
+
function requestRefreshFromLeader(leasePath, allowDisabledAutoIndex) {
|
|
3148
|
+
const requestPath = refreshRequestPath(leasePath);
|
|
3149
|
+
const temporaryPath = `${requestPath}.tmp.${process.pid}.${(0, import_node_crypto.randomUUID)()}`;
|
|
3150
|
+
try {
|
|
3151
|
+
const request = {
|
|
3152
|
+
allowDisabledAutoIndex,
|
|
3153
|
+
requestedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3154
|
+
version: 1
|
|
3155
|
+
};
|
|
3156
|
+
(0, import_node_fs.writeFileSync)(temporaryPath, JSON.stringify(request), {
|
|
3157
|
+
encoding: "utf-8",
|
|
3158
|
+
flag: "wx",
|
|
3159
|
+
mode: 384
|
|
3160
|
+
});
|
|
3161
|
+
(0, import_node_fs.renameSync)(temporaryPath, requestPath);
|
|
3162
|
+
} catch (error) {
|
|
3163
|
+
if (getErrorCode2(error) !== "ENOENT") {
|
|
3164
|
+
console.error("[codebase-index] Failed to request background index refresh from the project worker:", error);
|
|
3165
|
+
}
|
|
3166
|
+
} finally {
|
|
3167
|
+
if ((0, import_node_fs.existsSync)(temporaryPath)) (0, import_node_fs.rmSync)(temporaryPath, { force: true });
|
|
3168
|
+
}
|
|
3169
|
+
}
|
|
3170
|
+
function consumeRefreshRequest(leasePath) {
|
|
3171
|
+
const requestPath = refreshRequestPath(leasePath);
|
|
3172
|
+
const claimedPath = `${requestPath}.handling.${process.pid}.${(0, import_node_crypto.randomUUID)()}`;
|
|
3173
|
+
try {
|
|
3174
|
+
(0, import_node_fs.renameSync)(requestPath, claimedPath);
|
|
3175
|
+
} catch (error) {
|
|
3176
|
+
if (getErrorCode2(error) === "ENOENT") return null;
|
|
3177
|
+
throw error;
|
|
3178
|
+
}
|
|
3179
|
+
try {
|
|
3180
|
+
const value = JSON.parse((0, import_node_fs.readFileSync)(claimedPath, "utf-8"));
|
|
3181
|
+
return {
|
|
3182
|
+
allowDisabledAutoIndex: value.version === 1 && value.allowDisabledAutoIndex === true,
|
|
3183
|
+
requestedAt: typeof value.requestedAt === "string" ? value.requestedAt : (/* @__PURE__ */ new Date()).toISOString(),
|
|
3184
|
+
version: 1
|
|
3185
|
+
};
|
|
3186
|
+
} catch {
|
|
3187
|
+
return { allowDisabledAutoIndex: false, requestedAt: (/* @__PURE__ */ new Date()).toISOString(), version: 1 };
|
|
3188
|
+
} finally {
|
|
3189
|
+
(0, import_node_fs.rmSync)(claimedPath, { force: true });
|
|
3190
|
+
}
|
|
3191
|
+
}
|
|
3192
|
+
function publishLease(leasePath, owner) {
|
|
3193
|
+
const candidatePath = `${leasePath}.candidate.${process.pid}.${owner.token}`;
|
|
3194
|
+
try {
|
|
3195
|
+
(0, import_node_fs.mkdirSync)(candidatePath, { mode: 448 });
|
|
3196
|
+
} catch (error) {
|
|
3197
|
+
if (getErrorCode2(error) === "ENOENT") return false;
|
|
3198
|
+
throw error;
|
|
3199
|
+
}
|
|
3200
|
+
try {
|
|
3201
|
+
(0, import_node_fs.writeFileSync)(path10.join(candidatePath, OWNER_FILE_NAME2), JSON.stringify(owner), {
|
|
3202
|
+
encoding: "utf-8",
|
|
3203
|
+
flag: "wx",
|
|
3204
|
+
mode: 384
|
|
3205
|
+
});
|
|
3206
|
+
if ((0, import_node_fs.existsSync)(leasePath)) return false;
|
|
3207
|
+
try {
|
|
3208
|
+
(0, import_node_fs.renameSync)(candidatePath, leasePath);
|
|
3209
|
+
return true;
|
|
3210
|
+
} catch (error) {
|
|
3211
|
+
if ((0, import_node_fs.existsSync)(leasePath) || getErrorCode2(error) === "ENOENT") return false;
|
|
3212
|
+
throw error;
|
|
3213
|
+
}
|
|
3214
|
+
} finally {
|
|
3215
|
+
if ((0, import_node_fs.existsSync)(candidatePath)) (0, import_node_fs.rmSync)(candidatePath, { recursive: true, force: true });
|
|
3216
|
+
}
|
|
3217
|
+
}
|
|
3218
|
+
function sameReclaimOwner2(left, right) {
|
|
3219
|
+
return left.pid === right.pid && left.hostname === right.hostname && left.token === right.token && left.expectedOwnerToken === right.expectedOwnerToken;
|
|
3220
|
+
}
|
|
3221
|
+
function reclaimerLiveness(owner) {
|
|
3222
|
+
return ownerLiveness(owner);
|
|
3223
|
+
}
|
|
3224
|
+
function isReclaimMarkerExpired(leasePath, owner) {
|
|
3225
|
+
const startedAt = owner ? Date.parse(owner.startedAt) : (() => {
|
|
3226
|
+
try {
|
|
3227
|
+
return (0, import_node_fs.lstatSync)(reclaimPath(leasePath)).mtimeMs;
|
|
3228
|
+
} catch {
|
|
3229
|
+
return Date.now();
|
|
3230
|
+
}
|
|
3231
|
+
})();
|
|
3232
|
+
return Date.now() - startedAt >= STALE_LEASE_MS;
|
|
3233
|
+
}
|
|
3234
|
+
function hasActiveReclaimMarker(leasePath, owner) {
|
|
3235
|
+
const marker = readReclaimOwner2(leasePath);
|
|
3236
|
+
return marker !== null && marker.expectedOwnerToken === owner.token && (marker.hostname !== os3.hostname() || ownerLiveness(owner) !== "alive");
|
|
3237
|
+
}
|
|
3238
|
+
function publishReclaimMarker(leasePath, expectedOwner) {
|
|
3239
|
+
const markerPath = reclaimPath(leasePath);
|
|
3240
|
+
const owner = {
|
|
3241
|
+
version: 1,
|
|
3242
|
+
pid: process.pid,
|
|
3243
|
+
hostname: os3.hostname(),
|
|
3244
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3245
|
+
token: (0, import_node_crypto.randomUUID)(),
|
|
3246
|
+
expectedOwnerToken: expectedOwner?.token ?? null
|
|
3247
|
+
};
|
|
3248
|
+
try {
|
|
3249
|
+
(0, import_node_fs.mkdirSync)(markerPath, { mode: 448 });
|
|
3250
|
+
} catch (error) {
|
|
3251
|
+
if (getErrorCode2(error) === "EEXIST" || getErrorCode2(error) === "ENOENT") return null;
|
|
3252
|
+
throw error;
|
|
3253
|
+
}
|
|
3254
|
+
try {
|
|
3255
|
+
(0, import_node_fs.writeFileSync)(path10.join(markerPath, OWNER_FILE_NAME2), JSON.stringify(owner), {
|
|
3256
|
+
encoding: "utf-8",
|
|
3257
|
+
flag: "wx",
|
|
3258
|
+
mode: 384
|
|
3259
|
+
});
|
|
3260
|
+
return owner;
|
|
3261
|
+
} catch (error) {
|
|
3262
|
+
(0, import_node_fs.rmSync)(markerPath, { recursive: true, force: true });
|
|
3263
|
+
throw error;
|
|
3264
|
+
}
|
|
3265
|
+
}
|
|
3266
|
+
function removeExpiredReclaimMarker(leasePath, expectedOwner) {
|
|
3267
|
+
const marker = readReclaimOwner2(leasePath);
|
|
3268
|
+
const markerPath = reclaimPath(leasePath);
|
|
3269
|
+
if (!(0, import_node_fs.existsSync)(markerPath)) return false;
|
|
3270
|
+
if (marker && marker.expectedOwnerToken !== (expectedOwner?.token ?? null)) return false;
|
|
3271
|
+
if (marker && (reclaimerLiveness(marker) === "alive" || !isReclaimMarkerExpired(leasePath, marker))) return false;
|
|
3272
|
+
if (!marker && !isReclaimMarkerExpired(leasePath, null)) return false;
|
|
3273
|
+
const staleMarkerPath = `${markerPath}.stale.${marker?.pid ?? process.pid}.${marker?.token ?? (0, import_node_crypto.randomUUID)()}.${(0, import_node_crypto.randomUUID)()}`;
|
|
3274
|
+
try {
|
|
3275
|
+
(0, import_node_fs.renameSync)(markerPath, staleMarkerPath);
|
|
3276
|
+
} catch (error) {
|
|
3277
|
+
if (getErrorCode2(error) === "ENOENT") return false;
|
|
3278
|
+
throw error;
|
|
3279
|
+
}
|
|
3280
|
+
try {
|
|
3281
|
+
let claimedMarker = null;
|
|
3282
|
+
try {
|
|
3283
|
+
claimedMarker = parseReclaimOwner2(
|
|
3284
|
+
JSON.parse((0, import_node_fs.readFileSync)(path10.join(staleMarkerPath, OWNER_FILE_NAME2), "utf-8"))
|
|
3285
|
+
);
|
|
3286
|
+
} catch {
|
|
3287
|
+
claimedMarker = null;
|
|
3288
|
+
}
|
|
3289
|
+
const markerMatches = marker ? claimedMarker !== null && sameReclaimOwner2(claimedMarker, marker) : claimedMarker === null;
|
|
3290
|
+
if (!markerMatches || !canReclaimLease(leasePath, expectedOwner)) {
|
|
3291
|
+
if (!(0, import_node_fs.existsSync)(markerPath) && (0, import_node_fs.existsSync)(staleMarkerPath)) (0, import_node_fs.renameSync)(staleMarkerPath, markerPath);
|
|
3292
|
+
return false;
|
|
3293
|
+
}
|
|
3294
|
+
(0, import_node_fs.rmSync)(staleMarkerPath, { recursive: true, force: true });
|
|
3295
|
+
return true;
|
|
3296
|
+
} catch (error) {
|
|
3297
|
+
if (getErrorCode2(error) === "ENOENT") return false;
|
|
3298
|
+
throw error;
|
|
3299
|
+
}
|
|
3300
|
+
}
|
|
3301
|
+
function canReclaimLease(leasePath, expectedOwner) {
|
|
3302
|
+
if (!(0, import_node_fs.existsSync)(leasePath)) return false;
|
|
3303
|
+
if (!expectedOwner) return false;
|
|
3304
|
+
const currentOwner = readOwner(leasePath);
|
|
3305
|
+
if (!currentOwner || !sameOwner2(currentOwner, expectedOwner)) return false;
|
|
3306
|
+
if (currentOwner.hostname === os3.hostname()) {
|
|
3307
|
+
return ownerLiveness(currentOwner) === "dead";
|
|
3308
|
+
}
|
|
3309
|
+
return isHeartbeatExpired(currentOwner);
|
|
3310
|
+
}
|
|
3311
|
+
function reclaimLease(leasePath, expectedOwner) {
|
|
3312
|
+
let marker = null;
|
|
3313
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
3314
|
+
marker = publishReclaimMarker(leasePath, expectedOwner);
|
|
3315
|
+
if (marker) break;
|
|
3316
|
+
if (attempt === 0 && removeExpiredReclaimMarker(leasePath, expectedOwner)) continue;
|
|
3317
|
+
return false;
|
|
3318
|
+
}
|
|
3319
|
+
if (!marker) return false;
|
|
3320
|
+
const markerPath = reclaimPath(leasePath);
|
|
3321
|
+
try {
|
|
3322
|
+
const currentMarker = readReclaimOwner2(leasePath);
|
|
3323
|
+
if (!currentMarker || !sameReclaimOwner2(currentMarker, marker) || !canReclaimLease(leasePath, expectedOwner)) {
|
|
3324
|
+
return false;
|
|
3325
|
+
}
|
|
3326
|
+
const stalePath = `${leasePath}.stale.${process.pid}.${marker.token}`;
|
|
3327
|
+
(0, import_node_fs.renameSync)(leasePath, stalePath);
|
|
3328
|
+
const quarantinedOwner = readOwner(stalePath);
|
|
3329
|
+
const quarantinedMarker = readReclaimOwner2(stalePath);
|
|
3330
|
+
if (!quarantinedMarker || !sameReclaimOwner2(quarantinedMarker, marker) || expectedOwner !== null && (!quarantinedOwner || !sameOwner2(quarantinedOwner, expectedOwner))) {
|
|
3331
|
+
if (!(0, import_node_fs.existsSync)(leasePath) && (0, import_node_fs.existsSync)(stalePath)) (0, import_node_fs.renameSync)(stalePath, leasePath);
|
|
3332
|
+
return false;
|
|
3333
|
+
}
|
|
3334
|
+
(0, import_node_fs.rmSync)(stalePath, { recursive: true, force: true });
|
|
3335
|
+
return true;
|
|
3336
|
+
} catch (error) {
|
|
3337
|
+
if (getErrorCode2(error) === "ENOENT") return false;
|
|
3338
|
+
throw error;
|
|
3339
|
+
} finally {
|
|
3340
|
+
const currentMarker = readReclaimOwner2(leasePath);
|
|
3341
|
+
if (currentMarker && sameReclaimOwner2(currentMarker, marker)) {
|
|
3342
|
+
(0, import_node_fs.rmSync)(markerPath, { recursive: true, force: true });
|
|
3343
|
+
}
|
|
3344
|
+
}
|
|
3345
|
+
}
|
|
3346
|
+
function acquireLease(identity) {
|
|
3347
|
+
(0, import_node_fs.mkdirSync)(identity.canonicalIndexPath, { recursive: true, mode: 448 });
|
|
3348
|
+
const canonicalIndexPath = import_node_fs.realpathSync.native(identity.canonicalIndexPath);
|
|
3349
|
+
const leasePath = path10.join(canonicalIndexPath, leaseDirectoryName({ ...identity, canonicalIndexPath }));
|
|
3350
|
+
for (let attempt = 0; attempt < 4; attempt += 1) {
|
|
3351
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
3352
|
+
const owner = {
|
|
3353
|
+
version: 1,
|
|
3354
|
+
pid: process.pid,
|
|
3355
|
+
hostname: os3.hostname(),
|
|
3356
|
+
startedAt: timestamp,
|
|
3357
|
+
heartbeatAt: timestamp,
|
|
3358
|
+
projectRoot: identity.canonicalProjectRoot,
|
|
3359
|
+
indexPath: canonicalIndexPath,
|
|
3360
|
+
token: (0, import_node_crypto.randomUUID)()
|
|
3361
|
+
};
|
|
3362
|
+
if (publishLease(leasePath, owner)) {
|
|
3363
|
+
return { leasePath, owner };
|
|
3364
|
+
}
|
|
3365
|
+
const existingOwner = readOwner(leasePath);
|
|
3366
|
+
if (existingOwner) {
|
|
3367
|
+
if (canReclaimLease(leasePath, existingOwner) && reclaimLease(leasePath, existingOwner)) continue;
|
|
3368
|
+
return null;
|
|
3369
|
+
}
|
|
3370
|
+
return null;
|
|
3371
|
+
}
|
|
3372
|
+
return null;
|
|
3373
|
+
}
|
|
3374
|
+
function releaseLease(lease) {
|
|
3375
|
+
const currentOwner = readOwner(lease.leasePath);
|
|
3376
|
+
if (!currentOwner || !sameOwner2(currentOwner, lease.owner)) return false;
|
|
3377
|
+
const releasePath = `${lease.leasePath}.release.${lease.owner.pid}.${lease.owner.token}`;
|
|
3378
|
+
try {
|
|
3379
|
+
(0, import_node_fs.renameSync)(lease.leasePath, releasePath);
|
|
3380
|
+
} catch (error) {
|
|
3381
|
+
if (getErrorCode2(error) === "ENOENT") return false;
|
|
3382
|
+
throw error;
|
|
3383
|
+
}
|
|
3384
|
+
const claimedOwner = readOwner(releasePath);
|
|
3385
|
+
if (!claimedOwner || !sameOwner2(claimedOwner, lease.owner)) {
|
|
3386
|
+
if (!(0, import_node_fs.existsSync)(lease.leasePath) && (0, import_node_fs.existsSync)(releasePath)) {
|
|
3387
|
+
(0, import_node_fs.renameSync)(releasePath, lease.leasePath);
|
|
3388
|
+
}
|
|
3389
|
+
return false;
|
|
3390
|
+
}
|
|
3391
|
+
(0, import_node_fs.rmSync)(releasePath, { recursive: true, force: true });
|
|
3392
|
+
return true;
|
|
3393
|
+
}
|
|
3394
|
+
var BackgroundWorkerController = class {
|
|
3395
|
+
constructor(projectRoot, host, config, hooks, identity) {
|
|
3396
|
+
this.projectRoot = projectRoot;
|
|
3397
|
+
this.host = host;
|
|
3398
|
+
this.config = config;
|
|
3399
|
+
this.hooks = hooks;
|
|
3400
|
+
this.identity = identity;
|
|
3401
|
+
}
|
|
3402
|
+
projectRoot;
|
|
3403
|
+
host;
|
|
3404
|
+
config;
|
|
3405
|
+
hooks;
|
|
3406
|
+
identity;
|
|
3407
|
+
lease = null;
|
|
3408
|
+
watcher = null;
|
|
3409
|
+
leaderReady = Promise.resolve();
|
|
3410
|
+
heartbeatTimer = null;
|
|
3411
|
+
retryTimer = null;
|
|
3412
|
+
teardownRetryTimer = null;
|
|
3413
|
+
transition = Promise.resolve();
|
|
3414
|
+
stopPromise = null;
|
|
3415
|
+
stopped = false;
|
|
3416
|
+
stopping = false;
|
|
3417
|
+
losingLeadership = false;
|
|
3418
|
+
restartAfterStop = false;
|
|
3419
|
+
leaderWorkStopped = false;
|
|
3420
|
+
startingLeaderWork = false;
|
|
3421
|
+
stopAutoIndexOnTeardown = true;
|
|
3422
|
+
autoIndexStarted = false;
|
|
3423
|
+
reportedError = null;
|
|
3424
|
+
update(config, hooks, options) {
|
|
3425
|
+
const autoIndexWasEnabled = this.config.indexing.autoIndex;
|
|
3426
|
+
const shouldReplaceWatcher = this.watcher !== null && hooks.watcherFactory !== void 0 && (hooks.watcherFactory === null || hooks.replaceWatcher === true);
|
|
3427
|
+
this.config = config;
|
|
3428
|
+
this.hooks = {
|
|
3429
|
+
...this.hooks,
|
|
3430
|
+
...hooks,
|
|
3431
|
+
watcherFactory: hooks.watcherFactory === void 0 ? this.hooks.watcherFactory : hooks.watcherFactory,
|
|
3432
|
+
watcherFactoryForConfig: hooks.watcherFactoryForConfig === void 0 ? this.hooks.watcherFactoryForConfig : hooks.watcherFactoryForConfig
|
|
3433
|
+
};
|
|
3434
|
+
if (autoIndexWasEnabled && !config.indexing.autoIndex || options.restartAutoIndex === true && config.indexing.autoIndex && !this.startingLeaderWork) {
|
|
3435
|
+
this.autoIndexStarted = false;
|
|
3436
|
+
}
|
|
3437
|
+
if (!this.canRun()) {
|
|
3438
|
+
void this.stop().catch((error) => {
|
|
3439
|
+
console.error("[codebase-index] Failed to stop background worker after disabling automatic work:", error);
|
|
3440
|
+
});
|
|
3441
|
+
return;
|
|
3442
|
+
}
|
|
3443
|
+
if (shouldReplaceWatcher) {
|
|
3444
|
+
void this.enqueue(async () => {
|
|
3445
|
+
const watcher = this.watcher;
|
|
3446
|
+
if (watcher) {
|
|
3447
|
+
await watcher.stop();
|
|
3448
|
+
if (this.watcher === watcher) this.watcher = null;
|
|
3449
|
+
}
|
|
3450
|
+
if (this.lease && !this.stopped) this.startLeaderWork();
|
|
3451
|
+
}).catch((error) => {
|
|
3452
|
+
console.error("[codebase-index] Failed to replace background file watcher:", error);
|
|
3453
|
+
});
|
|
3454
|
+
}
|
|
3455
|
+
this.start();
|
|
3456
|
+
}
|
|
3457
|
+
startAfter(activation) {
|
|
3458
|
+
this.transition = activation.catch(() => void 0);
|
|
3459
|
+
this.start();
|
|
3460
|
+
}
|
|
3461
|
+
start() {
|
|
3462
|
+
if (!this.canRun() || this.losingLeadership) return;
|
|
3463
|
+
if (this.stopping) {
|
|
3464
|
+
this.restartAfterStop = true;
|
|
3465
|
+
return;
|
|
3466
|
+
}
|
|
3467
|
+
this.stopped = false;
|
|
3468
|
+
void this.enqueue(async () => {
|
|
3469
|
+
if (this.stopped || this.stopping || this.losingLeadership || !this.canRun()) return;
|
|
3470
|
+
if (!this.lease) {
|
|
3471
|
+
try {
|
|
3472
|
+
this.lease = acquireLease(this.identity);
|
|
3473
|
+
this.reportedError = null;
|
|
3474
|
+
} catch (error) {
|
|
3475
|
+
this.reportAcquireError(error);
|
|
3476
|
+
this.scheduleRetry();
|
|
3477
|
+
return;
|
|
3478
|
+
}
|
|
3479
|
+
}
|
|
3480
|
+
if (!this.lease) {
|
|
3481
|
+
this.scheduleRetry();
|
|
3482
|
+
return;
|
|
3483
|
+
}
|
|
3484
|
+
this.startHeartbeat();
|
|
3485
|
+
this.startLeaderWork();
|
|
3486
|
+
});
|
|
3487
|
+
}
|
|
3488
|
+
waitForStart() {
|
|
3489
|
+
return this.transition.catch(() => void 0).then(() => this.leaderReady);
|
|
3490
|
+
}
|
|
3491
|
+
requestRefresh(allowDisabledAutoIndex = false) {
|
|
3492
|
+
this.start();
|
|
3493
|
+
if (!this.isLeader()) {
|
|
3494
|
+
requestRefreshFromLeader(leasePathFor(this.identity), allowDisabledAutoIndex);
|
|
3495
|
+
return;
|
|
3496
|
+
}
|
|
3497
|
+
void this.enqueue(async () => {
|
|
3498
|
+
if (this.stopped || !this.lease) return;
|
|
3499
|
+
this.hooks.startAutoIndex("retrieval", allowDisabledAutoIndex);
|
|
3500
|
+
});
|
|
3501
|
+
}
|
|
3502
|
+
isLeader() {
|
|
3503
|
+
return this.lease !== null && !this.stopping && !this.losingLeadership;
|
|
3504
|
+
}
|
|
3505
|
+
isStopping() {
|
|
3506
|
+
return this.stopping;
|
|
3507
|
+
}
|
|
3508
|
+
getHooksForConfig(config) {
|
|
3509
|
+
const watcherFactoryForConfig = this.hooks.watcherFactoryForConfig;
|
|
3510
|
+
if (!watcherFactoryForConfig) return this.hooks;
|
|
3511
|
+
return {
|
|
3512
|
+
...this.hooks,
|
|
3513
|
+
watcherFactory: watcherFactoryForConfig(config),
|
|
3514
|
+
replaceWatcher: true
|
|
3515
|
+
};
|
|
3516
|
+
}
|
|
3517
|
+
attachWatcher(watcherFactory, watcherFactoryForConfig) {
|
|
3518
|
+
if (this.hooks.watcherFactory !== void 0) return;
|
|
3519
|
+
this.hooks = {
|
|
3520
|
+
...this.hooks,
|
|
3521
|
+
watcherFactory,
|
|
3522
|
+
watcherFactoryForConfig: watcherFactoryForConfig ?? this.hooks.watcherFactoryForConfig
|
|
3523
|
+
};
|
|
3524
|
+
this.start();
|
|
3525
|
+
}
|
|
3526
|
+
async stop(stopAutoIndex = true) {
|
|
3527
|
+
if (this.stopPromise) return this.stopPromise;
|
|
3528
|
+
this.stopped = true;
|
|
3529
|
+
this.stopping = true;
|
|
3530
|
+
this.stopAutoIndexOnTeardown &&= stopAutoIndex;
|
|
3531
|
+
this.clearRetryTimer();
|
|
3532
|
+
const attempt = this.enqueue(async () => {
|
|
3533
|
+
try {
|
|
3534
|
+
const lease = this.lease;
|
|
3535
|
+
if (this.leaderWorkStopped) {
|
|
3536
|
+
if (lease) {
|
|
3537
|
+
this.releaseStoppedLease(lease);
|
|
3538
|
+
} else {
|
|
3539
|
+
this.finishStoppedLease();
|
|
3540
|
+
}
|
|
3541
|
+
return;
|
|
3542
|
+
}
|
|
3543
|
+
const hadLeaderWork = lease !== null || this.watcher !== null || this.autoIndexStarted;
|
|
3544
|
+
const stopped = await this.stopLeaderWork(hadLeaderWork && this.stopAutoIndexOnTeardown);
|
|
3545
|
+
if (!lease) {
|
|
3546
|
+
this.finishStoppedLease();
|
|
3547
|
+
return;
|
|
3548
|
+
}
|
|
3549
|
+
if (!stopped.completed) {
|
|
3550
|
+
this.releaseLeaseWhenAutoIndexStops(lease, stopped.completion);
|
|
3551
|
+
return;
|
|
3552
|
+
}
|
|
3553
|
+
this.leaderWorkStopped = true;
|
|
3554
|
+
this.releaseStoppedLease(lease);
|
|
3555
|
+
} catch (error) {
|
|
3556
|
+
this.scheduleTeardownRetry();
|
|
3557
|
+
throw error;
|
|
3558
|
+
}
|
|
3559
|
+
});
|
|
3560
|
+
const completion = attempt.finally(() => {
|
|
3561
|
+
if (this.stopPromise === completion) this.stopPromise = null;
|
|
3562
|
+
});
|
|
3563
|
+
this.stopPromise = completion;
|
|
3564
|
+
return completion;
|
|
3565
|
+
}
|
|
3566
|
+
canRun() {
|
|
3567
|
+
return this.config.indexing.autoIndex || this.hooks.watcherFactory != null;
|
|
3568
|
+
}
|
|
3569
|
+
enqueue(operation) {
|
|
3570
|
+
const next = this.transition.catch(() => void 0).then(operation);
|
|
3571
|
+
this.transition = next;
|
|
3572
|
+
return next;
|
|
3573
|
+
}
|
|
3574
|
+
startLeaderWork() {
|
|
3575
|
+
if (this.stopped || this.stopping || this.losingLeadership) return;
|
|
3576
|
+
this.startingLeaderWork = true;
|
|
3577
|
+
try {
|
|
3578
|
+
if (this.config.indexing.autoIndex && !this.autoIndexStarted) {
|
|
3579
|
+
this.autoIndexStarted = true;
|
|
3580
|
+
this.hooks.startAutoIndex("startup");
|
|
3581
|
+
}
|
|
3582
|
+
if (!this.watcher && this.hooks.watcherFactory) {
|
|
3583
|
+
try {
|
|
3584
|
+
const watcher = this.hooks.watcherFactory();
|
|
3585
|
+
this.watcher = watcher;
|
|
3586
|
+
this.leaderReady = watcher.whenReady?.().catch((error) => {
|
|
3587
|
+
console.error("[codebase-index] Failed while waiting for background file watcher startup:", error);
|
|
3588
|
+
}) ?? Promise.resolve();
|
|
3589
|
+
} catch (error) {
|
|
3590
|
+
console.error("[codebase-index] Failed to start background file watcher:", error);
|
|
3591
|
+
this.leaderReady = Promise.resolve();
|
|
3592
|
+
}
|
|
3593
|
+
}
|
|
3594
|
+
} finally {
|
|
3595
|
+
this.startingLeaderWork = false;
|
|
3596
|
+
}
|
|
3597
|
+
}
|
|
3598
|
+
async stopLeaderWork(stopAutoIndex) {
|
|
3599
|
+
const watcher = this.watcher;
|
|
3600
|
+
let watcherError;
|
|
3601
|
+
if (watcher) {
|
|
3602
|
+
try {
|
|
3603
|
+
await watcher.stop();
|
|
3604
|
+
if (this.watcher === watcher) this.watcher = null;
|
|
3605
|
+
} catch (error) {
|
|
3606
|
+
watcherError = error;
|
|
3607
|
+
}
|
|
3608
|
+
}
|
|
3609
|
+
let autoIndexError;
|
|
3610
|
+
let autoIndexStop = {
|
|
3611
|
+
completed: true,
|
|
3612
|
+
completion: Promise.resolve()
|
|
3613
|
+
};
|
|
3614
|
+
if (stopAutoIndex) {
|
|
3615
|
+
try {
|
|
3616
|
+
autoIndexStop = await this.hooks.stopAutoIndex();
|
|
3617
|
+
this.autoIndexStarted = false;
|
|
3618
|
+
} catch (error) {
|
|
3619
|
+
autoIndexError = error;
|
|
3620
|
+
}
|
|
3621
|
+
}
|
|
3622
|
+
if (watcherError !== void 0 || autoIndexError !== void 0) {
|
|
3623
|
+
throw new BackgroundWorkerStopError(watcherError, autoIndexError);
|
|
3624
|
+
}
|
|
3625
|
+
return autoIndexStop;
|
|
3626
|
+
}
|
|
3627
|
+
releaseLeaseWhenAutoIndexStops(lease, completion) {
|
|
3628
|
+
void completion.then(
|
|
3629
|
+
() => {
|
|
3630
|
+
void this.enqueue(async () => {
|
|
3631
|
+
if (this.lease !== lease || !this.stopping) return;
|
|
3632
|
+
this.leaderWorkStopped = true;
|
|
3633
|
+
this.releaseStoppedLease(lease);
|
|
3634
|
+
}).catch((error) => {
|
|
3635
|
+
console.error("[codebase-index] Failed to release background worker lease after automatic indexing stopped:", error);
|
|
3636
|
+
this.scheduleTeardownRetry();
|
|
3637
|
+
});
|
|
3638
|
+
},
|
|
3639
|
+
(error) => {
|
|
3640
|
+
console.error("[codebase-index] Failed while waiting for automatic indexing to stop:", error);
|
|
3641
|
+
this.scheduleTeardownRetry();
|
|
3642
|
+
}
|
|
3643
|
+
);
|
|
3644
|
+
}
|
|
3645
|
+
releaseStoppedLease(lease) {
|
|
3646
|
+
if (this.lease !== lease) {
|
|
3647
|
+
this.finishStoppedLease();
|
|
3648
|
+
return;
|
|
3649
|
+
}
|
|
3650
|
+
releaseLease(lease);
|
|
3651
|
+
this.lease = null;
|
|
3652
|
+
this.finishStoppedLease();
|
|
3653
|
+
}
|
|
3654
|
+
finishStoppedLease() {
|
|
3655
|
+
this.leaderWorkStopped = false;
|
|
3656
|
+
this.stopAutoIndexOnTeardown = true;
|
|
3657
|
+
this.stopping = false;
|
|
3658
|
+
this.clearTimers();
|
|
3659
|
+
this.restartAfterTeardown();
|
|
3660
|
+
if (!this.stopped || this.stopping) return;
|
|
3661
|
+
const projectKey = projectLookupKey(this.projectRoot, this.host);
|
|
3662
|
+
const key = controllerKey(this.identity, this.host);
|
|
3663
|
+
if (workers.get(key) === this) workers.delete(key);
|
|
3664
|
+
if (workerKeysByProject.get(projectKey) === key) workerKeysByProject.delete(projectKey);
|
|
3665
|
+
}
|
|
3666
|
+
startHeartbeat() {
|
|
3667
|
+
if (this.heartbeatTimer) return;
|
|
3668
|
+
const heartbeat = () => {
|
|
3669
|
+
void this.heartbeat();
|
|
3670
|
+
};
|
|
3671
|
+
this.heartbeatTimer = setInterval(heartbeat, HEARTBEAT_INTERVAL_MS);
|
|
3672
|
+
this.heartbeatTimer.unref?.();
|
|
3673
|
+
}
|
|
3674
|
+
async heartbeat() {
|
|
3675
|
+
const lease = this.lease;
|
|
3676
|
+
if (!lease || this.losingLeadership || this.stopped && !this.stopping) return;
|
|
3677
|
+
if (hasActiveReclaimMarker(lease.leasePath, lease.owner)) {
|
|
3678
|
+
await this.loseLeadership();
|
|
3679
|
+
return;
|
|
3680
|
+
}
|
|
3681
|
+
const currentOwner = readOwner(lease.leasePath);
|
|
3682
|
+
if (!currentOwner || !sameOwner2(currentOwner, lease.owner)) {
|
|
3683
|
+
await this.loseLeadership();
|
|
3684
|
+
return;
|
|
3685
|
+
}
|
|
3686
|
+
try {
|
|
3687
|
+
const nextOwner = { ...lease.owner, heartbeatAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
3688
|
+
if (!writeHeartbeat(lease.leasePath, nextOwner)) {
|
|
3689
|
+
await this.loseLeadership();
|
|
3690
|
+
return;
|
|
3691
|
+
}
|
|
3692
|
+
lease.owner = nextOwner;
|
|
3693
|
+
const refreshRequest = !this.stopping ? consumeRefreshRequest(lease.leasePath) : null;
|
|
3694
|
+
if (refreshRequest) {
|
|
3695
|
+
this.hooks.startAutoIndex("retrieval", refreshRequest.allowDisabledAutoIndex);
|
|
3696
|
+
}
|
|
3697
|
+
} catch (error) {
|
|
3698
|
+
const ownerAfterError = readOwner(lease.leasePath);
|
|
3699
|
+
if (hasActiveReclaimMarker(lease.leasePath, lease.owner) || !ownerAfterError || !sameOwner2(ownerAfterError, lease.owner)) {
|
|
3700
|
+
await this.loseLeadership();
|
|
3701
|
+
return;
|
|
3702
|
+
}
|
|
3703
|
+
console.error("[codebase-index] Failed to renew background worker lease:", error);
|
|
3704
|
+
}
|
|
3705
|
+
}
|
|
3706
|
+
async loseLeadership() {
|
|
3707
|
+
if (this.losingLeadership) return;
|
|
3708
|
+
this.losingLeadership = true;
|
|
3709
|
+
this.clearHeartbeat();
|
|
3710
|
+
await this.enqueue(async () => this.stopAfterLeadershipLoss());
|
|
3711
|
+
}
|
|
3712
|
+
async stopAfterLeadershipLoss() {
|
|
3713
|
+
const lease = this.lease;
|
|
3714
|
+
if (!lease) {
|
|
3715
|
+
this.losingLeadership = false;
|
|
3716
|
+
return;
|
|
3717
|
+
}
|
|
3718
|
+
try {
|
|
3719
|
+
const stopped = await this.stopLeaderWork(true);
|
|
3720
|
+
this.lease = null;
|
|
3721
|
+
this.losingLeadership = false;
|
|
3722
|
+
if (stopped.completed) {
|
|
3723
|
+
this.scheduleRetry();
|
|
3724
|
+
} else {
|
|
3725
|
+
void stopped.completion.then(() => this.scheduleRetry());
|
|
3726
|
+
}
|
|
3727
|
+
} catch (error) {
|
|
3728
|
+
console.error("[codebase-index] Failed to stop background work after losing its lease:", error);
|
|
3729
|
+
this.scheduleLostLeadershipTeardownRetry();
|
|
3730
|
+
}
|
|
3731
|
+
}
|
|
3732
|
+
scheduleRetry() {
|
|
3733
|
+
if (this.stopped || !this.canRun() || this.retryTimer) return;
|
|
3734
|
+
this.retryTimer = setTimeout(() => {
|
|
3735
|
+
this.retryTimer = null;
|
|
3736
|
+
this.start();
|
|
3737
|
+
}, RETRY_DELAY_MS);
|
|
3738
|
+
this.retryTimer.unref?.();
|
|
3739
|
+
}
|
|
3740
|
+
scheduleTeardownRetry() {
|
|
3741
|
+
if (!this.stopping || this.teardownRetryTimer) return;
|
|
3742
|
+
this.teardownRetryTimer = setTimeout(() => {
|
|
3743
|
+
this.teardownRetryTimer = null;
|
|
3744
|
+
void this.stop(this.stopAutoIndexOnTeardown).catch((error) => {
|
|
3745
|
+
console.error("[codebase-index] Failed to retry background worker teardown:", error);
|
|
3746
|
+
});
|
|
3747
|
+
}, RETRY_DELAY_MS);
|
|
3748
|
+
this.teardownRetryTimer.unref?.();
|
|
3749
|
+
}
|
|
3750
|
+
restartAfterTeardown() {
|
|
3751
|
+
if (!this.restartAfterStop || !this.canRun() || this.losingLeadership) return;
|
|
3752
|
+
this.restartAfterStop = false;
|
|
3753
|
+
this.stopped = false;
|
|
3754
|
+
this.start();
|
|
3755
|
+
}
|
|
3756
|
+
scheduleLostLeadershipTeardownRetry() {
|
|
3757
|
+
if (this.stopped || !this.losingLeadership || this.retryTimer) return;
|
|
3758
|
+
this.retryTimer = setTimeout(() => {
|
|
3759
|
+
this.retryTimer = null;
|
|
3760
|
+
void this.enqueue(async () => this.stopAfterLeadershipLoss());
|
|
3761
|
+
}, RETRY_DELAY_MS);
|
|
3762
|
+
this.retryTimer.unref?.();
|
|
3763
|
+
}
|
|
3764
|
+
clearHeartbeat() {
|
|
3765
|
+
if (!this.heartbeatTimer) return;
|
|
3766
|
+
clearInterval(this.heartbeatTimer);
|
|
3767
|
+
this.heartbeatTimer = null;
|
|
3768
|
+
}
|
|
3769
|
+
clearTimers() {
|
|
3770
|
+
this.clearHeartbeat();
|
|
3771
|
+
this.clearRetryTimer();
|
|
3772
|
+
if (this.teardownRetryTimer) {
|
|
3773
|
+
clearTimeout(this.teardownRetryTimer);
|
|
3774
|
+
this.teardownRetryTimer = null;
|
|
3775
|
+
}
|
|
3776
|
+
}
|
|
3777
|
+
clearRetryTimer() {
|
|
3778
|
+
if (!this.retryTimer) return;
|
|
3779
|
+
clearTimeout(this.retryTimer);
|
|
3780
|
+
this.retryTimer = null;
|
|
3781
|
+
}
|
|
3782
|
+
reportAcquireError(error) {
|
|
3783
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
3784
|
+
if (this.reportedError === message) return;
|
|
3785
|
+
this.reportedError = message;
|
|
3786
|
+
console.error("[codebase-index] Failed to acquire background worker lease:", error);
|
|
3787
|
+
}
|
|
3788
|
+
};
|
|
3789
|
+
function configureBackgroundWorker(projectRoot, host, config, hooks, options = {}) {
|
|
3790
|
+
const projectKey = projectLookupKey(projectRoot, host);
|
|
3791
|
+
const identity = resolveIdentity(projectRoot, config, host);
|
|
3792
|
+
const key = controllerKey(identity, host);
|
|
3793
|
+
const previousKey = workerKeysByProject.get(projectKey);
|
|
3794
|
+
if (previousKey && previousKey !== key) {
|
|
3795
|
+
const previous = workers.get(previousKey);
|
|
3796
|
+
const previousBarrier = workerReplacementBarriers.get(projectKey) ?? Promise.resolve();
|
|
3797
|
+
const stopPrevious = previous?.stop(options.stopPreviousAutoIndex ?? true) ?? Promise.resolve();
|
|
3798
|
+
const activation = Promise.all([previousBarrier, stopPrevious]).then(() => void 0);
|
|
3799
|
+
workerReplacementBarriers.set(projectKey, activation);
|
|
3800
|
+
workers.delete(previousKey);
|
|
3801
|
+
const worker2 = new BackgroundWorkerController(projectRoot, host, config, hooks, identity);
|
|
3802
|
+
worker2.startAfter(activation);
|
|
3803
|
+
workers.set(key, worker2);
|
|
3804
|
+
workerKeysByProject.set(projectKey, key);
|
|
3805
|
+
return;
|
|
3806
|
+
}
|
|
3807
|
+
let worker = workers.get(key);
|
|
3808
|
+
if (!worker) {
|
|
3809
|
+
worker = new BackgroundWorkerController(projectRoot, host, config, hooks, identity);
|
|
3810
|
+
workers.set(key, worker);
|
|
3811
|
+
} else {
|
|
3812
|
+
worker.update(config, hooks, options);
|
|
3813
|
+
}
|
|
3814
|
+
workerKeysByProject.set(projectKey, key);
|
|
3815
|
+
worker.start();
|
|
3816
|
+
}
|
|
3817
|
+
function updateBackgroundWorkerConfig(projectRoot, host, config) {
|
|
3818
|
+
const projectKey = projectLookupKey(projectRoot, host);
|
|
3819
|
+
const key = workerKeysByProject.get(projectKey);
|
|
3820
|
+
const worker = key ? workers.get(key) : void 0;
|
|
3821
|
+
if (!worker) return;
|
|
3822
|
+
configureBackgroundWorker(projectRoot, host, config, worker.getHooksForConfig(config), {
|
|
3823
|
+
stopPreviousAutoIndex: false,
|
|
3824
|
+
restartAutoIndex: true
|
|
3825
|
+
});
|
|
3826
|
+
}
|
|
3827
|
+
function requestBackgroundWorkerRefresh(projectRoot, host, allowDisabledAutoIndex = false) {
|
|
3828
|
+
const key = workerKeysByProject.get(projectLookupKey(projectRoot, host));
|
|
3829
|
+
workers.get(key ?? "")?.requestRefresh(allowDisabledAutoIndex);
|
|
3830
|
+
}
|
|
3831
|
+
function isBackgroundWorkerManaged(projectRoot, host) {
|
|
3832
|
+
const key = workerKeysByProject.get(projectLookupKey(projectRoot, host));
|
|
3833
|
+
return key !== void 0 && workers.has(key);
|
|
3834
|
+
}
|
|
3835
|
+
function isBackgroundWorkerLeader(projectRoot, host) {
|
|
3836
|
+
const key = workerKeysByProject.get(projectLookupKey(projectRoot, host));
|
|
3837
|
+
return key !== void 0 && workers.get(key)?.isLeader() === true;
|
|
3838
|
+
}
|
|
3839
|
+
async function stopBackgroundWorker(projectRoot, host) {
|
|
3840
|
+
const projectKey = projectLookupKey(projectRoot, host);
|
|
3841
|
+
const key = workerKeysByProject.get(projectKey);
|
|
3842
|
+
const worker = key ? workers.get(key) : void 0;
|
|
3843
|
+
if (!worker) return;
|
|
3844
|
+
await worker.stop();
|
|
3845
|
+
}
|
|
3846
|
+
|
|
2977
3847
|
// src/utils/files.ts
|
|
2978
3848
|
var import_ignore = __toESM(require_ignore(), 1);
|
|
2979
3849
|
var import_fs6 = require("fs");
|
|
2980
|
-
var
|
|
3850
|
+
var path11 = __toESM(require("path"), 1);
|
|
2981
3851
|
var PROJECT_MARKERS = [
|
|
2982
3852
|
".git",
|
|
2983
3853
|
"package.json",
|
|
@@ -2995,7 +3865,7 @@ var PROJECT_MARKERS = [
|
|
|
2995
3865
|
];
|
|
2996
3866
|
function hasProjectMarker(projectRoot) {
|
|
2997
3867
|
for (const marker of PROJECT_MARKERS) {
|
|
2998
|
-
if ((0, import_fs6.existsSync)(
|
|
3868
|
+
if ((0, import_fs6.existsSync)(path11.join(projectRoot, marker))) {
|
|
2999
3869
|
return true;
|
|
3000
3870
|
}
|
|
3001
3871
|
}
|
|
@@ -3022,13 +3892,40 @@ function createIgnoreFilter(projectRoot) {
|
|
|
3022
3892
|
"**/*build*/**"
|
|
3023
3893
|
];
|
|
3024
3894
|
ig.add(defaultIgnores);
|
|
3025
|
-
const gitignorePath =
|
|
3895
|
+
const gitignorePath = path11.join(projectRoot, ".gitignore");
|
|
3026
3896
|
if ((0, import_fs6.existsSync)(gitignorePath)) {
|
|
3027
3897
|
const gitignoreContent = (0, import_fs6.readFileSync)(gitignorePath, "utf-8");
|
|
3028
3898
|
ig.add(gitignoreContent);
|
|
3029
3899
|
}
|
|
3030
3900
|
return ig;
|
|
3031
3901
|
}
|
|
3902
|
+
function toPosixRelativePath(relativePath) {
|
|
3903
|
+
return relativePath.split(path11.sep).join("/");
|
|
3904
|
+
}
|
|
3905
|
+
function matchesAnyGlob(filePath, patterns) {
|
|
3906
|
+
const normalized = toPosixRelativePath(filePath);
|
|
3907
|
+
return patterns.some((pattern) => matchGlob(normalized, pattern));
|
|
3908
|
+
}
|
|
3909
|
+
function isExcludedByPatterns(relativePath, excludePatterns) {
|
|
3910
|
+
return matchesAnyGlob(relativePath, excludePatterns);
|
|
3911
|
+
}
|
|
3912
|
+
function isExcludedDirectory(relativePath, excludePatterns) {
|
|
3913
|
+
const normalized = toPosixRelativePath(relativePath);
|
|
3914
|
+
if (matchesAnyGlob(normalized, excludePatterns)) {
|
|
3915
|
+
return true;
|
|
3916
|
+
}
|
|
3917
|
+
for (const pattern of excludePatterns) {
|
|
3918
|
+
const posixPattern = toPosixRelativePath(pattern).replace(/\/+$/, "");
|
|
3919
|
+
if (!posixPattern.endsWith("/**")) {
|
|
3920
|
+
continue;
|
|
3921
|
+
}
|
|
3922
|
+
const directoryPattern = posixPattern.slice(0, -3);
|
|
3923
|
+
if (directoryPattern && matchesAnyGlob(normalized, [directoryPattern])) {
|
|
3924
|
+
return true;
|
|
3925
|
+
}
|
|
3926
|
+
}
|
|
3927
|
+
return false;
|
|
3928
|
+
}
|
|
3032
3929
|
function matchGlob(filePath, pattern) {
|
|
3033
3930
|
if (pattern.startsWith("**/")) {
|
|
3034
3931
|
const withoutPrefix = pattern.slice(3);
|
|
@@ -3049,8 +3946,8 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
|
|
|
3049
3946
|
const filesInDir = [];
|
|
3050
3947
|
const subdirs = [];
|
|
3051
3948
|
for (const entry of entries) {
|
|
3052
|
-
const fullPath =
|
|
3053
|
-
const relativePath =
|
|
3949
|
+
const fullPath = path11.join(dir, entry.name);
|
|
3950
|
+
const relativePath = toPosixRelativePath(path11.relative(projectRoot, fullPath));
|
|
3054
3951
|
if (isHiddenPathSegment(entry.name)) {
|
|
3055
3952
|
if (entry.isDirectory()) {
|
|
3056
3953
|
skipped.push({ path: relativePath, reason: "excluded" });
|
|
@@ -3068,6 +3965,10 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
|
|
|
3068
3965
|
continue;
|
|
3069
3966
|
}
|
|
3070
3967
|
if (entry.isDirectory()) {
|
|
3968
|
+
if (isExcludedDirectory(relativePath, excludePatterns)) {
|
|
3969
|
+
skipped.push({ path: relativePath, reason: "excluded" });
|
|
3970
|
+
continue;
|
|
3971
|
+
}
|
|
3071
3972
|
subdirs.push({ fullPath, relativePath });
|
|
3072
3973
|
} else if (entry.isFile()) {
|
|
3073
3974
|
const stat2 = await import_fs6.promises.stat(fullPath);
|
|
@@ -3075,20 +3976,11 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
|
|
|
3075
3976
|
skipped.push({ path: relativePath, reason: "too_large" });
|
|
3076
3977
|
continue;
|
|
3077
3978
|
}
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
continue;
|
|
3082
|
-
}
|
|
3083
|
-
}
|
|
3084
|
-
let matched = false;
|
|
3085
|
-
for (const pattern of includePatterns) {
|
|
3086
|
-
if (matchGlob(relativePath, pattern)) {
|
|
3087
|
-
matched = true;
|
|
3088
|
-
break;
|
|
3089
|
-
}
|
|
3979
|
+
if (isExcludedByPatterns(relativePath, excludePatterns)) {
|
|
3980
|
+
skipped.push({ path: relativePath, reason: "excluded" });
|
|
3981
|
+
continue;
|
|
3090
3982
|
}
|
|
3091
|
-
if (
|
|
3983
|
+
if (matchesAnyGlob(relativePath, includePatterns)) {
|
|
3092
3984
|
filesInDir.push({ path: fullPath, size: stat2.size });
|
|
3093
3985
|
}
|
|
3094
3986
|
}
|
|
@@ -3099,7 +3991,7 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
|
|
|
3099
3991
|
yield f;
|
|
3100
3992
|
}
|
|
3101
3993
|
for (let i = options.maxFilesPerDirectory; i < filesInDir.length; i++) {
|
|
3102
|
-
skipped.push({ path:
|
|
3994
|
+
skipped.push({ path: toPosixRelativePath(path11.relative(projectRoot, filesInDir[i].path)), reason: "excluded" });
|
|
3103
3995
|
}
|
|
3104
3996
|
const canRecurse = options.maxDepth === -1 || currentDepth < options.maxDepth;
|
|
3105
3997
|
if (canRecurse) {
|
|
@@ -3139,8 +4031,8 @@ async function collectFiles(projectRoot, includePatterns, excludePatterns, maxFi
|
|
|
3139
4031
|
if (additionalRoots && additionalRoots.length > 0) {
|
|
3140
4032
|
const normalizedRoots = /* @__PURE__ */ new Set();
|
|
3141
4033
|
for (const kbRoot of additionalRoots) {
|
|
3142
|
-
const resolved =
|
|
3143
|
-
|
|
4034
|
+
const resolved = path11.normalize(
|
|
4035
|
+
path11.isAbsolute(kbRoot) ? kbRoot : path11.resolve(projectRoot, kbRoot)
|
|
3144
4036
|
);
|
|
3145
4037
|
normalizedRoots.add(resolved);
|
|
3146
4038
|
}
|
|
@@ -3181,7 +4073,7 @@ function getErrorMessage(error) {
|
|
|
3181
4073
|
return error instanceof Error ? error.message : String(error);
|
|
3182
4074
|
}
|
|
3183
4075
|
function runCommand(file, args, options) {
|
|
3184
|
-
return new Promise((
|
|
4076
|
+
return new Promise((resolve20, reject) => {
|
|
3185
4077
|
childProcess.execFile(
|
|
3186
4078
|
file,
|
|
3187
4079
|
args,
|
|
@@ -3191,7 +4083,7 @@ function runCommand(file, args, options) {
|
|
|
3191
4083
|
reject(error);
|
|
3192
4084
|
return;
|
|
3193
4085
|
}
|
|
3194
|
-
|
|
4086
|
+
resolve20(stdout);
|
|
3195
4087
|
}
|
|
3196
4088
|
);
|
|
3197
4089
|
});
|
|
@@ -3283,8 +4175,8 @@ var AutoIndexCancelledError = class extends Error {
|
|
|
3283
4175
|
function now() {
|
|
3284
4176
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
3285
4177
|
}
|
|
3286
|
-
function
|
|
3287
|
-
const resolved =
|
|
4178
|
+
function canonicalizePath2(targetPath) {
|
|
4179
|
+
const resolved = path12.resolve(targetPath);
|
|
3288
4180
|
if ((0, import_fs7.existsSync)(resolved)) {
|
|
3289
4181
|
try {
|
|
3290
4182
|
return import_fs7.realpathSync.native(resolved);
|
|
@@ -3292,20 +4184,20 @@ function canonicalizePath(targetPath) {
|
|
|
3292
4184
|
return resolved;
|
|
3293
4185
|
}
|
|
3294
4186
|
}
|
|
3295
|
-
const parent =
|
|
4187
|
+
const parent = path12.dirname(resolved);
|
|
3296
4188
|
if (parent === resolved) return resolved;
|
|
3297
|
-
return
|
|
4189
|
+
return path12.join(canonicalizePath2(parent), path12.basename(resolved));
|
|
3298
4190
|
}
|
|
3299
4191
|
function isHomeDirectory(projectRoot) {
|
|
3300
|
-
return
|
|
4192
|
+
return canonicalizePath2(projectRoot) === canonicalizePath2(os4.homedir());
|
|
3301
4193
|
}
|
|
3302
|
-
function
|
|
3303
|
-
return `${host}::${
|
|
4194
|
+
function projectLookupKey2(projectRoot, host) {
|
|
4195
|
+
return `${host}::${canonicalizePath2(projectRoot)}`;
|
|
3304
4196
|
}
|
|
3305
4197
|
function coordinatorKey(projectRoot, config, host) {
|
|
3306
|
-
const canonicalProjectRoot =
|
|
4198
|
+
const canonicalProjectRoot = canonicalizePath2(projectRoot);
|
|
3307
4199
|
const indexPath = resolveProjectIndexPath(projectRoot, config.scope, host);
|
|
3308
|
-
return `${
|
|
4200
|
+
return `${canonicalizePath2(indexPath)}::${canonicalProjectRoot}`;
|
|
3309
4201
|
}
|
|
3310
4202
|
function getProjectSafety(projectRoot, config) {
|
|
3311
4203
|
if (isHomeDirectory(projectRoot)) {
|
|
@@ -3336,10 +4228,10 @@ function safeFailureMessage(error) {
|
|
|
3336
4228
|
}
|
|
3337
4229
|
function cancellableDelay(delayMs, signal) {
|
|
3338
4230
|
if (signal.aborted) return Promise.reject(new AutoIndexCancelledError());
|
|
3339
|
-
return new Promise((
|
|
4231
|
+
return new Promise((resolve20, reject) => {
|
|
3340
4232
|
const timer = setTimeout(() => {
|
|
3341
4233
|
signal.removeEventListener("abort", onAbort);
|
|
3342
|
-
|
|
4234
|
+
resolve20();
|
|
3343
4235
|
}, delayMs);
|
|
3344
4236
|
timer.unref?.();
|
|
3345
4237
|
const onAbort = () => {
|
|
@@ -3351,18 +4243,44 @@ function cancellableDelay(delayMs, signal) {
|
|
|
3351
4243
|
}
|
|
3352
4244
|
function withTimeout(promise, timeoutMs) {
|
|
3353
4245
|
if (timeoutMs <= 0) return Promise.resolve(void 0);
|
|
3354
|
-
return new Promise((
|
|
3355
|
-
const timer = setTimeout(() =>
|
|
4246
|
+
return new Promise((resolve20) => {
|
|
4247
|
+
const timer = setTimeout(() => resolve20(void 0), timeoutMs);
|
|
3356
4248
|
timer.unref?.();
|
|
3357
4249
|
void promise.then((value) => {
|
|
3358
4250
|
clearTimeout(timer);
|
|
3359
|
-
|
|
4251
|
+
resolve20(value);
|
|
3360
4252
|
}, () => {
|
|
3361
4253
|
clearTimeout(timer);
|
|
3362
|
-
|
|
4254
|
+
resolve20(void 0);
|
|
3363
4255
|
});
|
|
3364
4256
|
});
|
|
3365
4257
|
}
|
|
4258
|
+
function settlesWithin(promise, timeoutMs) {
|
|
4259
|
+
if (timeoutMs <= 0) return Promise.resolve(false);
|
|
4260
|
+
return new Promise((resolve20) => {
|
|
4261
|
+
let settled = false;
|
|
4262
|
+
const timer = setTimeout(() => {
|
|
4263
|
+
if (settled) return;
|
|
4264
|
+
settled = true;
|
|
4265
|
+
resolve20(false);
|
|
4266
|
+
}, timeoutMs);
|
|
4267
|
+
timer.unref?.();
|
|
4268
|
+
void promise.then(
|
|
4269
|
+
() => {
|
|
4270
|
+
if (settled) return;
|
|
4271
|
+
settled = true;
|
|
4272
|
+
clearTimeout(timer);
|
|
4273
|
+
resolve20(true);
|
|
4274
|
+
},
|
|
4275
|
+
() => {
|
|
4276
|
+
if (settled) return;
|
|
4277
|
+
settled = true;
|
|
4278
|
+
clearTimeout(timer);
|
|
4279
|
+
resolve20(true);
|
|
4280
|
+
}
|
|
4281
|
+
);
|
|
4282
|
+
});
|
|
4283
|
+
}
|
|
3366
4284
|
function requestPriority(request) {
|
|
3367
4285
|
if (request.force) return 4;
|
|
3368
4286
|
if (request.source === "manual") return 3;
|
|
@@ -3373,6 +4291,7 @@ function mergeRequests(current, next) {
|
|
|
3373
4291
|
if (!current) return next;
|
|
3374
4292
|
const preferred = requestPriority(next) > requestPriority(current) ? next : current;
|
|
3375
4293
|
return {
|
|
4294
|
+
allowDisabledAutoIndex: current.allowDisabledAutoIndex || next.allowDisabledAutoIndex,
|
|
3376
4295
|
checkFreshness: current.checkFreshness && next.checkFreshness,
|
|
3377
4296
|
force: current.force || next.force,
|
|
3378
4297
|
onProgress: next.onProgress ?? current.onProgress,
|
|
@@ -3434,11 +4353,11 @@ var AutoIndexCoordinator = class {
|
|
|
3434
4353
|
progress: this.status.progress ? { ...this.status.progress } : void 0
|
|
3435
4354
|
};
|
|
3436
4355
|
}
|
|
3437
|
-
start(source) {
|
|
4356
|
+
start(source, allowDisabledAutoIndex = false) {
|
|
3438
4357
|
this.refreshSafety();
|
|
3439
|
-
if (!this.registration.config.indexing.autoIndex || !this.registration.safeToRun) return null;
|
|
4358
|
+
if (!this.registration.config.indexing.autoIndex && !allowDisabledAutoIndex || !this.registration.safeToRun) return null;
|
|
3440
4359
|
if (this.status.state === "failed") return this.inFlight;
|
|
3441
|
-
return this.request({ checkFreshness: true, force: false, source });
|
|
4360
|
+
return this.request({ allowDisabledAutoIndex, checkFreshness: true, force: false, source });
|
|
3442
4361
|
}
|
|
3443
4362
|
request(request) {
|
|
3444
4363
|
if (this.stopped) {
|
|
@@ -3513,13 +4432,15 @@ var AutoIndexCoordinator = class {
|
|
|
3513
4432
|
retryAttempt: void 0
|
|
3514
4433
|
});
|
|
3515
4434
|
const inFlight = this.inFlight;
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
|
|
4435
|
+
const completion = inFlight ? inFlight.then(() => void 0, () => void 0) : Promise.resolve();
|
|
4436
|
+
if (!inFlight) {
|
|
4437
|
+
return { completed: true, completion };
|
|
4438
|
+
}
|
|
4439
|
+
if (waitForCompletion) {
|
|
4440
|
+
await completion;
|
|
4441
|
+
return { completed: true, completion };
|
|
3522
4442
|
}
|
|
4443
|
+
return { completed: await settlesWithin(completion, SHUTDOWN_WAIT_MS), completion };
|
|
3523
4444
|
}
|
|
3524
4445
|
startRequest(request) {
|
|
3525
4446
|
if (this.stopped || !this.canRun(request)) {
|
|
@@ -3708,7 +4629,7 @@ var AutoIndexCoordinator = class {
|
|
|
3708
4629
|
if (request.source === "manual" || request.source === "watcher") {
|
|
3709
4630
|
return true;
|
|
3710
4631
|
}
|
|
3711
|
-
return this.registration.safeToRun && this.registration.config.indexing.autoIndex;
|
|
4632
|
+
return this.registration.safeToRun && (this.registration.config.indexing.autoIndex || request.allowDisabledAutoIndex === true);
|
|
3712
4633
|
}
|
|
3713
4634
|
shouldDeferForBattery(request) {
|
|
3714
4635
|
return this.registration.backgroundIndexingPolicy !== null && (request.source === "startup" || request.source === "watcher");
|
|
@@ -3741,17 +4662,17 @@ var AutoIndexCoordinator = class {
|
|
|
3741
4662
|
}
|
|
3742
4663
|
}
|
|
3743
4664
|
waitForBatteryRetry(delayMs) {
|
|
3744
|
-
return new Promise((
|
|
4665
|
+
return new Promise((resolve20) => {
|
|
3745
4666
|
const timer = setTimeout(() => {
|
|
3746
4667
|
if (this.batteryRetryTimer === timer) {
|
|
3747
4668
|
this.batteryRetryTimer = null;
|
|
3748
4669
|
this.resolveBatteryRetry = null;
|
|
3749
4670
|
}
|
|
3750
|
-
|
|
4671
|
+
resolve20();
|
|
3751
4672
|
}, delayMs);
|
|
3752
4673
|
timer.unref?.();
|
|
3753
4674
|
this.batteryRetryTimer = timer;
|
|
3754
|
-
this.resolveBatteryRetry =
|
|
4675
|
+
this.resolveBatteryRetry = resolve20;
|
|
3755
4676
|
});
|
|
3756
4677
|
}
|
|
3757
4678
|
cancelBatteryRetry() {
|
|
@@ -3759,9 +4680,9 @@ var AutoIndexCoordinator = class {
|
|
|
3759
4680
|
clearTimeout(this.batteryRetryTimer);
|
|
3760
4681
|
this.batteryRetryTimer = null;
|
|
3761
4682
|
}
|
|
3762
|
-
const
|
|
4683
|
+
const resolve20 = this.resolveBatteryRetry;
|
|
3763
4684
|
this.resolveBatteryRetry = null;
|
|
3764
|
-
|
|
4685
|
+
resolve20?.();
|
|
3765
4686
|
}
|
|
3766
4687
|
finishBatteryCheck(batteryCheck) {
|
|
3767
4688
|
if (this.batteryCheck !== batteryCheck) return;
|
|
@@ -3774,12 +4695,25 @@ var AutoIndexCoordinator = class {
|
|
|
3774
4695
|
}
|
|
3775
4696
|
};
|
|
3776
4697
|
function getCoordinator(projectRoot, host) {
|
|
3777
|
-
const key = coordinatorKeysByProject.get(
|
|
4698
|
+
const key = coordinatorKeysByProject.get(projectLookupKey2(projectRoot, host));
|
|
3778
4699
|
return key ? coordinators.get(key) ?? null : null;
|
|
3779
4700
|
}
|
|
3780
|
-
function
|
|
3781
|
-
|
|
4701
|
+
function synchronizeBackgroundWorker(projectRoot, host, config, safeToRun) {
|
|
4702
|
+
if (safeToRun) {
|
|
4703
|
+
updateBackgroundWorkerConfig(projectRoot, host, config);
|
|
4704
|
+
return;
|
|
4705
|
+
}
|
|
4706
|
+
void stopBackgroundWorker(projectRoot, host).catch((error) => {
|
|
4707
|
+
console.error("[codebase-index] Failed to stop background worker after project safety changed:", error);
|
|
4708
|
+
});
|
|
4709
|
+
}
|
|
4710
|
+
function configureAutoIndex(projectRoot, host, config, getIndexer, options = {}) {
|
|
4711
|
+
const projectKey = projectLookupKey2(projectRoot, host);
|
|
3782
4712
|
const safety = getProjectSafety(projectRoot, config);
|
|
4713
|
+
const synchronizeWorker = options.synchronizeBackgroundWorker ?? true;
|
|
4714
|
+
if (options.preserveManagedWorker === true && isBackgroundWorkerManaged(projectRoot, host)) {
|
|
4715
|
+
return;
|
|
4716
|
+
}
|
|
3783
4717
|
const registration = {
|
|
3784
4718
|
backgroundIndexingPolicy: createBackgroundIndexingPolicy(
|
|
3785
4719
|
config.indexing.pauseBackgroundIndexingOnBattery
|
|
@@ -3797,6 +4731,9 @@ function configureAutoIndex(projectRoot, host, config, getIndexer) {
|
|
|
3797
4731
|
const stopPrevious = previousCoordinator?.stop(true) ?? Promise.resolve();
|
|
3798
4732
|
const activation = Promise.all([previousBarrier, stopPrevious]).then(() => void 0);
|
|
3799
4733
|
coordinatorReplacementBarriers.set(projectKey, activation);
|
|
4734
|
+
if (synchronizeWorker) {
|
|
4735
|
+
synchronizeBackgroundWorker(projectRoot, host, config, safety.safeToRun);
|
|
4736
|
+
}
|
|
3800
4737
|
coordinators.delete(previousKey);
|
|
3801
4738
|
const coordinator2 = new AutoIndexCoordinator(registration);
|
|
3802
4739
|
coordinator2.activateAfter(activation);
|
|
@@ -3812,6 +4749,9 @@ function configureAutoIndex(projectRoot, host, config, getIndexer) {
|
|
|
3812
4749
|
coordinator.update(registration);
|
|
3813
4750
|
}
|
|
3814
4751
|
coordinatorKeysByProject.set(projectKey, key);
|
|
4752
|
+
if (synchronizeWorker) {
|
|
4753
|
+
synchronizeBackgroundWorker(projectRoot, host, config, safety.safeToRun);
|
|
4754
|
+
}
|
|
3815
4755
|
}
|
|
3816
4756
|
function runCoordinatedIndex(projectRoot, host, force, onProgress) {
|
|
3817
4757
|
return getCoordinator(projectRoot, host)?.request({
|
|
@@ -3846,15 +4786,23 @@ async function waitForAutoIndexForRetrieval(projectRoot, host) {
|
|
|
3846
4786
|
};
|
|
3847
4787
|
}
|
|
3848
4788
|
try {
|
|
3849
|
-
|
|
4789
|
+
const readiness = await getSearchReadiness(coordinator);
|
|
4790
|
+
if (readiness.searchable) {
|
|
4791
|
+
return { ready: true };
|
|
4792
|
+
}
|
|
4793
|
+
if (readiness.blocked) return unavailableSnapshotResult(readiness.reason);
|
|
3850
4794
|
} catch {
|
|
3851
4795
|
}
|
|
3852
|
-
const job =
|
|
4796
|
+
const job = startRetrievalRefresh(projectRoot, host, coordinator);
|
|
3853
4797
|
if (job) {
|
|
3854
4798
|
await withTimeout(job, coordinator.getWaitMs());
|
|
4799
|
+
} else if (isBackgroundWorkerManaged(projectRoot, host)) {
|
|
4800
|
+
await waitForPublishedSnapshot(coordinator, coordinator.getWaitMs());
|
|
3855
4801
|
}
|
|
3856
4802
|
try {
|
|
3857
|
-
|
|
4803
|
+
const readiness = await getSearchReadiness(coordinator);
|
|
4804
|
+
if (readiness.searchable) return { ready: true };
|
|
4805
|
+
if (readiness.blocked) return unavailableSnapshotResult(readiness.reason);
|
|
3858
4806
|
} catch {
|
|
3859
4807
|
}
|
|
3860
4808
|
const status = coordinator.snapshot();
|
|
@@ -3875,18 +4823,45 @@ async function waitForAutoIndexForRetrieval(projectRoot, host) {
|
|
|
3875
4823
|
text: `Automatic indexing is ${status.state}. Retry shortly or call index_status for progress. You can also run index_codebase explicitly.`
|
|
3876
4824
|
};
|
|
3877
4825
|
}
|
|
3878
|
-
async function
|
|
4826
|
+
async function getSearchReadiness(coordinator) {
|
|
3879
4827
|
const indexer = coordinator.getIndexer();
|
|
3880
4828
|
if (indexer.getIndexFreshness) {
|
|
3881
4829
|
const freshness = await indexer.getIndexFreshness();
|
|
3882
|
-
|
|
4830
|
+
const searchable = freshness.readable && freshness.current && freshness.reason === "current";
|
|
4831
|
+
return {
|
|
4832
|
+
blocked: freshness.reason === "unreadable" || freshness.reason === "incompatible" || freshness.reason === "failed-batches" || freshness.reason === "migration-required",
|
|
4833
|
+
reason: freshness.reason,
|
|
4834
|
+
searchable
|
|
4835
|
+
};
|
|
4836
|
+
}
|
|
4837
|
+
const indexed = (await indexer.getStatus()).indexed;
|
|
4838
|
+
return { blocked: false, searchable: indexed };
|
|
4839
|
+
}
|
|
4840
|
+
function unavailableSnapshotResult(reason) {
|
|
4841
|
+
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.";
|
|
4842
|
+
return {
|
|
4843
|
+
ready: false,
|
|
4844
|
+
text: `${detail} Run index_codebase before retrying retrieval.`
|
|
4845
|
+
};
|
|
4846
|
+
}
|
|
4847
|
+
function startRetrievalRefresh(projectRoot, host, coordinator) {
|
|
4848
|
+
if (isBackgroundWorkerManaged(projectRoot, host)) {
|
|
4849
|
+
requestBackgroundWorkerRefresh(projectRoot, host, true);
|
|
4850
|
+
return isBackgroundWorkerLeader(projectRoot, host) ? coordinator.currentJob() : null;
|
|
4851
|
+
}
|
|
4852
|
+
return coordinator.start("retrieval") ?? coordinator.currentJob();
|
|
4853
|
+
}
|
|
4854
|
+
async function waitForPublishedSnapshot(coordinator, waitMs) {
|
|
4855
|
+
const deadline = Date.now() + waitMs;
|
|
4856
|
+
while (Date.now() < deadline) {
|
|
4857
|
+
if ((await getSearchReadiness(coordinator)).searchable) return;
|
|
4858
|
+
await new Promise((resolve20) => setTimeout(resolve20, Math.min(250, deadline - Date.now())));
|
|
3883
4859
|
}
|
|
3884
|
-
return (await indexer.getStatus()).indexed;
|
|
3885
4860
|
}
|
|
3886
4861
|
|
|
3887
4862
|
// src/tools/config-state.ts
|
|
3888
4863
|
var import_fs8 = require("fs");
|
|
3889
|
-
var
|
|
4864
|
+
var path13 = __toESM(require("path"), 1);
|
|
3890
4865
|
function normalizeKnowledgeBasePaths(config, projectRoot) {
|
|
3891
4866
|
const normalized = { ...config };
|
|
3892
4867
|
if (Array.isArray(normalized.knowledgeBases)) {
|
|
@@ -3908,7 +4883,7 @@ function loadRuntimeConfig(projectRoot, host) {
|
|
|
3908
4883
|
|
|
3909
4884
|
// src/indexer/index.ts
|
|
3910
4885
|
var import_fs12 = require("fs");
|
|
3911
|
-
var
|
|
4886
|
+
var path20 = __toESM(require("path"), 1);
|
|
3912
4887
|
var import_perf_hooks = require("perf_hooks");
|
|
3913
4888
|
var import_child_process4 = require("child_process");
|
|
3914
4889
|
var import_util4 = require("util");
|
|
@@ -3935,7 +4910,7 @@ function pTimeout(promise, options) {
|
|
|
3935
4910
|
} = options;
|
|
3936
4911
|
let timer;
|
|
3937
4912
|
let abortHandler;
|
|
3938
|
-
const wrappedPromise = new Promise((
|
|
4913
|
+
const wrappedPromise = new Promise((resolve20, reject) => {
|
|
3939
4914
|
if (typeof milliseconds !== "number" || Math.sign(milliseconds) !== 1) {
|
|
3940
4915
|
throw new TypeError(`Expected \`milliseconds\` to be a positive number, got \`${milliseconds}\``);
|
|
3941
4916
|
}
|
|
@@ -3949,7 +4924,7 @@ function pTimeout(promise, options) {
|
|
|
3949
4924
|
};
|
|
3950
4925
|
signal.addEventListener("abort", abortHandler, { once: true });
|
|
3951
4926
|
}
|
|
3952
|
-
promise.then(
|
|
4927
|
+
promise.then(resolve20, reject);
|
|
3953
4928
|
if (milliseconds === Number.POSITIVE_INFINITY) {
|
|
3954
4929
|
return;
|
|
3955
4930
|
}
|
|
@@ -3957,7 +4932,7 @@ function pTimeout(promise, options) {
|
|
|
3957
4932
|
timer = customTimers.setTimeout.call(void 0, () => {
|
|
3958
4933
|
if (fallback) {
|
|
3959
4934
|
try {
|
|
3960
|
-
|
|
4935
|
+
resolve20(fallback());
|
|
3961
4936
|
} catch (error) {
|
|
3962
4937
|
reject(error);
|
|
3963
4938
|
}
|
|
@@ -3967,7 +4942,7 @@ function pTimeout(promise, options) {
|
|
|
3967
4942
|
promise.cancel();
|
|
3968
4943
|
}
|
|
3969
4944
|
if (message === false) {
|
|
3970
|
-
|
|
4945
|
+
resolve20();
|
|
3971
4946
|
} else if (message instanceof Error) {
|
|
3972
4947
|
reject(message);
|
|
3973
4948
|
} else {
|
|
@@ -4369,7 +5344,7 @@ var PQueue = class extends import_index.default {
|
|
|
4369
5344
|
// Assign unique ID if not provided
|
|
4370
5345
|
id: options.id ?? (this.#idAssigner++).toString()
|
|
4371
5346
|
};
|
|
4372
|
-
return new Promise((
|
|
5347
|
+
return new Promise((resolve20, reject) => {
|
|
4373
5348
|
const taskSymbol = /* @__PURE__ */ Symbol(`task-${options.id}`);
|
|
4374
5349
|
let cleanupQueueAbortHandler = () => void 0;
|
|
4375
5350
|
const run = async () => {
|
|
@@ -4409,7 +5384,7 @@ var PQueue = class extends import_index.default {
|
|
|
4409
5384
|
})]);
|
|
4410
5385
|
}
|
|
4411
5386
|
const result = await operation;
|
|
4412
|
-
|
|
5387
|
+
resolve20(result);
|
|
4413
5388
|
this.emit("completed", result);
|
|
4414
5389
|
} catch (error) {
|
|
4415
5390
|
reject(error);
|
|
@@ -4597,13 +5572,13 @@ var PQueue = class extends import_index.default {
|
|
|
4597
5572
|
});
|
|
4598
5573
|
}
|
|
4599
5574
|
async #onEvent(event, filter) {
|
|
4600
|
-
return new Promise((
|
|
5575
|
+
return new Promise((resolve20) => {
|
|
4601
5576
|
const listener = () => {
|
|
4602
5577
|
if (filter && !filter()) {
|
|
4603
5578
|
return;
|
|
4604
5579
|
}
|
|
4605
5580
|
this.off(event, listener);
|
|
4606
|
-
|
|
5581
|
+
resolve20();
|
|
4607
5582
|
};
|
|
4608
5583
|
this.on(event, listener);
|
|
4609
5584
|
});
|
|
@@ -4889,7 +5864,7 @@ async function onAttemptFailure({ error, attemptNumber, retriesConsumed, startTi
|
|
|
4889
5864
|
const finalDelay = Math.min(delayTime, remainingTime);
|
|
4890
5865
|
options.signal?.throwIfAborted();
|
|
4891
5866
|
if (finalDelay > 0) {
|
|
4892
|
-
await new Promise((
|
|
5867
|
+
await new Promise((resolve20, reject) => {
|
|
4893
5868
|
const onAbort = () => {
|
|
4894
5869
|
clearTimeout(timeoutToken);
|
|
4895
5870
|
options.signal?.removeEventListener("abort", onAbort);
|
|
@@ -4897,7 +5872,7 @@ async function onAttemptFailure({ error, attemptNumber, retriesConsumed, startTi
|
|
|
4897
5872
|
};
|
|
4898
5873
|
const timeoutToken = setTimeout(() => {
|
|
4899
5874
|
options.signal?.removeEventListener("abort", onAbort);
|
|
4900
|
-
|
|
5875
|
+
resolve20();
|
|
4901
5876
|
}, finalDelay);
|
|
4902
5877
|
if (options.unref) {
|
|
4903
5878
|
timeoutToken.unref?.();
|
|
@@ -4959,10 +5934,10 @@ async function pRetry(input, options = {}) {
|
|
|
4959
5934
|
|
|
4960
5935
|
// src/embeddings/detector.ts
|
|
4961
5936
|
var import_fs9 = require("fs");
|
|
4962
|
-
var
|
|
4963
|
-
var
|
|
5937
|
+
var path14 = __toESM(require("path"), 1);
|
|
5938
|
+
var os5 = __toESM(require("os"), 1);
|
|
4964
5939
|
function getOpenCodeAuthPath() {
|
|
4965
|
-
return
|
|
5940
|
+
return path14.join(os5.homedir(), ".local", "share", "opencode", "auth.json");
|
|
4966
5941
|
}
|
|
4967
5942
|
function loadOpenCodeAuth() {
|
|
4968
5943
|
const authPath = getOpenCodeAuthPath();
|
|
@@ -5259,17 +6234,17 @@ function validateExternalUrl(urlString) {
|
|
|
5259
6234
|
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
5260
6235
|
return { valid: false, reason: `Blocked protocol: ${parsed.protocol}` };
|
|
5261
6236
|
}
|
|
5262
|
-
const
|
|
5263
|
-
if (BLOCKED_HOSTNAMES.has(
|
|
5264
|
-
return { valid: false, reason: `Blocked: cloud metadata service (${
|
|
6237
|
+
const hostname3 = parsed.hostname.toLowerCase();
|
|
6238
|
+
if (BLOCKED_HOSTNAMES.has(hostname3)) {
|
|
6239
|
+
return { valid: false, reason: `Blocked: cloud metadata service (${hostname3})` };
|
|
5265
6240
|
}
|
|
5266
6241
|
for (const pattern of BLOCKED_METADATA_IPS) {
|
|
5267
|
-
if (pattern.test(
|
|
5268
|
-
return { valid: false, reason: `Blocked: cloud metadata IP (${
|
|
6242
|
+
if (pattern.test(hostname3)) {
|
|
6243
|
+
return { valid: false, reason: `Blocked: cloud metadata IP (${hostname3})` };
|
|
5269
6244
|
}
|
|
5270
6245
|
}
|
|
5271
|
-
if (/^169\.254\./.test(
|
|
5272
|
-
return { valid: false, reason: `Blocked: link-local address (${
|
|
6246
|
+
if (/^169\.254\./.test(hostname3)) {
|
|
6247
|
+
return { valid: false, reason: `Blocked: link-local address (${hostname3})` };
|
|
5273
6248
|
}
|
|
5274
6249
|
return { valid: true };
|
|
5275
6250
|
}
|
|
@@ -6361,8 +7336,8 @@ function extractParamNames(params) {
|
|
|
6361
7336
|
}
|
|
6362
7337
|
|
|
6363
7338
|
// src/native/binding.ts
|
|
6364
|
-
var
|
|
6365
|
-
var
|
|
7339
|
+
var os6 = __toESM(require("os"), 1);
|
|
7340
|
+
var path15 = __toESM(require("path"), 1);
|
|
6366
7341
|
var module2 = __toESM(require("module"), 1);
|
|
6367
7342
|
var import_node_url = require("url");
|
|
6368
7343
|
|
|
@@ -6399,7 +7374,7 @@ var STABLE_NATIVE_BINARY_NAME = IDENTITY_CATALOG.native.binaryName;
|
|
|
6399
7374
|
|
|
6400
7375
|
// src/native/binding.ts
|
|
6401
7376
|
var import_meta = {};
|
|
6402
|
-
function getNativeBindingFilename(platform2 =
|
|
7377
|
+
function getNativeBindingFilename(platform2 = os6.platform(), arch2 = os6.arch()) {
|
|
6403
7378
|
if (platform2 === "darwin" && arch2 === "arm64") {
|
|
6404
7379
|
return `${STABLE_NATIVE_BINARY_NAME}.darwin-arm64.node`;
|
|
6405
7380
|
}
|
|
@@ -6417,25 +7392,25 @@ function getNativeBindingFilename(platform2 = os5.platform(), arch2 = os5.arch()
|
|
|
6417
7392
|
}
|
|
6418
7393
|
throw new Error(`Unsupported platform: ${platform2}-${arch2}`);
|
|
6419
7394
|
}
|
|
6420
|
-
function resolveNativeBindingPath(packageRoot, platform2 =
|
|
6421
|
-
return
|
|
7395
|
+
function resolveNativeBindingPath(packageRoot, platform2 = os6.platform(), arch2 = os6.arch()) {
|
|
7396
|
+
return path15.join(packageRoot, "native", getNativeBindingFilename(platform2, arch2));
|
|
6422
7397
|
}
|
|
6423
7398
|
function getNativeBinding() {
|
|
6424
7399
|
let currentDir;
|
|
6425
7400
|
let requireTarget;
|
|
6426
7401
|
if (typeof import_meta !== "undefined" && import_meta.url) {
|
|
6427
|
-
currentDir =
|
|
7402
|
+
currentDir = path15.dirname((0, import_node_url.fileURLToPath)(import_meta.url));
|
|
6428
7403
|
requireTarget = import_meta.url;
|
|
6429
7404
|
} else if (typeof __dirname !== "undefined") {
|
|
6430
7405
|
currentDir = __dirname;
|
|
6431
7406
|
requireTarget = __filename;
|
|
6432
7407
|
} else {
|
|
6433
7408
|
currentDir = process.cwd();
|
|
6434
|
-
requireTarget =
|
|
7409
|
+
requireTarget = path15.join(currentDir, "index.js");
|
|
6435
7410
|
}
|
|
6436
7411
|
const normalizedDir = currentDir.replace(/\\/g, "/");
|
|
6437
|
-
const isDevMode = normalizedDir.includes("/src/native") || currentDir.includes(
|
|
6438
|
-
const packageRoot = isDevMode ?
|
|
7412
|
+
const isDevMode = normalizedDir.includes("/src/native") || currentDir.includes(path15.join("src", "native"));
|
|
7413
|
+
const packageRoot = isDevMode ? path15.resolve(currentDir, "../..") : path15.resolve(currentDir, "..");
|
|
6439
7414
|
const nativePath = resolveNativeBindingPath(packageRoot);
|
|
6440
7415
|
const require2 = module2.createRequire(requireTarget);
|
|
6441
7416
|
return require2(nativePath);
|
|
@@ -7019,8 +7994,8 @@ var Database = class _Database {
|
|
|
7019
7994
|
|
|
7020
7995
|
// src/git/branch-materialization.ts
|
|
7021
7996
|
var import_fs10 = require("fs");
|
|
7022
|
-
var
|
|
7023
|
-
var
|
|
7997
|
+
var os7 = __toESM(require("os"), 1);
|
|
7998
|
+
var path16 = __toESM(require("path"), 1);
|
|
7024
7999
|
|
|
7025
8000
|
// src/git/branch-resolution.ts
|
|
7026
8001
|
var import_child_process = require("child_process");
|
|
@@ -7339,13 +8314,13 @@ async function isWorktreeRegistered(projectRoot, worktreePath) {
|
|
|
7339
8314
|
return false;
|
|
7340
8315
|
}
|
|
7341
8316
|
function isPathWithinRoot(filePath, rootPath) {
|
|
7342
|
-
const relative12 =
|
|
7343
|
-
return relative12 === "" || !relative12.startsWith(`..${
|
|
8317
|
+
const relative12 = path16.relative(path16.resolve(rootPath), path16.resolve(filePath));
|
|
8318
|
+
return relative12 === "" || !relative12.startsWith(`..${path16.sep}`) && relative12 !== ".." && !path16.isAbsolute(relative12);
|
|
7344
8319
|
}
|
|
7345
8320
|
async function pruneExactMissingWorktreeRegistration(projectRoot, worktreePath) {
|
|
7346
8321
|
if (await pathExists(worktreePath)) return false;
|
|
7347
8322
|
const commonDir = await runGit(projectRoot, ["rev-parse", "--path-format=absolute", "--git-common-dir"]);
|
|
7348
|
-
const registrationsRoot =
|
|
8323
|
+
const registrationsRoot = path16.join(commonDir, "worktrees");
|
|
7349
8324
|
let entries;
|
|
7350
8325
|
try {
|
|
7351
8326
|
entries = await import_fs10.promises.readdir(registrationsRoot, { withFileTypes: true });
|
|
@@ -7356,16 +8331,16 @@ async function pruneExactMissingWorktreeRegistration(projectRoot, worktreePath)
|
|
|
7356
8331
|
const target = canonicalizePathForComparison(worktreePath);
|
|
7357
8332
|
for (const entry of entries) {
|
|
7358
8333
|
if (!entry.isDirectory()) continue;
|
|
7359
|
-
const registrationPath =
|
|
8334
|
+
const registrationPath = path16.join(registrationsRoot, entry.name);
|
|
7360
8335
|
if (!isPathWithinRoot(registrationPath, registrationsRoot)) continue;
|
|
7361
8336
|
let gitdirPath;
|
|
7362
8337
|
try {
|
|
7363
|
-
gitdirPath = (await import_fs10.promises.readFile(
|
|
8338
|
+
gitdirPath = (await import_fs10.promises.readFile(path16.join(registrationPath, "gitdir"), "utf8")).trim();
|
|
7364
8339
|
} catch {
|
|
7365
8340
|
continue;
|
|
7366
8341
|
}
|
|
7367
|
-
const resolvedGitdirPath =
|
|
7368
|
-
if (canonicalizePathForComparison(
|
|
8342
|
+
const resolvedGitdirPath = path16.isAbsolute(gitdirPath) ? gitdirPath : path16.resolve(registrationPath, gitdirPath);
|
|
8343
|
+
if (canonicalizePathForComparison(path16.dirname(resolvedGitdirPath)) !== target) continue;
|
|
7369
8344
|
await import_fs10.promises.rm(registrationPath, { recursive: true, force: true });
|
|
7370
8345
|
return true;
|
|
7371
8346
|
}
|
|
@@ -7383,7 +8358,7 @@ async function removeWorktree(projectRoot, worktreePath) {
|
|
|
7383
8358
|
registered = await isWorktreeRegistered(projectRoot, worktreePath);
|
|
7384
8359
|
} catch (error) {
|
|
7385
8360
|
errors.push(asError(error));
|
|
7386
|
-
throw new AggregateError(errors, `Could not verify temporary worktree deregistration; preserved ${
|
|
8361
|
+
throw new AggregateError(errors, `Could not verify temporary worktree deregistration; preserved ${path16.dirname(worktreePath)}`);
|
|
7387
8362
|
}
|
|
7388
8363
|
if (registered) {
|
|
7389
8364
|
try {
|
|
@@ -7399,7 +8374,7 @@ async function removeWorktree(projectRoot, worktreePath) {
|
|
|
7399
8374
|
registered = await isWorktreeRegistered(projectRoot, worktreePath);
|
|
7400
8375
|
} catch (error) {
|
|
7401
8376
|
errors.push(asError(error));
|
|
7402
|
-
throw new AggregateError(errors, `Could not verify temporary worktree deregistration; preserved ${
|
|
8377
|
+
throw new AggregateError(errors, `Could not verify temporary worktree deregistration; preserved ${path16.dirname(worktreePath)}`);
|
|
7403
8378
|
}
|
|
7404
8379
|
}
|
|
7405
8380
|
if (registered && !await pathExists(worktreePath)) {
|
|
@@ -7412,13 +8387,13 @@ async function removeWorktree(projectRoot, worktreePath) {
|
|
|
7412
8387
|
}
|
|
7413
8388
|
if (registered) {
|
|
7414
8389
|
errors.push(new Error(`Temporary worktree remains registered: ${worktreePath}`));
|
|
7415
|
-
throw new AggregateError(errors, `Failed to deregister temporary worktree; preserved ${
|
|
8390
|
+
throw new AggregateError(errors, `Failed to deregister temporary worktree; preserved ${path16.dirname(worktreePath)}`);
|
|
7416
8391
|
}
|
|
7417
8392
|
try {
|
|
7418
|
-
await import_fs10.promises.rm(
|
|
8393
|
+
await import_fs10.promises.rm(path16.dirname(worktreePath), { recursive: true, force: true });
|
|
7419
8394
|
} catch (error) {
|
|
7420
8395
|
errors.push(asError(error));
|
|
7421
|
-
throw new AggregateError(errors, `Deregistered the temporary worktree but could not remove ${
|
|
8396
|
+
throw new AggregateError(errors, `Deregistered the temporary worktree but could not remove ${path16.dirname(worktreePath)}`);
|
|
7422
8397
|
}
|
|
7423
8398
|
}
|
|
7424
8399
|
async function cleanupTemporaryWorktree(projectRoot, worktreePath, temporaryRoot) {
|
|
@@ -7454,9 +8429,9 @@ async function withMaterializedBranch(request, callback) {
|
|
|
7454
8429
|
`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.`
|
|
7455
8430
|
);
|
|
7456
8431
|
}
|
|
7457
|
-
const temporaryRoot = await import_fs10.promises.mkdtemp(
|
|
7458
|
-
const worktreePath =
|
|
7459
|
-
const hooksPath =
|
|
8432
|
+
const temporaryRoot = await import_fs10.promises.mkdtemp(path16.join(os7.tmpdir(), "codebase-index-branch-"));
|
|
8433
|
+
const worktreePath = path16.join(temporaryRoot, "worktree");
|
|
8434
|
+
const hooksPath = path16.join(temporaryRoot, "hooks");
|
|
7460
8435
|
await import_fs10.promises.mkdir(hooksPath);
|
|
7461
8436
|
const info = {
|
|
7462
8437
|
branch: request.branch,
|
|
@@ -7508,7 +8483,7 @@ async function withMaterializedBranch(request, callback) {
|
|
|
7508
8483
|
// src/tools/changed-files.ts
|
|
7509
8484
|
var import_child_process2 = require("child_process");
|
|
7510
8485
|
var import_fs11 = require("fs");
|
|
7511
|
-
var
|
|
8486
|
+
var path17 = __toESM(require("path"), 1);
|
|
7512
8487
|
var import_util2 = require("util");
|
|
7513
8488
|
var execFileAsync2 = (0, import_util2.promisify)(import_child_process2.execFile);
|
|
7514
8489
|
var GH_PR_VIEW_FIELDS = [
|
|
@@ -7650,7 +8625,7 @@ function getHeadRepositoryIdentity(data, host) {
|
|
|
7650
8625
|
return `${host}/${owner.toLowerCase()}/${repository.replace(/\.git$/i, "").toLowerCase()}`;
|
|
7651
8626
|
}
|
|
7652
8627
|
function getLocalRepositoryIdentity(projectRoot) {
|
|
7653
|
-
let canonicalRoot =
|
|
8628
|
+
let canonicalRoot = path17.resolve(projectRoot);
|
|
7654
8629
|
try {
|
|
7655
8630
|
canonicalRoot = import_fs11.realpathSync.native(canonicalRoot);
|
|
7656
8631
|
} catch {
|
|
@@ -7711,17 +8686,17 @@ async function getMergeBase(projectRoot, baseCommit, headCommit) {
|
|
|
7711
8686
|
return commit;
|
|
7712
8687
|
}
|
|
7713
8688
|
function normalizeFiles(rawFiles, projectRoot) {
|
|
7714
|
-
const root =
|
|
8689
|
+
const root = path17.resolve(projectRoot);
|
|
7715
8690
|
const seen = /* @__PURE__ */ new Set();
|
|
7716
8691
|
const result = [];
|
|
7717
8692
|
for (const raw of rawFiles) {
|
|
7718
8693
|
if (raw.length === 0) continue;
|
|
7719
|
-
const absolute =
|
|
7720
|
-
const relative12 =
|
|
7721
|
-
if (
|
|
8694
|
+
const absolute = path17.resolve(root, raw);
|
|
8695
|
+
const relative12 = path17.relative(root, absolute);
|
|
8696
|
+
if (path17.isAbsolute(raw) || relative12 === ".." || relative12.startsWith(`..${path17.sep}`) || path17.isAbsolute(relative12)) {
|
|
7722
8697
|
throw new Error(`Changed file escapes the project root: ${JSON.stringify(raw)}`);
|
|
7723
8698
|
}
|
|
7724
|
-
const cleaned = relative12.startsWith(`.${
|
|
8699
|
+
const cleaned = relative12.startsWith(`.${path17.sep}`) ? relative12.slice(2) : relative12;
|
|
7725
8700
|
if (!seen.has(cleaned)) {
|
|
7726
8701
|
seen.add(cleaned);
|
|
7727
8702
|
result.push(cleaned);
|
|
@@ -7732,7 +8707,7 @@ function normalizeFiles(rawFiles, projectRoot) {
|
|
|
7732
8707
|
|
|
7733
8708
|
// src/indexer/git-blame.ts
|
|
7734
8709
|
var import_child_process3 = require("child_process");
|
|
7735
|
-
var
|
|
8710
|
+
var path18 = __toESM(require("path"), 1);
|
|
7736
8711
|
var import_util3 = require("util");
|
|
7737
8712
|
var execFileAsync3 = (0, import_util3.promisify)(import_child_process3.execFile);
|
|
7738
8713
|
function parseGitBlamePorcelain(output) {
|
|
@@ -7770,7 +8745,7 @@ function parseGitBlamePorcelain(output) {
|
|
|
7770
8745
|
return Array.from(commits.values()).filter((commit) => commit.lines > 0).sort((a, b) => b.lines - a.lines || b.committedAt - a.committedAt)[0];
|
|
7771
8746
|
}
|
|
7772
8747
|
async function getChunkGitBlame(projectRoot, filePath, startLine, endLine) {
|
|
7773
|
-
const relativePath =
|
|
8748
|
+
const relativePath = path18.relative(projectRoot, filePath);
|
|
7774
8749
|
try {
|
|
7775
8750
|
const { stdout } = await execFileAsync3(
|
|
7776
8751
|
"git",
|
|
@@ -8349,8 +9324,8 @@ function pathSegmentsForAffinityMatch(filePath) {
|
|
|
8349
9324
|
if (segments.length === 0) {
|
|
8350
9325
|
return [];
|
|
8351
9326
|
}
|
|
8352
|
-
const
|
|
8353
|
-
const basenameWithoutExt =
|
|
9327
|
+
const basename7 = segments[segments.length - 1] ?? "";
|
|
9328
|
+
const basenameWithoutExt = basename7.replace(/\.[^/.]+$/u, "");
|
|
8354
9329
|
const normalizedSegments = segments.map((segment) => segment.toLowerCase());
|
|
8355
9330
|
return Array.from(/* @__PURE__ */ new Set([
|
|
8356
9331
|
...normalizedSegments,
|
|
@@ -8659,8 +9634,8 @@ function hasAllEmbeddingParts(parts, expectedPartCount) {
|
|
|
8659
9634
|
|
|
8660
9635
|
// src/indexer/failed-state-persistence.ts
|
|
8661
9636
|
var fs2 = __toESM(require("fs"), 1);
|
|
8662
|
-
var
|
|
8663
|
-
var
|
|
9637
|
+
var import_node_crypto2 = require("crypto");
|
|
9638
|
+
var path19 = __toESM(require("path"), 1);
|
|
8664
9639
|
var import_node_string_decoder = require("string_decoder");
|
|
8665
9640
|
var CURRENT_FAILED_BATCH_VERSION = 1;
|
|
8666
9641
|
var DEFAULT_MALFORMED_LINE_ACTION = "skip";
|
|
@@ -8678,7 +9653,7 @@ function* readFailedBatchRecords(filePath, options = {}) {
|
|
|
8678
9653
|
function createFailedBatchWriter(targetPath) {
|
|
8679
9654
|
const temporaryPath = createTemporaryPath(targetPath);
|
|
8680
9655
|
let finalized = false;
|
|
8681
|
-
fs2.mkdirSync(
|
|
9656
|
+
fs2.mkdirSync(path19.dirname(targetPath), { recursive: true });
|
|
8682
9657
|
fs2.closeSync(fs2.openSync(temporaryPath, "w"));
|
|
8683
9658
|
const write = (record) => {
|
|
8684
9659
|
if (finalized) {
|
|
@@ -8697,7 +9672,7 @@ function createFailedBatchWriter(targetPath) {
|
|
|
8697
9672
|
if (lines.length === 0) {
|
|
8698
9673
|
return;
|
|
8699
9674
|
}
|
|
8700
|
-
fs2.mkdirSync(
|
|
9675
|
+
fs2.mkdirSync(path19.dirname(targetPath), { recursive: true });
|
|
8701
9676
|
fs2.appendFileSync(temporaryPath, `${lines.join("\n")}
|
|
8702
9677
|
`, "utf-8");
|
|
8703
9678
|
};
|
|
@@ -8705,7 +9680,7 @@ function createFailedBatchWriter(targetPath) {
|
|
|
8705
9680
|
if (finalized) {
|
|
8706
9681
|
return;
|
|
8707
9682
|
}
|
|
8708
|
-
fs2.mkdirSync(
|
|
9683
|
+
fs2.mkdirSync(path19.dirname(targetPath), { recursive: true });
|
|
8709
9684
|
fs2.renameSync(temporaryPath, targetPath);
|
|
8710
9685
|
finalized = true;
|
|
8711
9686
|
};
|
|
@@ -8851,10 +9826,10 @@ function stripLeadingBomAndWhitespace(value) {
|
|
|
8851
9826
|
return result;
|
|
8852
9827
|
}
|
|
8853
9828
|
function createTemporaryPath(targetPath) {
|
|
8854
|
-
const randomId = (0,
|
|
8855
|
-
const targetDir =
|
|
8856
|
-
const baseName =
|
|
8857
|
-
return
|
|
9829
|
+
const randomId = (0, import_node_crypto2.createHash)("sha1").update(`${Date.now()}:${(0, import_node_crypto2.randomBytes)(8).toString("hex")}`).digest("hex");
|
|
9830
|
+
const targetDir = path19.dirname(targetPath);
|
|
9831
|
+
const baseName = path19.basename(targetPath);
|
|
9832
|
+
return path19.join(targetDir, `.${baseName}.${randomId}.tmp`);
|
|
8858
9833
|
}
|
|
8859
9834
|
function handleMalformedLine(filePath, lineNumber, line, error, options) {
|
|
8860
9835
|
const action = options.malformedLineAction ?? DEFAULT_MALFORMED_LINE_ACTION;
|
|
@@ -9100,9 +10075,9 @@ var SWIFT_PARSER_VERSION = "1";
|
|
|
9100
10075
|
var METAL_PARSER_VERSION = "1";
|
|
9101
10076
|
var SYMBOL_EXTRACTOR_VERSION = "1";
|
|
9102
10077
|
function isPathWithinRoot2(filePath, rootPath) {
|
|
9103
|
-
const normalizedFilePath =
|
|
9104
|
-
const normalizedRoot =
|
|
9105
|
-
return normalizedFilePath === normalizedRoot || normalizedFilePath.startsWith(`${normalizedRoot}${
|
|
10078
|
+
const normalizedFilePath = path20.resolve(filePath);
|
|
10079
|
+
const normalizedRoot = path20.resolve(rootPath);
|
|
10080
|
+
return normalizedFilePath === normalizedRoot || normalizedFilePath.startsWith(`${normalizedRoot}${path20.sep}`);
|
|
9106
10081
|
}
|
|
9107
10082
|
function promoteIdentifierMatches(query, combined, semanticCandidates, keywordCandidates, database, branchChunkIds, prioritizeSourcePaths = classifyQueryIntentRaw(query) === "source") {
|
|
9108
10083
|
if (combined.length === 0) {
|
|
@@ -9433,10 +10408,10 @@ function matchesHardSearchFilters(candidate, options, projectRoot) {
|
|
|
9433
10408
|
}
|
|
9434
10409
|
if (options?.directory) {
|
|
9435
10410
|
const candidatePath = canonicalizePathForComparison(
|
|
9436
|
-
|
|
10411
|
+
path20.resolve(projectRoot, candidate.metadata.filePath.replace(/\\/g, path20.sep))
|
|
9437
10412
|
);
|
|
9438
10413
|
const directoryPath = canonicalizePathForComparison(
|
|
9439
|
-
|
|
10414
|
+
path20.resolve(projectRoot, options.directory.trim().replace(/\\/g, path20.sep))
|
|
9440
10415
|
);
|
|
9441
10416
|
if (!isPathWithinRoot2(candidatePath, directoryPath)) return false;
|
|
9442
10417
|
}
|
|
@@ -9549,26 +10524,37 @@ var Indexer = class _Indexer {
|
|
|
9549
10524
|
return this.indexPathOverride ?? resolveProjectIndexPath(this.projectRoot, this.config.scope, this.host);
|
|
9550
10525
|
}
|
|
9551
10526
|
toCanonicalFilePath(filePath) {
|
|
9552
|
-
if (!
|
|
10527
|
+
if (!path20.isAbsolute(filePath)) {
|
|
9553
10528
|
return this.resolveStoredFilePath(filePath, this.projectRoot);
|
|
9554
10529
|
}
|
|
9555
|
-
if (
|
|
10530
|
+
if (path20.resolve(this.materializedProjectRoot) === path20.resolve(this.projectRoot) || !isPathWithinRoot2(filePath, this.materializedProjectRoot)) {
|
|
9556
10531
|
return filePath;
|
|
9557
10532
|
}
|
|
9558
|
-
return
|
|
10533
|
+
return path20.resolve(this.projectRoot, path20.relative(this.materializedProjectRoot, filePath));
|
|
9559
10534
|
}
|
|
9560
10535
|
toStoredFilePath(filePath) {
|
|
9561
10536
|
const canonicalFilePath = this.toCanonicalFilePath(filePath);
|
|
9562
10537
|
if (this.config.scope !== "project" || !isPathWithinRoot2(canonicalFilePath, this.projectRoot)) {
|
|
9563
10538
|
return canonicalFilePath;
|
|
9564
10539
|
}
|
|
9565
|
-
return
|
|
10540
|
+
return path20.relative(this.projectRoot, canonicalFilePath).split(path20.sep).join("/");
|
|
10541
|
+
}
|
|
10542
|
+
isStoredPathExcluded(storedPath) {
|
|
10543
|
+
let matchPath = storedPath.split(path20.sep).join("/");
|
|
10544
|
+
if (path20.isAbsolute(storedPath)) {
|
|
10545
|
+
const relativePath = path20.relative(this.projectRoot, storedPath).split(path20.sep).join("/");
|
|
10546
|
+
if (relativePath.startsWith("..") || path20.isAbsolute(relativePath)) {
|
|
10547
|
+
return false;
|
|
10548
|
+
}
|
|
10549
|
+
matchPath = relativePath;
|
|
10550
|
+
}
|
|
10551
|
+
return isExcludedByPatterns(matchPath, this.config.exclude);
|
|
9566
10552
|
}
|
|
9567
10553
|
resolveStoredFilePath(filePath, rootPath = this.projectRoot) {
|
|
9568
|
-
if (
|
|
10554
|
+
if (path20.isAbsolute(filePath)) {
|
|
9569
10555
|
return filePath;
|
|
9570
10556
|
}
|
|
9571
|
-
const resolvedPath =
|
|
10557
|
+
const resolvedPath = path20.resolve(rootPath, ...filePath.split("/"));
|
|
9572
10558
|
if (!isPathWithinRoot2(resolvedPath, rootPath)) {
|
|
9573
10559
|
throw new Error(`Stored project path escapes project root: ${JSON.stringify(filePath)}`);
|
|
9574
10560
|
}
|
|
@@ -9592,7 +10578,7 @@ var Indexer = class _Indexer {
|
|
|
9592
10578
|
}
|
|
9593
10579
|
toMaterializedFilePath(filePath) {
|
|
9594
10580
|
const storedFilePath = this.toStoredFilePath(filePath);
|
|
9595
|
-
if (
|
|
10581
|
+
if (path20.isAbsolute(storedFilePath)) {
|
|
9596
10582
|
return storedFilePath;
|
|
9597
10583
|
}
|
|
9598
10584
|
return this.resolveStoredFilePath(storedFilePath, this.materializedProjectRoot);
|
|
@@ -9609,10 +10595,10 @@ var Indexer = class _Indexer {
|
|
|
9609
10595
|
}
|
|
9610
10596
|
getRuntimeArtifactPath(fileName) {
|
|
9611
10597
|
const namespace = this.getRuntimeArtifactNamespace();
|
|
9612
|
-
if (!namespace) return
|
|
9613
|
-
const extension =
|
|
10598
|
+
if (!namespace) return path20.join(this.indexPath, fileName);
|
|
10599
|
+
const extension = path20.extname(fileName);
|
|
9614
10600
|
const baseName = fileName.slice(0, fileName.length - extension.length);
|
|
9615
|
-
return
|
|
10601
|
+
return path20.join(this.indexPath, `${baseName}.${namespace}${extension}`);
|
|
9616
10602
|
}
|
|
9617
10603
|
refreshRuntimeArtifactPaths() {
|
|
9618
10604
|
this.fileHashCachePath = this.getRuntimeArtifactPath("file-hashes.json");
|
|
@@ -9625,14 +10611,14 @@ var Indexer = class _Indexer {
|
|
|
9625
10611
|
getMaterializedKnowledgeBases() {
|
|
9626
10612
|
const canonicalProjectRoot = this.getCanonicalPath(this.projectRoot);
|
|
9627
10613
|
return this.config.knowledgeBases.map((knowledgeBase) => {
|
|
9628
|
-
const configuredPath =
|
|
10614
|
+
const configuredPath = path20.isAbsolute(knowledgeBase) ? knowledgeBase : path20.resolve(this.projectRoot, knowledgeBase);
|
|
9629
10615
|
const canonicalPath = this.getCanonicalPath(configuredPath);
|
|
9630
10616
|
if (!isPathWithinRoot2(canonicalPath, canonicalProjectRoot)) {
|
|
9631
10617
|
return canonicalPath;
|
|
9632
10618
|
}
|
|
9633
|
-
return
|
|
10619
|
+
return path20.resolve(
|
|
9634
10620
|
this.materializedProjectRoot,
|
|
9635
|
-
|
|
10621
|
+
path20.relative(canonicalProjectRoot, canonicalPath)
|
|
9636
10622
|
);
|
|
9637
10623
|
});
|
|
9638
10624
|
}
|
|
@@ -9640,7 +10626,7 @@ var Indexer = class _Indexer {
|
|
|
9640
10626
|
try {
|
|
9641
10627
|
return canonicalizePathForComparison(targetPath);
|
|
9642
10628
|
} catch {
|
|
9643
|
-
return
|
|
10629
|
+
return path20.resolve(targetPath);
|
|
9644
10630
|
}
|
|
9645
10631
|
}
|
|
9646
10632
|
getProjectIdentityHash(projectRoot) {
|
|
@@ -9766,7 +10752,7 @@ var Indexer = class _Indexer {
|
|
|
9766
10752
|
atomicWriteSync(targetPath, data) {
|
|
9767
10753
|
const lease = this.requireActiveLease();
|
|
9768
10754
|
const tempPath = createLeaseTemporaryPath(targetPath, lease.owner, "tmp");
|
|
9769
|
-
(0, import_fs12.mkdirSync)(
|
|
10755
|
+
(0, import_fs12.mkdirSync)(path20.dirname(targetPath), { recursive: true });
|
|
9770
10756
|
try {
|
|
9771
10757
|
(0, import_fs12.writeFileSync)(tempPath, data);
|
|
9772
10758
|
(0, import_fs12.renameSync)(tempPath, targetPath);
|
|
@@ -9776,14 +10762,14 @@ var Indexer = class _Indexer {
|
|
|
9776
10762
|
}
|
|
9777
10763
|
saveInvertedIndex(invertedIndex) {
|
|
9778
10764
|
this.atomicWriteSync(
|
|
9779
|
-
|
|
10765
|
+
path20.join(this.indexPath, "inverted-index.json"),
|
|
9780
10766
|
invertedIndex.serialize()
|
|
9781
10767
|
);
|
|
9782
10768
|
}
|
|
9783
10769
|
getScopedRoots(projectRoot = this.projectRoot) {
|
|
9784
10770
|
const roots = /* @__PURE__ */ new Set([this.getCanonicalPath(projectRoot)]);
|
|
9785
10771
|
for (const kbRoot of this.config.knowledgeBases) {
|
|
9786
|
-
roots.add(this.getCanonicalPath(
|
|
10772
|
+
roots.add(this.getCanonicalPath(path20.resolve(projectRoot, kbRoot)));
|
|
9787
10773
|
}
|
|
9788
10774
|
return Array.from(roots);
|
|
9789
10775
|
}
|
|
@@ -10200,7 +11186,7 @@ var Indexer = class _Indexer {
|
|
|
10200
11186
|
return configuredProviderInfo !== null && recovery.embeddingProvider === configuredProviderInfo.provider && recovery.embeddingModel === configuredProviderInfo.modelInfo.model && recovery.embeddingDimensions === configuredProviderInfo.modelInfo.dimensions && recovery.embeddingStrategyVersion === EMBEDDING_STRATEGY_VERSION;
|
|
10201
11187
|
}
|
|
10202
11188
|
hasUnknownLegacyForceIndexClear(owner) {
|
|
10203
|
-
return owner.operation === "force-index" && owner.clearRecovery === void 0 && owner.recoveryProtocolVersion !== 1 && (0, import_fs12.existsSync)(
|
|
11189
|
+
return owner.operation === "force-index" && owner.clearRecovery === void 0 && owner.recoveryProtocolVersion !== 1 && (0, import_fs12.existsSync)(path20.join(this.indexPath, "force-index-phase"));
|
|
10204
11190
|
}
|
|
10205
11191
|
async recoverFromInterruptedIndexingUnlocked(owners) {
|
|
10206
11192
|
for (const owner of owners) {
|
|
@@ -10588,7 +11574,7 @@ var Indexer = class _Indexer {
|
|
|
10588
11574
|
await options.queue.onSizeLessThan(Math.max(1, options.providerRateLimits.concurrency));
|
|
10589
11575
|
const task = options.queue.add(async () => {
|
|
10590
11576
|
if (options.rateLimitState.backoffMs > 0) {
|
|
10591
|
-
await new Promise((
|
|
11577
|
+
await new Promise((resolve20) => setTimeout(resolve20, options.rateLimitState.backoffMs));
|
|
10592
11578
|
}
|
|
10593
11579
|
try {
|
|
10594
11580
|
const embeddingResult = await pRetry(
|
|
@@ -11007,12 +11993,12 @@ var Indexer = class _Indexer {
|
|
|
11007
11993
|
}
|
|
11008
11994
|
}
|
|
11009
11995
|
captureReaderArtifactFingerprint() {
|
|
11010
|
-
const storePath =
|
|
11996
|
+
const storePath = path20.join(this.indexPath, "vectors");
|
|
11011
11997
|
return {
|
|
11012
11998
|
vectors: `${this.getReaderFileFingerprint(storePath)}|${this.getReaderFileFingerprint(`${storePath}.meta.json`)}`,
|
|
11013
|
-
keyword: this.getReaderFileFingerprint(
|
|
11014
|
-
database: this.getReaderFileFingerprint(
|
|
11015
|
-
databaseIdentity: this.getReaderFileFingerprint(
|
|
11999
|
+
keyword: this.getReaderFileFingerprint(path20.join(this.indexPath, "inverted-index.json")),
|
|
12000
|
+
database: this.getReaderFileFingerprint(path20.join(this.indexPath, "codebase.db")),
|
|
12001
|
+
databaseIdentity: this.getReaderFileFingerprint(path20.join(this.indexPath, "codebase.db"), true)
|
|
11016
12002
|
};
|
|
11017
12003
|
}
|
|
11018
12004
|
refreshReaderArtifacts() {
|
|
@@ -11037,10 +12023,10 @@ var Indexer = class _Indexer {
|
|
|
11037
12023
|
issues.set(component, this.createReadIssue(component, message));
|
|
11038
12024
|
this.readerArtifactRetryAfter.set(component, Date.now() + READER_ARTIFACT_RETRY_INTERVAL_MS);
|
|
11039
12025
|
};
|
|
11040
|
-
const storePath =
|
|
12026
|
+
const storePath = path20.join(this.indexPath, "vectors");
|
|
11041
12027
|
const vectorMetadataPath = `${storePath}.meta.json`;
|
|
11042
|
-
const invertedIndexPath =
|
|
11043
|
-
const dbPath =
|
|
12028
|
+
const invertedIndexPath = path20.join(this.indexPath, "inverted-index.json");
|
|
12029
|
+
const dbPath = path20.join(this.indexPath, "codebase.db");
|
|
11044
12030
|
if (vectorsChanged || retryDue("vectors")) {
|
|
11045
12031
|
const vectorStoreExists = (0, import_fs12.existsSync)(storePath);
|
|
11046
12032
|
const vectorMetadataExists = (0, import_fs12.existsSync)(vectorMetadataPath);
|
|
@@ -11156,10 +12142,10 @@ var Indexer = class _Indexer {
|
|
|
11156
12142
|
});
|
|
11157
12143
|
this.provider = createEmbeddingProvider(this.configuredProviderInfo);
|
|
11158
12144
|
const dimensions = this.configuredProviderInfo.modelInfo.dimensions;
|
|
11159
|
-
const storePath =
|
|
12145
|
+
const storePath = path20.join(this.indexPath, "vectors");
|
|
11160
12146
|
const vectorMetadataPath = `${storePath}.meta.json`;
|
|
11161
|
-
const invertedIndexPath =
|
|
11162
|
-
const dbPath =
|
|
12147
|
+
const invertedIndexPath = path20.join(this.indexPath, "inverted-index.json");
|
|
12148
|
+
const dbPath = path20.join(this.indexPath, "codebase.db");
|
|
11163
12149
|
let dbIsNew = !(0, import_fs12.existsSync)(dbPath);
|
|
11164
12150
|
const readerArtifactFingerprint = mode === "reader" ? this.captureReaderArtifactFingerprint() : null;
|
|
11165
12151
|
if (mode === "writer") {
|
|
@@ -11337,7 +12323,7 @@ var Indexer = class _Indexer {
|
|
|
11337
12323
|
if (await this.tryResetCorruptedIndex("running automatic orphan garbage collection", error)) {
|
|
11338
12324
|
return {
|
|
11339
12325
|
resetCorruptedIndex: true,
|
|
11340
|
-
warning: this.getCorruptedIndexWarning(
|
|
12326
|
+
warning: this.getCorruptedIndexWarning(path20.join(this.indexPath, "codebase.db"))
|
|
11341
12327
|
};
|
|
11342
12328
|
}
|
|
11343
12329
|
throw error;
|
|
@@ -11352,7 +12338,7 @@ var Indexer = class _Indexer {
|
|
|
11352
12338
|
return;
|
|
11353
12339
|
}
|
|
11354
12340
|
const retainedEntries = store.getAllMetadata().filter(({ key }) => !excludedSet.has(key));
|
|
11355
|
-
const storeBasePath =
|
|
12341
|
+
const storeBasePath = path20.join(this.indexPath, "vectors");
|
|
11356
12342
|
const storeIndexPath = storeBasePath;
|
|
11357
12343
|
const storeMetadataPath = `${storeBasePath}.meta.json`;
|
|
11358
12344
|
const lease = this.requireActiveLease();
|
|
@@ -11439,7 +12425,7 @@ var Indexer = class _Indexer {
|
|
|
11439
12425
|
const names = await import_fs12.promises.readdir(this.indexPath);
|
|
11440
12426
|
const runtimeStatePattern = /^(?:file-hashes|failed-batches)(?:\.[a-f0-9]{16})?\.json$/;
|
|
11441
12427
|
await Promise.all(
|
|
11442
|
-
names.filter((name) => runtimeStatePattern.test(name)).map((name) => import_fs12.promises.rm(
|
|
12428
|
+
names.filter((name) => runtimeStatePattern.test(name)).map((name) => import_fs12.promises.rm(path20.join(this.indexPath, name), { force: true }))
|
|
11443
12429
|
);
|
|
11444
12430
|
}
|
|
11445
12431
|
async resetLocalIndexArtifacts() {
|
|
@@ -11455,13 +12441,13 @@ var Indexer = class _Indexer {
|
|
|
11455
12441
|
this.readerArtifactRetryAfter.clear();
|
|
11456
12442
|
this.fileHashCache.clear();
|
|
11457
12443
|
const resetPaths = [
|
|
11458
|
-
|
|
11459
|
-
|
|
11460
|
-
|
|
11461
|
-
|
|
11462
|
-
|
|
11463
|
-
|
|
11464
|
-
|
|
12444
|
+
path20.join(this.indexPath, "codebase.db"),
|
|
12445
|
+
path20.join(this.indexPath, "codebase.db-shm"),
|
|
12446
|
+
path20.join(this.indexPath, "codebase.db-wal"),
|
|
12447
|
+
path20.join(this.indexPath, "vectors"),
|
|
12448
|
+
path20.join(this.indexPath, "vectors.usearch"),
|
|
12449
|
+
path20.join(this.indexPath, "vectors.meta.json"),
|
|
12450
|
+
path20.join(this.indexPath, "inverted-index.json")
|
|
11465
12451
|
];
|
|
11466
12452
|
await Promise.all(resetPaths.map((targetPath) => import_fs12.promises.rm(targetPath, { recursive: true, force: true })));
|
|
11467
12453
|
await this.removeProjectRuntimeStateArtifacts();
|
|
@@ -11471,7 +12457,7 @@ var Indexer = class _Indexer {
|
|
|
11471
12457
|
if (!isSqliteCorruptionError(error)) {
|
|
11472
12458
|
return false;
|
|
11473
12459
|
}
|
|
11474
|
-
const dbPath =
|
|
12460
|
+
const dbPath = path20.join(this.indexPath, "codebase.db");
|
|
11475
12461
|
const warning = this.getCorruptedIndexWarning(dbPath);
|
|
11476
12462
|
const errorMessage = getErrorMessage4(error);
|
|
11477
12463
|
if (this.config.scope === "global") {
|
|
@@ -11858,10 +12844,10 @@ var Indexer = class _Indexer {
|
|
|
11858
12844
|
const reparseCachedMetalFiles = database.getMetadata(metalParserMetadataKey) !== METAL_PARSER_VERSION;
|
|
11859
12845
|
const symbolExtractorMetadataKey = this.getSymbolExtractorVersionMetadataKey();
|
|
11860
12846
|
const refreshCachedSymbols = database.getMetadata(symbolExtractorMetadataKey) !== SYMBOL_EXTRACTOR_VERSION;
|
|
11861
|
-
if (reparseCachedSwiftFiles && Array.from(this.fileHashCache.keys()).some((filePath) =>
|
|
12847
|
+
if (reparseCachedSwiftFiles && Array.from(this.fileHashCache.keys()).some((filePath) => path20.extname(filePath).toLowerCase() === ".swift")) {
|
|
11862
12848
|
this.logger.info("Reindexing cached Swift files for parser support");
|
|
11863
12849
|
}
|
|
11864
|
-
if (reparseCachedMetalFiles && Array.from(this.fileHashCache.keys()).some((filePath) =>
|
|
12850
|
+
if (reparseCachedMetalFiles && Array.from(this.fileHashCache.keys()).some((filePath) => path20.extname(filePath).toLowerCase() === ".metal")) {
|
|
11865
12851
|
this.logger.info("Reindexing cached Metal files for parser support");
|
|
11866
12852
|
}
|
|
11867
12853
|
const includePatterns = [...this.config.include, ...this.config.additionalInclude];
|
|
@@ -11905,8 +12891,8 @@ var Indexer = class _Indexer {
|
|
|
11905
12891
|
const needsCallGraphRefresh = cachedHashMatches && needsCallGraphResolutionMigration && database.getChunksByFile(storedPath).some(
|
|
11906
12892
|
(chunk) => chunk.language === "php" || chunk.language === "c" || chunk.language === "cpp"
|
|
11907
12893
|
);
|
|
11908
|
-
const requiresSwiftParserUpgrade = reparseCachedSwiftFiles &&
|
|
11909
|
-
const requiresMetalParserUpgrade = reparseCachedMetalFiles &&
|
|
12894
|
+
const requiresSwiftParserUpgrade = reparseCachedSwiftFiles && path20.extname(storedPath).toLowerCase() === ".swift";
|
|
12895
|
+
const requiresMetalParserUpgrade = reparseCachedMetalFiles && path20.extname(storedPath).toLowerCase() === ".metal";
|
|
11910
12896
|
const inMigrationScope = forceScopedReembed && scopedRoots !== null && this.isFileInCurrentScope(storedPath, scopedRoots);
|
|
11911
12897
|
if (cachedHashMatches && !inMigrationScope && !needsCallGraphRefresh && !requiresSwiftParserUpgrade && !requiresMetalParserUpgrade && !refreshCachedSymbols) {
|
|
11912
12898
|
unchangedFilePaths.add(storedPath);
|
|
@@ -11965,7 +12951,7 @@ var Indexer = class _Indexer {
|
|
|
11965
12951
|
}
|
|
11966
12952
|
}
|
|
11967
12953
|
}
|
|
11968
|
-
const shouldRetryFailedPath = (filePath) => filePath !== null && currentFileHashes.has(filePath) && unchangedFilePaths.has(filePath);
|
|
12954
|
+
const shouldRetryFailedPath = (filePath) => filePath !== null && !this.isStoredPathExcluded(filePath) && currentFileHashes.has(filePath) && unchangedFilePaths.has(filePath);
|
|
11969
12955
|
const failedProcessing = this.prepareFailedBatchProcessing(scopedRoots, shouldRetryFailedPath);
|
|
11970
12956
|
const maxChunkTokens = getSafeEmbeddingChunkTokenLimit(configuredProviderInfo);
|
|
11971
12957
|
const providerRateLimits = this.getProviderRateLimits(configuredProviderInfo.provider);
|
|
@@ -12069,7 +13055,7 @@ var Indexer = class _Indexer {
|
|
|
12069
13055
|
throw new Error(`Parsed file was not present in its source batch: ${parsed.path}`);
|
|
12070
13056
|
}
|
|
12071
13057
|
if (parsed.chunks.length === 0) {
|
|
12072
|
-
stats.parseFailures.push(
|
|
13058
|
+
stats.parseFailures.push(path20.isAbsolute(parsed.path) ? path20.relative(this.projectRoot, parsed.path) : parsed.path);
|
|
12073
13059
|
}
|
|
12074
13060
|
let chunksToProcess = parsed.chunks;
|
|
12075
13061
|
if (this.config.indexing.fallbackToTextOnMaxChunks && chunksToProcess.length > this.config.indexing.maxChunksPerFile) {
|
|
@@ -12404,7 +13390,7 @@ var Indexer = class _Indexer {
|
|
|
12404
13390
|
previousBranchSymbolIds,
|
|
12405
13391
|
Array.from(allSymbolIds)
|
|
12406
13392
|
);
|
|
12407
|
-
const vectorPath =
|
|
13393
|
+
const vectorPath = path20.join(this.indexPath, "vectors");
|
|
12408
13394
|
const shouldFingerprintLegacyPair = !store.hasFingerprint() && (0, import_fs12.existsSync)(vectorPath) && (0, import_fs12.existsSync)(`${vectorPath}.meta.json`);
|
|
12409
13395
|
if (backfilledBlameMetadata || shouldFingerprintLegacyPair || removedStoredChunks) {
|
|
12410
13396
|
store.save();
|
|
@@ -13263,7 +14249,7 @@ var Indexer = class _Indexer {
|
|
|
13263
14249
|
gcOrphanSymbols: 0,
|
|
13264
14250
|
gcOrphanCallEdges: 0,
|
|
13265
14251
|
resetCorruptedIndex: true,
|
|
13266
|
-
warning: this.getCorruptedIndexWarning(
|
|
14252
|
+
warning: this.getCorruptedIndexWarning(path20.join(this.indexPath, "codebase.db"))
|
|
13267
14253
|
};
|
|
13268
14254
|
}
|
|
13269
14255
|
this.logger.recordGc(removedCount, gcOrphanChunks, gcOrphanEmbeddings);
|
|
@@ -13293,7 +14279,8 @@ var Indexer = class _Indexer {
|
|
|
13293
14279
|
const maxChunkTokens = getSafeEmbeddingChunkTokenLimit(configuredProviderInfo);
|
|
13294
14280
|
const providerRateLimits = this.getProviderRateLimits(configuredProviderInfo.provider);
|
|
13295
14281
|
const roots = this.config.scope === "global" ? this.getScopedRoots() : null;
|
|
13296
|
-
const
|
|
14282
|
+
const shouldProcessFailedPath = (filePath) => filePath === null || !this.isStoredPathExcluded(filePath);
|
|
14283
|
+
const failedProcessing = this.prepareFailedBatchProcessing(roots, shouldProcessFailedPath);
|
|
13297
14284
|
if (failedProcessing.latestById.size === 0) {
|
|
13298
14285
|
this.finalizeFailedBatchWriteState(failedProcessing.state);
|
|
13299
14286
|
return { succeeded: 0, failed: 0, remaining: 0 };
|
|
@@ -13306,7 +14293,7 @@ var Indexer = class _Indexer {
|
|
|
13306
14293
|
const retryableChunks = this.iterateLatestFailedChunks(
|
|
13307
14294
|
failedProcessing.latestById,
|
|
13308
14295
|
roots,
|
|
13309
|
-
|
|
14296
|
+
shouldProcessFailedPath,
|
|
13310
14297
|
maxChunkTokens
|
|
13311
14298
|
);
|
|
13312
14299
|
for (const retryBatch of iterateOrderedFileBatches(
|
|
@@ -13576,9 +14563,9 @@ var Indexer = class _Indexer {
|
|
|
13576
14563
|
this.requireReadableComponents(readIssues, "database");
|
|
13577
14564
|
let shortest = [];
|
|
13578
14565
|
for (const branchKey of this.getBranchCatalogKeys()) {
|
|
13579
|
-
const
|
|
13580
|
-
if (
|
|
13581
|
-
shortest =
|
|
14566
|
+
const path35 = database.findShortestPath(fromName, toName, branchKey, maxDepth);
|
|
14567
|
+
if (path35.length > 0 && (shortest.length === 0 || path35.length < shortest.length)) {
|
|
14568
|
+
shortest = path35;
|
|
13582
14569
|
}
|
|
13583
14570
|
}
|
|
13584
14571
|
return shortest.map((hop) => this.resolveFilePathRecord(hop));
|
|
@@ -13626,13 +14613,13 @@ var Indexer = class _Indexer {
|
|
|
13626
14613
|
}
|
|
13627
14614
|
}
|
|
13628
14615
|
if (!found) continue;
|
|
13629
|
-
const
|
|
14616
|
+
const path35 = [];
|
|
13630
14617
|
let currentSymbolId = toSymbolId;
|
|
13631
14618
|
while (true) {
|
|
13632
14619
|
const symbol = symbolsById.get(currentSymbolId);
|
|
13633
14620
|
if (!symbol) break;
|
|
13634
14621
|
const parent = parentBySymbolId.get(currentSymbolId);
|
|
13635
|
-
|
|
14622
|
+
path35.push({
|
|
13636
14623
|
symbolId: symbol.id,
|
|
13637
14624
|
symbolName: symbol.name,
|
|
13638
14625
|
filePath: symbol.filePath,
|
|
@@ -13642,9 +14629,9 @@ var Indexer = class _Indexer {
|
|
|
13642
14629
|
if (!parent) break;
|
|
13643
14630
|
currentSymbolId = parent.parentId;
|
|
13644
14631
|
}
|
|
13645
|
-
|
|
13646
|
-
if (
|
|
13647
|
-
shortest =
|
|
14632
|
+
path35.reverse();
|
|
14633
|
+
if (path35.length > 0 && (shortest.length === 0 || path35.length < shortest.length)) {
|
|
14634
|
+
shortest = path35;
|
|
13648
14635
|
}
|
|
13649
14636
|
}
|
|
13650
14637
|
return shortest.map((hop) => this.resolveFilePathRecord(hop));
|
|
@@ -13795,7 +14782,7 @@ var Indexer = class _Indexer {
|
|
|
13795
14782
|
);
|
|
13796
14783
|
}
|
|
13797
14784
|
}
|
|
13798
|
-
const toStoredChangedFiles = (filePaths) => filePaths.map((filePath) => this.toStoredFilePath(
|
|
14785
|
+
const toStoredChangedFiles = (filePaths) => filePaths.map((filePath) => this.toStoredFilePath(path20.resolve(this.projectRoot, filePath)));
|
|
13799
14786
|
const storedChangedFiles = toStoredChangedFiles(changedFiles);
|
|
13800
14787
|
const directSymbols = database.getSymbolsForFiles(storedChangedFiles, branchKey);
|
|
13801
14788
|
const directIds = directSymbols.map((s) => s.id);
|
|
@@ -13944,12 +14931,12 @@ var Indexer = class _Indexer {
|
|
|
13944
14931
|
if (meta.filePath) filePaths.add(meta.filePath);
|
|
13945
14932
|
}
|
|
13946
14933
|
const directory = options?.directory?.replace(/\/$/, "");
|
|
13947
|
-
const absoluteDirectoryFilter = directory ?
|
|
14934
|
+
const absoluteDirectoryFilter = directory ? path20.resolve(this.projectRoot, directory) : void 0;
|
|
13948
14935
|
for (const filePath of filePaths) {
|
|
13949
14936
|
if (directory) {
|
|
13950
14937
|
const absoluteFilePath = this.resolveStoredFilePath(filePath);
|
|
13951
14938
|
const matchesRelative = filePath === directory || filePath.startsWith(directory + "/");
|
|
13952
|
-
const matchesProjectRelative = absoluteDirectoryFilter !== void 0 && (absoluteFilePath === absoluteDirectoryFilter || absoluteFilePath.startsWith(absoluteDirectoryFilter +
|
|
14939
|
+
const matchesProjectRelative = absoluteDirectoryFilter !== void 0 && (absoluteFilePath === absoluteDirectoryFilter || absoluteFilePath.startsWith(absoluteDirectoryFilter + path20.sep));
|
|
13953
14940
|
if (!matchesRelative && !matchesProjectRelative) {
|
|
13954
14941
|
continue;
|
|
13955
14942
|
}
|
|
@@ -14038,15 +15025,24 @@ function getOrCreateIndexer(projectRoot, host) {
|
|
|
14038
15025
|
}
|
|
14039
15026
|
const indexer = new Indexer(projectRoot, config, host);
|
|
14040
15027
|
indexerCache.set(key, indexer);
|
|
14041
|
-
configureAutoIndex(projectRoot, host, config, () => getOrCreateIndexer(projectRoot, host)
|
|
15028
|
+
configureAutoIndex(projectRoot, host, config, () => getOrCreateIndexer(projectRoot, host), {
|
|
15029
|
+
preserveManagedWorker: true,
|
|
15030
|
+
synchronizeBackgroundWorker: false
|
|
15031
|
+
});
|
|
14042
15032
|
return indexer;
|
|
14043
15033
|
}
|
|
14044
|
-
function initializeTools(projectRoot, config, host) {
|
|
15034
|
+
function initializeTools(projectRoot, config, host, options = {}) {
|
|
14045
15035
|
defaultProjectRoots.set(host, projectRoot);
|
|
14046
15036
|
const key = getIndexerCacheKey(projectRoot, host);
|
|
15037
|
+
if (options.preserveManagedWorker === true && isBackgroundWorkerManaged(projectRoot, host) && indexerCache.has(key)) {
|
|
15038
|
+
return;
|
|
15039
|
+
}
|
|
14047
15040
|
configCache.set(key, config);
|
|
14048
15041
|
indexerCache.set(key, new Indexer(projectRoot, config, host));
|
|
14049
|
-
configureAutoIndex(projectRoot, host, config, () => getOrCreateIndexer(projectRoot, host)
|
|
15042
|
+
configureAutoIndex(projectRoot, host, config, () => getOrCreateIndexer(projectRoot, host), {
|
|
15043
|
+
preserveManagedWorker: options.preserveManagedWorker,
|
|
15044
|
+
synchronizeBackgroundWorker: false
|
|
15045
|
+
});
|
|
14050
15046
|
}
|
|
14051
15047
|
function getIndexerForProject(projectRoot, host) {
|
|
14052
15048
|
const root = getProjectRoot(projectRoot, host);
|
|
@@ -14076,7 +15072,7 @@ function trimOrUndefined(value) {
|
|
|
14076
15072
|
return normalized || void 0;
|
|
14077
15073
|
}
|
|
14078
15074
|
function normalizeCallGraphPath(value) {
|
|
14079
|
-
let normalized =
|
|
15075
|
+
let normalized = path21.posix.normalize(value.trim().replaceAll("\\", "/"));
|
|
14080
15076
|
if (normalized.startsWith("./")) {
|
|
14081
15077
|
normalized = normalized.slice(2);
|
|
14082
15078
|
}
|
|
@@ -14292,32 +15288,32 @@ async function executeCallGraph(projectRoot, host, args) {
|
|
|
14292
15288
|
// src/adapters/mcp/cli.ts
|
|
14293
15289
|
var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
14294
15290
|
var import_fs20 = require("fs");
|
|
14295
|
-
var
|
|
14296
|
-
var
|
|
15291
|
+
var os9 = __toESM(require("os"), 1);
|
|
15292
|
+
var path33 = __toESM(require("path"), 1);
|
|
14297
15293
|
var import_url = require("url");
|
|
14298
15294
|
|
|
14299
15295
|
// src/eval/reports.ts
|
|
14300
15296
|
var import_fs14 = require("fs");
|
|
14301
|
-
var
|
|
15297
|
+
var path22 = __toESM(require("path"), 1);
|
|
14302
15298
|
|
|
14303
15299
|
// src/eval/runner.ts
|
|
14304
15300
|
var crypto2 = __toESM(require("crypto"), 1);
|
|
14305
15301
|
var import_fs17 = require("fs");
|
|
14306
|
-
var
|
|
15302
|
+
var path24 = __toESM(require("path"), 1);
|
|
14307
15303
|
|
|
14308
15304
|
// src/eval/runner-config.ts
|
|
14309
15305
|
var import_fs15 = require("fs");
|
|
14310
|
-
var
|
|
14311
|
-
var
|
|
15306
|
+
var os8 = __toESM(require("os"), 1);
|
|
15307
|
+
var path23 = __toESM(require("path"), 1);
|
|
14312
15308
|
|
|
14313
15309
|
// src/eval/schema.ts
|
|
14314
15310
|
var import_fs16 = require("fs");
|
|
14315
15311
|
|
|
14316
15312
|
// src/eval/cli.ts
|
|
14317
|
-
var
|
|
15313
|
+
var path26 = __toESM(require("path"), 1);
|
|
14318
15314
|
|
|
14319
15315
|
// src/eval/cli-parser.ts
|
|
14320
|
-
var
|
|
15316
|
+
var path25 = __toESM(require("path"), 1);
|
|
14321
15317
|
|
|
14322
15318
|
// src/adapters/mcp/server.ts
|
|
14323
15319
|
var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
@@ -14423,25 +15419,25 @@ var MCP_TOOL_NAMES = [
|
|
|
14423
15419
|
|
|
14424
15420
|
// src/watcher/file-watcher.ts
|
|
14425
15421
|
var import_fs19 = require("fs");
|
|
14426
|
-
var
|
|
15422
|
+
var path29 = __toESM(require("path"), 1);
|
|
14427
15423
|
|
|
14428
15424
|
// src/watcher/native-recursive-watcher.ts
|
|
14429
|
-
var
|
|
14430
|
-
var
|
|
15425
|
+
var import_node_fs2 = require("fs");
|
|
15426
|
+
var path27 = __toESM(require("path"), 1);
|
|
14431
15427
|
|
|
14432
15428
|
// src/watcher/snapshot.ts
|
|
14433
15429
|
var fsPromises4 = __toESM(require("fs/promises"), 1);
|
|
14434
|
-
var
|
|
15430
|
+
var path28 = __toESM(require("path"), 1);
|
|
14435
15431
|
|
|
14436
15432
|
// src/watcher/git-head-watcher.ts
|
|
14437
|
-
var
|
|
15433
|
+
var path30 = __toESM(require("path"), 1);
|
|
14438
15434
|
|
|
14439
15435
|
// src/tools/visualize/activity.ts
|
|
14440
15436
|
var import_child_process5 = require("child_process");
|
|
14441
|
-
var
|
|
15437
|
+
var path31 = __toESM(require("path"), 1);
|
|
14442
15438
|
|
|
14443
15439
|
// src/tools/visualize/transform.ts
|
|
14444
|
-
var
|
|
15440
|
+
var path32 = __toESM(require("path"), 1);
|
|
14445
15441
|
|
|
14446
15442
|
// src/adapters/mcp/cli.ts
|
|
14447
15443
|
function parseIndexArgs(argv, cwd) {
|
|
@@ -14463,7 +15459,7 @@ function parseIndexArgs(argv, cwd) {
|
|
|
14463
15459
|
if (!arg.startsWith("--project=")) {
|
|
14464
15460
|
i += 1;
|
|
14465
15461
|
}
|
|
14466
|
-
project =
|
|
15462
|
+
project = path33.resolve(cwd, value);
|
|
14467
15463
|
continue;
|
|
14468
15464
|
}
|
|
14469
15465
|
if (arg === "--config" || arg.startsWith("--config=")) {
|
|
@@ -14474,7 +15470,7 @@ function parseIndexArgs(argv, cwd) {
|
|
|
14474
15470
|
if (!arg.startsWith("--config=")) {
|
|
14475
15471
|
i += 1;
|
|
14476
15472
|
}
|
|
14477
|
-
config =
|
|
15473
|
+
config = path33.resolve(cwd, value);
|
|
14478
15474
|
continue;
|
|
14479
15475
|
}
|
|
14480
15476
|
if (arg === "--host" || arg.startsWith("--host=")) {
|
|
@@ -14638,7 +15634,7 @@ function parseCbiCommandArgs(command, args, cwd) {
|
|
|
14638
15634
|
if (arg === "--help" || arg === "-h") throw new Error("help-requested");
|
|
14639
15635
|
if (arg === "--project" || arg.startsWith("--project=")) {
|
|
14640
15636
|
const parsed = optionValue(args, index, "project");
|
|
14641
|
-
project =
|
|
15637
|
+
project = path34.resolve(cwd, parsed.value);
|
|
14642
15638
|
index += parsed.consumed;
|
|
14643
15639
|
continue;
|
|
14644
15640
|
}
|
|
@@ -14650,7 +15646,7 @@ function parseCbiCommandArgs(command, args, cwd) {
|
|
|
14650
15646
|
}
|
|
14651
15647
|
if (arg === "--config" || arg.startsWith("--config=")) {
|
|
14652
15648
|
const parsed = optionValue(args, index, "config");
|
|
14653
|
-
config =
|
|
15649
|
+
config = path34.resolve(cwd, parsed.value);
|
|
14654
15650
|
index += parsed.consumed;
|
|
14655
15651
|
continue;
|
|
14656
15652
|
}
|
|
@@ -14663,7 +15659,7 @@ function parseCbiCommandArgs(command, args, cwd) {
|
|
|
14663
15659
|
}
|
|
14664
15660
|
if (command === "graph" && (arg === "--file" || arg.startsWith("--file="))) {
|
|
14665
15661
|
const parsed = optionValue(args, index, "file");
|
|
14666
|
-
filePath =
|
|
15662
|
+
filePath = path34.resolve(cwd, parsed.value);
|
|
14667
15663
|
index += parsed.consumed;
|
|
14668
15664
|
continue;
|
|
14669
15665
|
}
|
|
@@ -14762,7 +15758,7 @@ async function runCbiCli(argv, cwd, deps = {}) {
|
|
|
14762
15758
|
}
|
|
14763
15759
|
}
|
|
14764
15760
|
function isCbiEntrypoint(moduleUrl, argvPath) {
|
|
14765
|
-
return argvPath !== void 0 && (0,
|
|
15761
|
+
return argvPath !== void 0 && (0, import_node_fs3.realpathSync)((0, import_node_url2.fileURLToPath)(moduleUrl)) === (0, import_node_fs3.realpathSync)(argvPath);
|
|
14766
15762
|
}
|
|
14767
15763
|
|
|
14768
15764
|
// src/cbi.ts
|