opencode-codebase-index 0.25.0 → 0.25.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.cjs CHANGED
@@ -496,7 +496,7 @@ var require_ignore = __commonJS({
496
496
  // path matching.
497
497
  // - check `string` either `MODE_IGNORE` or `MODE_CHECK_IGNORE`
498
498
  // @returns {TestResult} true if a file is ignored
499
- test(path33, checkUnignored, mode) {
499
+ test(path34, checkUnignored, mode) {
500
500
  let ignored = false;
501
501
  let unignored = false;
502
502
  let matchedRule;
@@ -505,7 +505,7 @@ var require_ignore = __commonJS({
505
505
  if (unignored === negative && ignored !== unignored || negative && !ignored && !unignored && !checkUnignored) {
506
506
  return;
507
507
  }
508
- const matched = rule[mode].test(path33);
508
+ const matched = rule[mode].test(path34);
509
509
  if (!matched) {
510
510
  return;
511
511
  }
@@ -526,17 +526,17 @@ var require_ignore = __commonJS({
526
526
  var throwError = (message, Ctor) => {
527
527
  throw new Ctor(message);
528
528
  };
529
- var checkPath = (path33, originalPath, doThrow) => {
530
- if (!isString(path33)) {
529
+ var checkPath = (path34, originalPath, doThrow) => {
530
+ if (!isString(path34)) {
531
531
  return doThrow(
532
532
  `path must be a string, but got \`${originalPath}\``,
533
533
  TypeError
534
534
  );
535
535
  }
536
- if (!path33) {
536
+ if (!path34) {
537
537
  return doThrow(`path must not be empty`, TypeError);
538
538
  }
539
- if (checkPath.isNotRelative(path33)) {
539
+ if (checkPath.isNotRelative(path34)) {
540
540
  const r = "`path.relative()`d";
541
541
  return doThrow(
542
542
  `path should be a ${r} string, but got "${originalPath}"`,
@@ -545,7 +545,7 @@ var require_ignore = __commonJS({
545
545
  }
546
546
  return true;
547
547
  };
548
- var isNotRelative = (path33) => REGEX_TEST_INVALID_PATH.test(path33);
548
+ var isNotRelative = (path34) => REGEX_TEST_INVALID_PATH.test(path34);
549
549
  checkPath.isNotRelative = isNotRelative;
550
550
  checkPath.convert = (p) => p;
551
551
  var Ignore2 = class {
@@ -575,19 +575,19 @@ var require_ignore = __commonJS({
575
575
  }
576
576
  // @returns {TestResult}
577
577
  _test(originalPath, cache, checkUnignored, slices) {
578
- const path33 = originalPath && checkPath.convert(originalPath);
578
+ const path34 = originalPath && checkPath.convert(originalPath);
579
579
  checkPath(
580
- path33,
580
+ path34,
581
581
  originalPath,
582
582
  this._strictPathCheck ? throwError : RETURN_FALSE
583
583
  );
584
- return this._t(path33, cache, checkUnignored, slices);
584
+ return this._t(path34, cache, checkUnignored, slices);
585
585
  }
586
- checkIgnore(path33) {
587
- if (!REGEX_TEST_TRAILING_SLASH.test(path33)) {
588
- return this.test(path33);
586
+ checkIgnore(path34) {
587
+ if (!REGEX_TEST_TRAILING_SLASH.test(path34)) {
588
+ return this.test(path34);
589
589
  }
590
- const slices = path33.split(SLASH2).filter(Boolean);
590
+ const slices = path34.split(SLASH2).filter(Boolean);
591
591
  slices.pop();
592
592
  if (slices.length) {
593
593
  const parent = this._t(
@@ -600,18 +600,18 @@ var require_ignore = __commonJS({
600
600
  return parent;
601
601
  }
602
602
  }
603
- return this._rules.test(path33, false, MODE_CHECK_IGNORE);
603
+ return this._rules.test(path34, false, MODE_CHECK_IGNORE);
604
604
  }
605
- _t(path33, cache, checkUnignored, slices) {
606
- if (path33 in cache) {
607
- return cache[path33];
605
+ _t(path34, cache, checkUnignored, slices) {
606
+ if (path34 in cache) {
607
+ return cache[path34];
608
608
  }
609
609
  if (!slices) {
610
- slices = path33.split(SLASH2).filter(Boolean);
610
+ slices = path34.split(SLASH2).filter(Boolean);
611
611
  }
612
612
  slices.pop();
613
613
  if (!slices.length) {
614
- return cache[path33] = this._rules.test(path33, checkUnignored, MODE_IGNORE);
614
+ return cache[path34] = this._rules.test(path34, checkUnignored, MODE_IGNORE);
615
615
  }
616
616
  const parent = this._t(
617
617
  slices.join(SLASH2) + SLASH2,
@@ -619,29 +619,29 @@ var require_ignore = __commonJS({
619
619
  checkUnignored,
620
620
  slices
621
621
  );
622
- return cache[path33] = parent.ignored ? parent : this._rules.test(path33, checkUnignored, MODE_IGNORE);
622
+ return cache[path34] = parent.ignored ? parent : this._rules.test(path34, checkUnignored, MODE_IGNORE);
623
623
  }
624
- ignores(path33) {
625
- return this._test(path33, this._ignoreCache, false).ignored;
624
+ ignores(path34) {
625
+ return this._test(path34, this._ignoreCache, false).ignored;
626
626
  }
627
627
  createFilter() {
628
- return (path33) => !this.ignores(path33);
628
+ return (path34) => !this.ignores(path34);
629
629
  }
630
630
  filter(paths) {
631
631
  return makeArray(paths).filter(this.createFilter());
632
632
  }
633
633
  // @returns {TestResult}
634
- test(path33) {
635
- return this._test(path33, this._testCache, true);
634
+ test(path34) {
635
+ return this._test(path34, this._testCache, true);
636
636
  }
637
637
  };
638
638
  var factory = (options) => new Ignore2(options);
639
- var isPathValid = (path33) => checkPath(path33 && checkPath.convert(path33), path33, RETURN_FALSE);
639
+ var isPathValid = (path34) => checkPath(path34 && checkPath.convert(path34), path34, RETURN_FALSE);
640
640
  var setupWindows = () => {
641
641
  const makePosix = (str) => /^\\\\\?\\/.test(str) || /["<>|\u0000-\u001F]+/u.test(str) ? str : str.replace(/\\/g, "/");
642
642
  checkPath.convert = makePosix;
643
643
  const REGEX_TEST_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i;
644
- checkPath.isNotRelative = (path33) => REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path33) || isNotRelative(path33);
644
+ checkPath.isNotRelative = (path34) => REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path34) || isNotRelative(path34);
645
645
  };
646
646
  if (
647
647
  // Detect `process` so that it can run in browsers.
@@ -668,8 +668,8 @@ module.exports = __toCommonJS(cli_exports);
668
668
  // src/adapters/mcp/cli.ts
669
669
  var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
670
670
  var import_fs20 = require("fs");
671
- var os8 = __toESM(require("os"), 1);
672
- var path32 = __toESM(require("path"), 1);
671
+ var os9 = __toESM(require("os"), 1);
672
+ var path33 = __toESM(require("path"), 1);
673
673
  var import_url = require("url");
674
674
 
675
675
  // src/config/constants.ts
@@ -1197,9 +1197,9 @@ var import_fs = require("fs");
1197
1197
  var path = __toESM(require("path"), 1);
1198
1198
 
1199
1199
  // src/eval/report-formatters.ts
1200
- function assertFiniteNumber(value, path33) {
1200
+ function assertFiniteNumber(value, path34) {
1201
1201
  if (typeof value !== "number" || Number.isNaN(value) || !Number.isFinite(value)) {
1202
- throw new Error(`${path33} must be a finite number`);
1202
+ throw new Error(`${path34} must be a finite number`);
1203
1203
  }
1204
1204
  return value;
1205
1205
  }
@@ -1439,7 +1439,7 @@ function buildPerQueryArtifact(perQuery) {
1439
1439
  // src/eval/runner.ts
1440
1440
  var crypto2 = __toESM(require("crypto"), 1);
1441
1441
  var import_fs17 = require("fs");
1442
- var path23 = __toESM(require("path"), 1);
1442
+ var path24 = __toESM(require("path"), 1);
1443
1443
  var import_perf_hooks2 = require("perf_hooks");
1444
1444
 
1445
1445
  // src/indexer/index.ts
@@ -1471,7 +1471,7 @@ function pTimeout(promise, options) {
1471
1471
  } = options;
1472
1472
  let timer;
1473
1473
  let abortHandler;
1474
- const wrappedPromise = new Promise((resolve20, reject) => {
1474
+ const wrappedPromise = new Promise((resolve21, reject) => {
1475
1475
  if (typeof milliseconds !== "number" || Math.sign(milliseconds) !== 1) {
1476
1476
  throw new TypeError(`Expected \`milliseconds\` to be a positive number, got \`${milliseconds}\``);
1477
1477
  }
@@ -1485,7 +1485,7 @@ function pTimeout(promise, options) {
1485
1485
  };
1486
1486
  signal.addEventListener("abort", abortHandler, { once: true });
1487
1487
  }
1488
- promise.then(resolve20, reject);
1488
+ promise.then(resolve21, reject);
1489
1489
  if (milliseconds === Number.POSITIVE_INFINITY) {
1490
1490
  return;
1491
1491
  }
@@ -1493,7 +1493,7 @@ function pTimeout(promise, options) {
1493
1493
  timer = customTimers.setTimeout.call(void 0, () => {
1494
1494
  if (fallback) {
1495
1495
  try {
1496
- resolve20(fallback());
1496
+ resolve21(fallback());
1497
1497
  } catch (error) {
1498
1498
  reject(error);
1499
1499
  }
@@ -1503,7 +1503,7 @@ function pTimeout(promise, options) {
1503
1503
  promise.cancel();
1504
1504
  }
1505
1505
  if (message === false) {
1506
- resolve20();
1506
+ resolve21();
1507
1507
  } else if (message instanceof Error) {
1508
1508
  reject(message);
1509
1509
  } else {
@@ -1905,7 +1905,7 @@ var PQueue = class extends import_index.default {
1905
1905
  // Assign unique ID if not provided
1906
1906
  id: options.id ?? (this.#idAssigner++).toString()
1907
1907
  };
1908
- return new Promise((resolve20, reject) => {
1908
+ return new Promise((resolve21, reject) => {
1909
1909
  const taskSymbol = /* @__PURE__ */ Symbol(`task-${options.id}`);
1910
1910
  let cleanupQueueAbortHandler = () => void 0;
1911
1911
  const run = async () => {
@@ -1945,7 +1945,7 @@ var PQueue = class extends import_index.default {
1945
1945
  })]);
1946
1946
  }
1947
1947
  const result = await operation;
1948
- resolve20(result);
1948
+ resolve21(result);
1949
1949
  this.emit("completed", result);
1950
1950
  } catch (error) {
1951
1951
  reject(error);
@@ -2133,13 +2133,13 @@ var PQueue = class extends import_index.default {
2133
2133
  });
2134
2134
  }
2135
2135
  async #onEvent(event, filter) {
2136
- return new Promise((resolve20) => {
2136
+ return new Promise((resolve21) => {
2137
2137
  const listener = () => {
2138
2138
  if (filter && !filter()) {
2139
2139
  return;
2140
2140
  }
2141
2141
  this.off(event, listener);
2142
- resolve20();
2142
+ resolve21();
2143
2143
  };
2144
2144
  this.on(event, listener);
2145
2145
  });
@@ -2425,7 +2425,7 @@ async function onAttemptFailure({ error, attemptNumber, retriesConsumed, startTi
2425
2425
  const finalDelay = Math.min(delayTime, remainingTime);
2426
2426
  options.signal?.throwIfAborted();
2427
2427
  if (finalDelay > 0) {
2428
- await new Promise((resolve20, reject) => {
2428
+ await new Promise((resolve21, reject) => {
2429
2429
  const onAbort = () => {
2430
2430
  clearTimeout(timeoutToken);
2431
2431
  options.signal?.removeEventListener("abort", onAbort);
@@ -2433,7 +2433,7 @@ async function onAttemptFailure({ error, attemptNumber, retriesConsumed, startTi
2433
2433
  };
2434
2434
  const timeoutToken = setTimeout(() => {
2435
2435
  options.signal?.removeEventListener("abort", onAbort);
2436
- resolve20();
2436
+ resolve21();
2437
2437
  }, finalDelay);
2438
2438
  if (options.unref) {
2439
2439
  timeoutToken.unref?.();
@@ -2795,17 +2795,17 @@ function validateExternalUrl(urlString) {
2795
2795
  if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
2796
2796
  return { valid: false, reason: `Blocked protocol: ${parsed.protocol}` };
2797
2797
  }
2798
- const hostname2 = parsed.hostname.toLowerCase();
2799
- if (BLOCKED_HOSTNAMES.has(hostname2)) {
2800
- return { valid: false, reason: `Blocked: cloud metadata service (${hostname2})` };
2798
+ const hostname3 = parsed.hostname.toLowerCase();
2799
+ if (BLOCKED_HOSTNAMES.has(hostname3)) {
2800
+ return { valid: false, reason: `Blocked: cloud metadata service (${hostname3})` };
2801
2801
  }
2802
2802
  for (const pattern of BLOCKED_METADATA_IPS) {
2803
- if (pattern.test(hostname2)) {
2804
- return { valid: false, reason: `Blocked: cloud metadata IP (${hostname2})` };
2803
+ if (pattern.test(hostname3)) {
2804
+ return { valid: false, reason: `Blocked: cloud metadata IP (${hostname3})` };
2805
2805
  }
2806
2806
  }
2807
- if (/^169\.254\./.test(hostname2)) {
2808
- return { valid: false, reason: `Blocked: link-local address (${hostname2})` };
2807
+ if (/^169\.254\./.test(hostname3)) {
2808
+ return { valid: false, reason: `Blocked: link-local address (${hostname3})` };
2809
2809
  }
2810
2810
  return { valid: true };
2811
2811
  }
@@ -3391,26 +3391,46 @@ function createIgnoreFilter(projectRoot) {
3391
3391
  }
3392
3392
  return ig;
3393
3393
  }
3394
- function shouldIncludeFile(filePath, projectRoot, includePatterns, excludePatterns, ignoreFilter) {
3395
- const relativePath = path4.relative(projectRoot, filePath);
3396
- if (hasFilteredPathSegment(relativePath, path4.sep)) {
3397
- return false;
3398
- }
3399
- if (ignoreFilter.ignores(relativePath)) {
3400
- return false;
3394
+ function toPosixRelativePath(relativePath) {
3395
+ return relativePath.split(path4.sep).join("/");
3396
+ }
3397
+ function matchesAnyGlob(filePath, patterns) {
3398
+ const normalized = toPosixRelativePath(filePath);
3399
+ return patterns.some((pattern) => matchGlob(normalized, pattern));
3400
+ }
3401
+ function isExcludedByPatterns(relativePath, excludePatterns) {
3402
+ return matchesAnyGlob(relativePath, excludePatterns);
3403
+ }
3404
+ function isExcludedDirectory(relativePath, excludePatterns) {
3405
+ const normalized = toPosixRelativePath(relativePath);
3406
+ if (matchesAnyGlob(normalized, excludePatterns)) {
3407
+ return true;
3401
3408
  }
3402
3409
  for (const pattern of excludePatterns) {
3403
- if (matchGlob(relativePath, pattern)) {
3404
- return false;
3410
+ const posixPattern = toPosixRelativePath(pattern).replace(/\/+$/, "");
3411
+ if (!posixPattern.endsWith("/**")) {
3412
+ continue;
3405
3413
  }
3406
- }
3407
- for (const pattern of includePatterns) {
3408
- if (matchGlob(relativePath, pattern)) {
3414
+ const directoryPattern = posixPattern.slice(0, -3);
3415
+ if (directoryPattern && matchesAnyGlob(normalized, [directoryPattern])) {
3409
3416
  return true;
3410
3417
  }
3411
3418
  }
3412
3419
  return false;
3413
3420
  }
3421
+ function shouldIncludeFile(filePath, projectRoot, includePatterns, excludePatterns, ignoreFilter) {
3422
+ const relativePath = toPosixRelativePath(path4.relative(projectRoot, filePath));
3423
+ if (hasFilteredPathSegment(relativePath, "/")) {
3424
+ return false;
3425
+ }
3426
+ if (ignoreFilter.ignores(relativePath)) {
3427
+ return false;
3428
+ }
3429
+ if (isExcludedByPatterns(relativePath, excludePatterns)) {
3430
+ return false;
3431
+ }
3432
+ return matchesAnyGlob(relativePath, includePatterns);
3433
+ }
3414
3434
  function matchGlob(filePath, pattern) {
3415
3435
  if (pattern.startsWith("**/")) {
3416
3436
  const withoutPrefix = pattern.slice(3);
@@ -3432,7 +3452,7 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
3432
3452
  const subdirs = [];
3433
3453
  for (const entry of entries) {
3434
3454
  const fullPath = path4.join(dir, entry.name);
3435
- const relativePath = path4.relative(projectRoot, fullPath);
3455
+ const relativePath = toPosixRelativePath(path4.relative(projectRoot, fullPath));
3436
3456
  if (isHiddenPathSegment(entry.name)) {
3437
3457
  if (entry.isDirectory()) {
3438
3458
  skipped.push({ path: relativePath, reason: "excluded" });
@@ -3450,6 +3470,10 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
3450
3470
  continue;
3451
3471
  }
3452
3472
  if (entry.isDirectory()) {
3473
+ if (isExcludedDirectory(relativePath, excludePatterns)) {
3474
+ skipped.push({ path: relativePath, reason: "excluded" });
3475
+ continue;
3476
+ }
3453
3477
  subdirs.push({ fullPath, relativePath });
3454
3478
  } else if (entry.isFile()) {
3455
3479
  const stat5 = await import_fs3.promises.stat(fullPath);
@@ -3457,20 +3481,11 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
3457
3481
  skipped.push({ path: relativePath, reason: "too_large" });
3458
3482
  continue;
3459
3483
  }
3460
- for (const pattern of excludePatterns) {
3461
- if (matchGlob(relativePath, pattern)) {
3462
- skipped.push({ path: relativePath, reason: "excluded" });
3463
- continue;
3464
- }
3465
- }
3466
- let matched = false;
3467
- for (const pattern of includePatterns) {
3468
- if (matchGlob(relativePath, pattern)) {
3469
- matched = true;
3470
- break;
3471
- }
3484
+ if (isExcludedByPatterns(relativePath, excludePatterns)) {
3485
+ skipped.push({ path: relativePath, reason: "excluded" });
3486
+ continue;
3472
3487
  }
3473
- if (matched) {
3488
+ if (matchesAnyGlob(relativePath, includePatterns)) {
3474
3489
  filesInDir.push({ path: fullPath, size: stat5.size });
3475
3490
  }
3476
3491
  }
@@ -3481,7 +3496,7 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
3481
3496
  yield f;
3482
3497
  }
3483
3498
  for (let i = options.maxFilesPerDirectory; i < filesInDir.length; i++) {
3484
- skipped.push({ path: path4.relative(projectRoot, filesInDir[i].path), reason: "excluded" });
3499
+ skipped.push({ path: toPosixRelativePath(path4.relative(projectRoot, filesInDir[i].path)), reason: "excluded" });
3485
3500
  }
3486
3501
  const canRecurse = options.maxDepth === -1 || currentDepth < options.maxDepth;
3487
3502
  if (canRecurse) {
@@ -7102,8 +7117,8 @@ function pathSegmentsForAffinityMatch(filePath) {
7102
7117
  if (segments.length === 0) {
7103
7118
  return [];
7104
7119
  }
7105
- const basename8 = segments[segments.length - 1] ?? "";
7106
- const basenameWithoutExt = basename8.replace(/\.[^/.]+$/u, "");
7120
+ const basename9 = segments[segments.length - 1] ?? "";
7121
+ const basenameWithoutExt = basename9.replace(/\.[^/.]+$/u, "");
7107
7122
  const normalizedSegments = segments.map((segment) => segment.toLowerCase());
7108
7123
  return Array.from(/* @__PURE__ */ new Set([
7109
7124
  ...normalizedSegments,
@@ -7516,7 +7531,7 @@ function removeDeadReclaimMarker(lockPath, expectedOwner) {
7516
7531
  return true;
7517
7532
  }
7518
7533
  function reclaimDeadOwner(indexPath, lockPath, expectedOwner) {
7519
- const reclaimPath = path13.join(lockPath, RECLAIM_DIRECTORY_NAME);
7534
+ const reclaimPath2 = path13.join(lockPath, RECLAIM_DIRECTORY_NAME);
7520
7535
  const reclaimOwner = {
7521
7536
  pid: process.pid,
7522
7537
  hostname: os5.hostname(),
@@ -7525,19 +7540,19 @@ function reclaimDeadOwner(indexPath, lockPath, expectedOwner) {
7525
7540
  expectedOwnerToken: expectedOwner.token
7526
7541
  };
7527
7542
  for (let attempt = 0; attempt < 2; attempt += 1) {
7528
- if (publishJsonDirectory(reclaimPath, reclaimOwner)) break;
7543
+ if (publishJsonDirectory(reclaimPath2, reclaimOwner)) break;
7529
7544
  if (attempt === 0 && removeDeadReclaimMarker(lockPath, expectedOwner)) continue;
7530
7545
  return false;
7531
7546
  }
7532
7547
  try {
7533
- const currentReclaimer = readReclaimOwner(reclaimPath);
7548
+ const currentReclaimer = readReclaimOwner(reclaimPath2);
7534
7549
  const currentOwner = readDirectoryOwner(lockPath);
7535
7550
  if (!currentReclaimer || !sameReclaimOwner(currentReclaimer, reclaimOwner) || !currentOwner || !sameOwner(currentOwner, expectedOwner) || getOwnerLiveness(currentOwner) !== "dead") {
7536
7551
  return false;
7537
7552
  }
7538
7553
  publishRecoveryMarker(indexPath, expectedOwner);
7539
7554
  const ownerBeforeQuarantine = readDirectoryOwner(lockPath);
7540
- const reclaimerBeforeQuarantine = readReclaimOwner(reclaimPath);
7555
+ const reclaimerBeforeQuarantine = readReclaimOwner(reclaimPath2);
7541
7556
  if (!ownerBeforeQuarantine || !sameOwner(ownerBeforeQuarantine, expectedOwner) || getOwnerLiveness(ownerBeforeQuarantine) !== "dead" || !reclaimerBeforeQuarantine || !sameReclaimOwner(reclaimerBeforeQuarantine, reclaimOwner)) {
7542
7557
  return false;
7543
7558
  }
@@ -8753,6 +8768,17 @@ var Indexer = class _Indexer {
8753
8768
  }
8754
8769
  return path15.relative(this.projectRoot, canonicalFilePath).split(path15.sep).join("/");
8755
8770
  }
8771
+ isStoredPathExcluded(storedPath) {
8772
+ let matchPath = storedPath.split(path15.sep).join("/");
8773
+ if (path15.isAbsolute(storedPath)) {
8774
+ const relativePath = path15.relative(this.projectRoot, storedPath).split(path15.sep).join("/");
8775
+ if (relativePath.startsWith("..") || path15.isAbsolute(relativePath)) {
8776
+ return false;
8777
+ }
8778
+ matchPath = relativePath;
8779
+ }
8780
+ return isExcludedByPatterns(matchPath, this.config.exclude);
8781
+ }
8756
8782
  resolveStoredFilePath(filePath, rootPath = this.projectRoot) {
8757
8783
  if (path15.isAbsolute(filePath)) {
8758
8784
  return filePath;
@@ -9777,7 +9803,7 @@ var Indexer = class _Indexer {
9777
9803
  await options.queue.onSizeLessThan(Math.max(1, options.providerRateLimits.concurrency));
9778
9804
  const task = options.queue.add(async () => {
9779
9805
  if (options.rateLimitState.backoffMs > 0) {
9780
- await new Promise((resolve20) => setTimeout(resolve20, options.rateLimitState.backoffMs));
9806
+ await new Promise((resolve21) => setTimeout(resolve21, options.rateLimitState.backoffMs));
9781
9807
  }
9782
9808
  try {
9783
9809
  const embeddingResult = await pRetry(
@@ -11154,7 +11180,7 @@ var Indexer = class _Indexer {
11154
11180
  }
11155
11181
  }
11156
11182
  }
11157
- const shouldRetryFailedPath = (filePath) => filePath !== null && currentFileHashes.has(filePath) && unchangedFilePaths.has(filePath);
11183
+ const shouldRetryFailedPath = (filePath) => filePath !== null && !this.isStoredPathExcluded(filePath) && currentFileHashes.has(filePath) && unchangedFilePaths.has(filePath);
11158
11184
  const failedProcessing = this.prepareFailedBatchProcessing(scopedRoots, shouldRetryFailedPath);
11159
11185
  const maxChunkTokens = getSafeEmbeddingChunkTokenLimit(configuredProviderInfo);
11160
11186
  const providerRateLimits = this.getProviderRateLimits(configuredProviderInfo.provider);
@@ -12482,7 +12508,8 @@ var Indexer = class _Indexer {
12482
12508
  const maxChunkTokens = getSafeEmbeddingChunkTokenLimit(configuredProviderInfo);
12483
12509
  const providerRateLimits = this.getProviderRateLimits(configuredProviderInfo.provider);
12484
12510
  const roots = this.config.scope === "global" ? this.getScopedRoots() : null;
12485
- const failedProcessing = this.prepareFailedBatchProcessing(roots, () => true);
12511
+ const shouldProcessFailedPath = (filePath) => filePath === null || !this.isStoredPathExcluded(filePath);
12512
+ const failedProcessing = this.prepareFailedBatchProcessing(roots, shouldProcessFailedPath);
12486
12513
  if (failedProcessing.latestById.size === 0) {
12487
12514
  this.finalizeFailedBatchWriteState(failedProcessing.state);
12488
12515
  return { succeeded: 0, failed: 0, remaining: 0 };
@@ -12495,7 +12522,7 @@ var Indexer = class _Indexer {
12495
12522
  const retryableChunks = this.iterateLatestFailedChunks(
12496
12523
  failedProcessing.latestById,
12497
12524
  roots,
12498
- () => true,
12525
+ shouldProcessFailedPath,
12499
12526
  maxChunkTokens
12500
12527
  );
12501
12528
  for (const retryBatch of iterateOrderedFileBatches(
@@ -12765,9 +12792,9 @@ var Indexer = class _Indexer {
12765
12792
  this.requireReadableComponents(readIssues, "database");
12766
12793
  let shortest = [];
12767
12794
  for (const branchKey of this.getBranchCatalogKeys()) {
12768
- const path33 = database.findShortestPath(fromName, toName, branchKey, maxDepth);
12769
- if (path33.length > 0 && (shortest.length === 0 || path33.length < shortest.length)) {
12770
- shortest = path33;
12795
+ const path34 = database.findShortestPath(fromName, toName, branchKey, maxDepth);
12796
+ if (path34.length > 0 && (shortest.length === 0 || path34.length < shortest.length)) {
12797
+ shortest = path34;
12771
12798
  }
12772
12799
  }
12773
12800
  return shortest.map((hop) => this.resolveFilePathRecord(hop));
@@ -12815,13 +12842,13 @@ var Indexer = class _Indexer {
12815
12842
  }
12816
12843
  }
12817
12844
  if (!found) continue;
12818
- const path33 = [];
12845
+ const path34 = [];
12819
12846
  let currentSymbolId = toSymbolId;
12820
12847
  while (true) {
12821
12848
  const symbol = symbolsById.get(currentSymbolId);
12822
12849
  if (!symbol) break;
12823
12850
  const parent = parentBySymbolId.get(currentSymbolId);
12824
- path33.push({
12851
+ path34.push({
12825
12852
  symbolId: symbol.id,
12826
12853
  symbolName: symbol.name,
12827
12854
  filePath: symbol.filePath,
@@ -12831,9 +12858,9 @@ var Indexer = class _Indexer {
12831
12858
  if (!parent) break;
12832
12859
  currentSymbolId = parent.parentId;
12833
12860
  }
12834
- path33.reverse();
12835
- if (path33.length > 0 && (shortest.length === 0 || path33.length < shortest.length)) {
12836
- shortest = path33;
12861
+ path34.reverse();
12862
+ if (path34.length > 0 && (shortest.length === 0 || path34.length < shortest.length)) {
12863
+ shortest = path34;
12837
12864
  }
12838
12865
  }
12839
12866
  return shortest.map((hop) => this.resolveFilePathRecord(hop));
@@ -13217,7 +13244,7 @@ var CODE_COMMUNITIES_MAX_COUPLING_LIMIT = 100;
13217
13244
 
13218
13245
  // src/tools/operations.ts
13219
13246
  var import_fs14 = require("fs");
13220
- var path21 = __toESM(require("path"), 1);
13247
+ var path22 = __toESM(require("path"), 1);
13221
13248
 
13222
13249
  // src/tools/knowledge-base-paths.ts
13223
13250
  var path16 = __toESM(require("path"), 1);
@@ -13512,8 +13539,8 @@ function formatExactSearchHandoff(results) {
13512
13539
  }
13513
13540
  function formatContextEvidence(result, index) {
13514
13541
  const symbol = result.name ? ` ${JSON.stringify(compactEvidenceValue(result.name, 80))}` : "";
13515
- const path33 = compactEvidenceValue(result.filePath, 120);
13516
- return `[${index}] ${result.chunkType}${symbol} in ${path33}:${result.startLine}-${result.endLine} (score ${result.score.toFixed(2)})`;
13542
+ const path34 = compactEvidenceValue(result.filePath, 120);
13543
+ return `[${index}] ${result.chunkType}${symbol} in ${path34}:${result.startLine}-${result.endLine} (score ${result.score.toFixed(2)})`;
13517
13544
  }
13518
13545
  function formatContextPack(heading, selected, candidateCount, duplicateCount, limitOmittedCount, budgetOmittedCount, includeExactSearchHandoff) {
13519
13546
  const lines = selected.map((result, index) => formatContextEvidence(result, index + 1));
@@ -14156,8 +14183,897 @@ function formatEffectivenessMetrics(snapshot) {
14156
14183
 
14157
14184
  // src/utils/auto-index.ts
14158
14185
  var import_fs11 = require("fs");
14186
+ var os7 = __toESM(require("os"), 1);
14187
+ var path18 = __toESM(require("path"), 1);
14188
+
14189
+ // src/utils/background-worker.ts
14190
+ var import_node_crypto2 = require("crypto");
14191
+ var import_node_fs = require("fs");
14159
14192
  var os6 = __toESM(require("os"), 1);
14160
14193
  var path17 = __toESM(require("path"), 1);
14194
+ var OWNER_FILE_NAME2 = "owner.json";
14195
+ var HEARTBEAT_FILE_PREFIX = "heartbeat.";
14196
+ var RECLAIM_DIRECTORY_NAME2 = "reclaim";
14197
+ var REFRESH_REQUEST_FILE_NAME = "refresh-request.json";
14198
+ var HEARTBEAT_INTERVAL_MS = 5e3;
14199
+ var STALE_LEASE_MS = 3e4;
14200
+ var RETRY_DELAY_MS = 5e3;
14201
+ 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;
14202
+ var BackgroundWorkerStopError = class extends Error {
14203
+ constructor(watcherError, autoIndexError) {
14204
+ super("Failed to stop background worker");
14205
+ this.watcherError = watcherError;
14206
+ this.autoIndexError = autoIndexError;
14207
+ this.name = "BackgroundWorkerStopError";
14208
+ }
14209
+ watcherError;
14210
+ autoIndexError;
14211
+ };
14212
+ var workers = /* @__PURE__ */ new Map();
14213
+ var workerKeysByProject = /* @__PURE__ */ new Map();
14214
+ var workerReplacementBarriers = /* @__PURE__ */ new Map();
14215
+ function getErrorCode2(error) {
14216
+ return typeof error === "object" && error !== null && "code" in error ? String(error.code) : void 0;
14217
+ }
14218
+ function canonicalizePath(targetPath) {
14219
+ const resolved = path17.resolve(targetPath);
14220
+ if ((0, import_node_fs.existsSync)(resolved)) {
14221
+ try {
14222
+ return import_node_fs.realpathSync.native(resolved);
14223
+ } catch {
14224
+ return resolved;
14225
+ }
14226
+ }
14227
+ const parent = path17.dirname(resolved);
14228
+ if (parent === resolved) return resolved;
14229
+ return path17.join(canonicalizePath(parent), path17.basename(resolved));
14230
+ }
14231
+ function projectLookupKey(projectRoot, host) {
14232
+ return `${host}::${canonicalizePath(projectRoot)}`;
14233
+ }
14234
+ function getBackgroundWorkerProjectKey(projectRoot, host) {
14235
+ return projectLookupKey(projectRoot, host);
14236
+ }
14237
+ function resolveIdentity(projectRoot, config, host) {
14238
+ const canonicalProjectRoot = canonicalizePath(projectRoot);
14239
+ const canonicalIndexPath = canonicalizePath(resolveProjectIndexPath(projectRoot, config.scope, host));
14240
+ return {
14241
+ canonicalIndexPath,
14242
+ canonicalProjectRoot,
14243
+ key: `${canonicalIndexPath}::${canonicalProjectRoot}`
14244
+ };
14245
+ }
14246
+ function controllerKey(identity, host) {
14247
+ return `${identity.key}::${host}`;
14248
+ }
14249
+ function leaseDirectoryName(identity) {
14250
+ const hash = (0, import_node_crypto2.createHash)("sha256").update(identity.key).digest("hex").slice(0, 32);
14251
+ return `background-worker.${hash}.lease`;
14252
+ }
14253
+ function leasePathFor(identity) {
14254
+ return path17.join(identity.canonicalIndexPath, leaseDirectoryName(identity));
14255
+ }
14256
+ function parseOwner2(value) {
14257
+ if (typeof value !== "object" || value === null) return null;
14258
+ const candidate = value;
14259
+ if (candidate.version !== 1) return null;
14260
+ if (!Number.isInteger(candidate.pid) || (candidate.pid ?? 0) <= 0) return null;
14261
+ if (typeof candidate.hostname !== "string" || candidate.hostname.length === 0) return null;
14262
+ if (typeof candidate.startedAt !== "string" || Number.isNaN(Date.parse(candidate.startedAt))) return null;
14263
+ if (typeof candidate.heartbeatAt !== "string" || Number.isNaN(Date.parse(candidate.heartbeatAt))) return null;
14264
+ if (typeof candidate.projectRoot !== "string" || candidate.projectRoot.length === 0) return null;
14265
+ if (typeof candidate.indexPath !== "string" || candidate.indexPath.length === 0) return null;
14266
+ if (typeof candidate.token !== "string" || !UUID_PATTERN2.test(candidate.token)) return null;
14267
+ return candidate;
14268
+ }
14269
+ function parseHeartbeat(value, expectedToken) {
14270
+ if (typeof value !== "object" || value === null) return null;
14271
+ const candidate = value;
14272
+ if (candidate.version !== 1 || candidate.token !== expectedToken) return null;
14273
+ if (typeof candidate.heartbeatAt !== "string" || Number.isNaN(Date.parse(candidate.heartbeatAt))) return null;
14274
+ return candidate;
14275
+ }
14276
+ function parseReclaimOwner2(value) {
14277
+ if (typeof value !== "object" || value === null) return null;
14278
+ const candidate = value;
14279
+ if (candidate.version !== 1) return null;
14280
+ if (!Number.isInteger(candidate.pid) || (candidate.pid ?? 0) <= 0) return null;
14281
+ if (typeof candidate.hostname !== "string" || candidate.hostname.length === 0) return null;
14282
+ if (typeof candidate.startedAt !== "string" || Number.isNaN(Date.parse(candidate.startedAt))) return null;
14283
+ if (typeof candidate.token !== "string" || !UUID_PATTERN2.test(candidate.token)) return null;
14284
+ if (candidate.expectedOwnerToken !== null && (typeof candidate.expectedOwnerToken !== "string" || !UUID_PATTERN2.test(candidate.expectedOwnerToken))) return null;
14285
+ return candidate;
14286
+ }
14287
+ function heartbeatPath(leasePath, token) {
14288
+ return path17.join(leasePath, `${HEARTBEAT_FILE_PREFIX}${token}.json`);
14289
+ }
14290
+ function reclaimPath(leasePath) {
14291
+ return path17.join(leasePath, RECLAIM_DIRECTORY_NAME2);
14292
+ }
14293
+ function refreshRequestPath(leasePath) {
14294
+ return path17.join(leasePath, REFRESH_REQUEST_FILE_NAME);
14295
+ }
14296
+ function readLeaseOwner(leasePath) {
14297
+ try {
14298
+ return parseOwner2(JSON.parse((0, import_node_fs.readFileSync)(path17.join(leasePath, OWNER_FILE_NAME2), "utf-8")));
14299
+ } catch {
14300
+ return null;
14301
+ }
14302
+ }
14303
+ function readOwner(leasePath) {
14304
+ const owner = readLeaseOwner(leasePath);
14305
+ if (!owner) return null;
14306
+ try {
14307
+ const heartbeat = parseHeartbeat(
14308
+ JSON.parse((0, import_node_fs.readFileSync)(heartbeatPath(leasePath, owner.token), "utf-8")),
14309
+ owner.token
14310
+ );
14311
+ return heartbeat ? { ...owner, heartbeatAt: heartbeat.heartbeatAt } : owner;
14312
+ } catch {
14313
+ return owner;
14314
+ }
14315
+ }
14316
+ function readReclaimOwner2(leasePath) {
14317
+ try {
14318
+ return parseReclaimOwner2(JSON.parse((0, import_node_fs.readFileSync)(path17.join(reclaimPath(leasePath), OWNER_FILE_NAME2), "utf-8")));
14319
+ } catch {
14320
+ return null;
14321
+ }
14322
+ }
14323
+ function ownerLiveness(owner) {
14324
+ if (owner.hostname !== os6.hostname()) return "unknown";
14325
+ try {
14326
+ process.kill(owner.pid, 0);
14327
+ return "alive";
14328
+ } catch (error) {
14329
+ const code = getErrorCode2(error);
14330
+ if (code === "ESRCH") return "dead";
14331
+ if (code === "EPERM") return "alive";
14332
+ return "unknown";
14333
+ }
14334
+ }
14335
+ function isHeartbeatExpired(owner) {
14336
+ return Date.now() - Date.parse(owner.heartbeatAt) >= STALE_LEASE_MS;
14337
+ }
14338
+ function sameOwner2(left, right) {
14339
+ return left.pid === right.pid && left.hostname === right.hostname && left.token === right.token;
14340
+ }
14341
+ function writeHeartbeat(leasePath, owner) {
14342
+ const targetPath = heartbeatPath(leasePath, owner.token);
14343
+ const temporaryPath = `${targetPath}.tmp.${process.pid}.${owner.token}.${(0, import_node_crypto2.randomUUID)()}`;
14344
+ const heartbeat = {
14345
+ version: 1,
14346
+ token: owner.token,
14347
+ heartbeatAt: owner.heartbeatAt
14348
+ };
14349
+ try {
14350
+ (0, import_node_fs.writeFileSync)(temporaryPath, JSON.stringify(heartbeat), {
14351
+ encoding: "utf-8",
14352
+ flag: "wx",
14353
+ mode: 384
14354
+ });
14355
+ (0, import_node_fs.renameSync)(temporaryPath, targetPath);
14356
+ const currentOwner = readLeaseOwner(leasePath);
14357
+ return currentOwner !== null && sameOwner2(currentOwner, owner);
14358
+ } finally {
14359
+ if ((0, import_node_fs.existsSync)(temporaryPath)) (0, import_node_fs.rmSync)(temporaryPath, { force: true });
14360
+ }
14361
+ }
14362
+ function requestRefreshFromLeader(leasePath, allowDisabledAutoIndex) {
14363
+ const requestPath = refreshRequestPath(leasePath);
14364
+ const temporaryPath = `${requestPath}.tmp.${process.pid}.${(0, import_node_crypto2.randomUUID)()}`;
14365
+ try {
14366
+ const request = {
14367
+ allowDisabledAutoIndex,
14368
+ requestedAt: (/* @__PURE__ */ new Date()).toISOString(),
14369
+ version: 1
14370
+ };
14371
+ (0, import_node_fs.writeFileSync)(temporaryPath, JSON.stringify(request), {
14372
+ encoding: "utf-8",
14373
+ flag: "wx",
14374
+ mode: 384
14375
+ });
14376
+ (0, import_node_fs.renameSync)(temporaryPath, requestPath);
14377
+ } catch (error) {
14378
+ if (getErrorCode2(error) !== "ENOENT") {
14379
+ console.error("[codebase-index] Failed to request background index refresh from the project worker:", error);
14380
+ }
14381
+ } finally {
14382
+ if ((0, import_node_fs.existsSync)(temporaryPath)) (0, import_node_fs.rmSync)(temporaryPath, { force: true });
14383
+ }
14384
+ }
14385
+ function consumeRefreshRequest(leasePath) {
14386
+ const requestPath = refreshRequestPath(leasePath);
14387
+ const claimedPath = `${requestPath}.handling.${process.pid}.${(0, import_node_crypto2.randomUUID)()}`;
14388
+ try {
14389
+ (0, import_node_fs.renameSync)(requestPath, claimedPath);
14390
+ } catch (error) {
14391
+ if (getErrorCode2(error) === "ENOENT") return null;
14392
+ throw error;
14393
+ }
14394
+ try {
14395
+ const value = JSON.parse((0, import_node_fs.readFileSync)(claimedPath, "utf-8"));
14396
+ return {
14397
+ allowDisabledAutoIndex: value.version === 1 && value.allowDisabledAutoIndex === true,
14398
+ requestedAt: typeof value.requestedAt === "string" ? value.requestedAt : (/* @__PURE__ */ new Date()).toISOString(),
14399
+ version: 1
14400
+ };
14401
+ } catch {
14402
+ return { allowDisabledAutoIndex: false, requestedAt: (/* @__PURE__ */ new Date()).toISOString(), version: 1 };
14403
+ } finally {
14404
+ (0, import_node_fs.rmSync)(claimedPath, { force: true });
14405
+ }
14406
+ }
14407
+ function publishLease(leasePath, owner) {
14408
+ const candidatePath = `${leasePath}.candidate.${process.pid}.${owner.token}`;
14409
+ try {
14410
+ (0, import_node_fs.mkdirSync)(candidatePath, { mode: 448 });
14411
+ } catch (error) {
14412
+ if (getErrorCode2(error) === "ENOENT") return false;
14413
+ throw error;
14414
+ }
14415
+ try {
14416
+ (0, import_node_fs.writeFileSync)(path17.join(candidatePath, OWNER_FILE_NAME2), JSON.stringify(owner), {
14417
+ encoding: "utf-8",
14418
+ flag: "wx",
14419
+ mode: 384
14420
+ });
14421
+ if ((0, import_node_fs.existsSync)(leasePath)) return false;
14422
+ try {
14423
+ (0, import_node_fs.renameSync)(candidatePath, leasePath);
14424
+ return true;
14425
+ } catch (error) {
14426
+ if ((0, import_node_fs.existsSync)(leasePath) || getErrorCode2(error) === "ENOENT") return false;
14427
+ throw error;
14428
+ }
14429
+ } finally {
14430
+ if ((0, import_node_fs.existsSync)(candidatePath)) (0, import_node_fs.rmSync)(candidatePath, { recursive: true, force: true });
14431
+ }
14432
+ }
14433
+ function sameReclaimOwner2(left, right) {
14434
+ return left.pid === right.pid && left.hostname === right.hostname && left.token === right.token && left.expectedOwnerToken === right.expectedOwnerToken;
14435
+ }
14436
+ function reclaimerLiveness(owner) {
14437
+ return ownerLiveness(owner);
14438
+ }
14439
+ function isReclaimMarkerExpired(leasePath, owner) {
14440
+ const startedAt = owner ? Date.parse(owner.startedAt) : (() => {
14441
+ try {
14442
+ return (0, import_node_fs.lstatSync)(reclaimPath(leasePath)).mtimeMs;
14443
+ } catch {
14444
+ return Date.now();
14445
+ }
14446
+ })();
14447
+ return Date.now() - startedAt >= STALE_LEASE_MS;
14448
+ }
14449
+ function hasActiveReclaimMarker(leasePath, owner) {
14450
+ const marker = readReclaimOwner2(leasePath);
14451
+ return marker !== null && marker.expectedOwnerToken === owner.token && (marker.hostname !== os6.hostname() || ownerLiveness(owner) !== "alive");
14452
+ }
14453
+ function publishReclaimMarker(leasePath, expectedOwner) {
14454
+ const markerPath = reclaimPath(leasePath);
14455
+ const owner = {
14456
+ version: 1,
14457
+ pid: process.pid,
14458
+ hostname: os6.hostname(),
14459
+ startedAt: (/* @__PURE__ */ new Date()).toISOString(),
14460
+ token: (0, import_node_crypto2.randomUUID)(),
14461
+ expectedOwnerToken: expectedOwner?.token ?? null
14462
+ };
14463
+ try {
14464
+ (0, import_node_fs.mkdirSync)(markerPath, { mode: 448 });
14465
+ } catch (error) {
14466
+ if (getErrorCode2(error) === "EEXIST" || getErrorCode2(error) === "ENOENT") return null;
14467
+ throw error;
14468
+ }
14469
+ try {
14470
+ (0, import_node_fs.writeFileSync)(path17.join(markerPath, OWNER_FILE_NAME2), JSON.stringify(owner), {
14471
+ encoding: "utf-8",
14472
+ flag: "wx",
14473
+ mode: 384
14474
+ });
14475
+ return owner;
14476
+ } catch (error) {
14477
+ (0, import_node_fs.rmSync)(markerPath, { recursive: true, force: true });
14478
+ throw error;
14479
+ }
14480
+ }
14481
+ function removeExpiredReclaimMarker(leasePath, expectedOwner) {
14482
+ const marker = readReclaimOwner2(leasePath);
14483
+ const markerPath = reclaimPath(leasePath);
14484
+ if (!(0, import_node_fs.existsSync)(markerPath)) return false;
14485
+ if (marker && marker.expectedOwnerToken !== (expectedOwner?.token ?? null)) return false;
14486
+ if (marker && (reclaimerLiveness(marker) === "alive" || !isReclaimMarkerExpired(leasePath, marker))) return false;
14487
+ if (!marker && !isReclaimMarkerExpired(leasePath, null)) return false;
14488
+ const staleMarkerPath = `${markerPath}.stale.${marker?.pid ?? process.pid}.${marker?.token ?? (0, import_node_crypto2.randomUUID)()}.${(0, import_node_crypto2.randomUUID)()}`;
14489
+ try {
14490
+ (0, import_node_fs.renameSync)(markerPath, staleMarkerPath);
14491
+ } catch (error) {
14492
+ if (getErrorCode2(error) === "ENOENT") return false;
14493
+ throw error;
14494
+ }
14495
+ try {
14496
+ let claimedMarker = null;
14497
+ try {
14498
+ claimedMarker = parseReclaimOwner2(
14499
+ JSON.parse((0, import_node_fs.readFileSync)(path17.join(staleMarkerPath, OWNER_FILE_NAME2), "utf-8"))
14500
+ );
14501
+ } catch {
14502
+ claimedMarker = null;
14503
+ }
14504
+ const markerMatches = marker ? claimedMarker !== null && sameReclaimOwner2(claimedMarker, marker) : claimedMarker === null;
14505
+ if (!markerMatches || !canReclaimLease(leasePath, expectedOwner)) {
14506
+ if (!(0, import_node_fs.existsSync)(markerPath) && (0, import_node_fs.existsSync)(staleMarkerPath)) (0, import_node_fs.renameSync)(staleMarkerPath, markerPath);
14507
+ return false;
14508
+ }
14509
+ (0, import_node_fs.rmSync)(staleMarkerPath, { recursive: true, force: true });
14510
+ return true;
14511
+ } catch (error) {
14512
+ if (getErrorCode2(error) === "ENOENT") return false;
14513
+ throw error;
14514
+ }
14515
+ }
14516
+ function canReclaimLease(leasePath, expectedOwner) {
14517
+ if (!(0, import_node_fs.existsSync)(leasePath)) return false;
14518
+ if (!expectedOwner) return false;
14519
+ const currentOwner = readOwner(leasePath);
14520
+ if (!currentOwner || !sameOwner2(currentOwner, expectedOwner)) return false;
14521
+ if (currentOwner.hostname === os6.hostname()) {
14522
+ return ownerLiveness(currentOwner) === "dead";
14523
+ }
14524
+ return isHeartbeatExpired(currentOwner);
14525
+ }
14526
+ function reclaimLease(leasePath, expectedOwner) {
14527
+ let marker = null;
14528
+ for (let attempt = 0; attempt < 2; attempt += 1) {
14529
+ marker = publishReclaimMarker(leasePath, expectedOwner);
14530
+ if (marker) break;
14531
+ if (attempt === 0 && removeExpiredReclaimMarker(leasePath, expectedOwner)) continue;
14532
+ return false;
14533
+ }
14534
+ if (!marker) return false;
14535
+ const markerPath = reclaimPath(leasePath);
14536
+ try {
14537
+ const currentMarker = readReclaimOwner2(leasePath);
14538
+ if (!currentMarker || !sameReclaimOwner2(currentMarker, marker) || !canReclaimLease(leasePath, expectedOwner)) {
14539
+ return false;
14540
+ }
14541
+ const stalePath = `${leasePath}.stale.${process.pid}.${marker.token}`;
14542
+ (0, import_node_fs.renameSync)(leasePath, stalePath);
14543
+ const quarantinedOwner = readOwner(stalePath);
14544
+ const quarantinedMarker = readReclaimOwner2(stalePath);
14545
+ if (!quarantinedMarker || !sameReclaimOwner2(quarantinedMarker, marker) || expectedOwner !== null && (!quarantinedOwner || !sameOwner2(quarantinedOwner, expectedOwner))) {
14546
+ if (!(0, import_node_fs.existsSync)(leasePath) && (0, import_node_fs.existsSync)(stalePath)) (0, import_node_fs.renameSync)(stalePath, leasePath);
14547
+ return false;
14548
+ }
14549
+ (0, import_node_fs.rmSync)(stalePath, { recursive: true, force: true });
14550
+ return true;
14551
+ } catch (error) {
14552
+ if (getErrorCode2(error) === "ENOENT") return false;
14553
+ throw error;
14554
+ } finally {
14555
+ const currentMarker = readReclaimOwner2(leasePath);
14556
+ if (currentMarker && sameReclaimOwner2(currentMarker, marker)) {
14557
+ (0, import_node_fs.rmSync)(markerPath, { recursive: true, force: true });
14558
+ }
14559
+ }
14560
+ }
14561
+ function acquireLease(identity) {
14562
+ (0, import_node_fs.mkdirSync)(identity.canonicalIndexPath, { recursive: true, mode: 448 });
14563
+ const canonicalIndexPath = import_node_fs.realpathSync.native(identity.canonicalIndexPath);
14564
+ const leasePath = path17.join(canonicalIndexPath, leaseDirectoryName({ ...identity, canonicalIndexPath }));
14565
+ for (let attempt = 0; attempt < 4; attempt += 1) {
14566
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
14567
+ const owner = {
14568
+ version: 1,
14569
+ pid: process.pid,
14570
+ hostname: os6.hostname(),
14571
+ startedAt: timestamp,
14572
+ heartbeatAt: timestamp,
14573
+ projectRoot: identity.canonicalProjectRoot,
14574
+ indexPath: canonicalIndexPath,
14575
+ token: (0, import_node_crypto2.randomUUID)()
14576
+ };
14577
+ if (publishLease(leasePath, owner)) {
14578
+ return { leasePath, owner };
14579
+ }
14580
+ const existingOwner = readOwner(leasePath);
14581
+ if (existingOwner) {
14582
+ if (canReclaimLease(leasePath, existingOwner) && reclaimLease(leasePath, existingOwner)) continue;
14583
+ return null;
14584
+ }
14585
+ return null;
14586
+ }
14587
+ return null;
14588
+ }
14589
+ function releaseLease(lease) {
14590
+ const currentOwner = readOwner(lease.leasePath);
14591
+ if (!currentOwner || !sameOwner2(currentOwner, lease.owner)) return false;
14592
+ const releasePath = `${lease.leasePath}.release.${lease.owner.pid}.${lease.owner.token}`;
14593
+ try {
14594
+ (0, import_node_fs.renameSync)(lease.leasePath, releasePath);
14595
+ } catch (error) {
14596
+ if (getErrorCode2(error) === "ENOENT") return false;
14597
+ throw error;
14598
+ }
14599
+ const claimedOwner = readOwner(releasePath);
14600
+ if (!claimedOwner || !sameOwner2(claimedOwner, lease.owner)) {
14601
+ if (!(0, import_node_fs.existsSync)(lease.leasePath) && (0, import_node_fs.existsSync)(releasePath)) {
14602
+ (0, import_node_fs.renameSync)(releasePath, lease.leasePath);
14603
+ }
14604
+ return false;
14605
+ }
14606
+ (0, import_node_fs.rmSync)(releasePath, { recursive: true, force: true });
14607
+ return true;
14608
+ }
14609
+ var BackgroundWorkerController = class {
14610
+ constructor(projectRoot, host, config, hooks, identity) {
14611
+ this.projectRoot = projectRoot;
14612
+ this.host = host;
14613
+ this.config = config;
14614
+ this.hooks = hooks;
14615
+ this.identity = identity;
14616
+ }
14617
+ projectRoot;
14618
+ host;
14619
+ config;
14620
+ hooks;
14621
+ identity;
14622
+ lease = null;
14623
+ watcher = null;
14624
+ leaderReady = Promise.resolve();
14625
+ heartbeatTimer = null;
14626
+ retryTimer = null;
14627
+ teardownRetryTimer = null;
14628
+ transition = Promise.resolve();
14629
+ stopPromise = null;
14630
+ stopped = false;
14631
+ stopping = false;
14632
+ losingLeadership = false;
14633
+ restartAfterStop = false;
14634
+ leaderWorkStopped = false;
14635
+ startingLeaderWork = false;
14636
+ stopAutoIndexOnTeardown = true;
14637
+ autoIndexStarted = false;
14638
+ reportedError = null;
14639
+ update(config, hooks, options) {
14640
+ const autoIndexWasEnabled = this.config.indexing.autoIndex;
14641
+ const shouldReplaceWatcher = this.watcher !== null && hooks.watcherFactory !== void 0 && (hooks.watcherFactory === null || hooks.replaceWatcher === true);
14642
+ this.config = config;
14643
+ this.hooks = {
14644
+ ...this.hooks,
14645
+ ...hooks,
14646
+ watcherFactory: hooks.watcherFactory === void 0 ? this.hooks.watcherFactory : hooks.watcherFactory,
14647
+ watcherFactoryForConfig: hooks.watcherFactoryForConfig === void 0 ? this.hooks.watcherFactoryForConfig : hooks.watcherFactoryForConfig
14648
+ };
14649
+ if (autoIndexWasEnabled && !config.indexing.autoIndex || options.restartAutoIndex === true && config.indexing.autoIndex && !this.startingLeaderWork) {
14650
+ this.autoIndexStarted = false;
14651
+ }
14652
+ if (!this.canRun()) {
14653
+ void this.stop().catch((error) => {
14654
+ console.error("[codebase-index] Failed to stop background worker after disabling automatic work:", error);
14655
+ });
14656
+ return;
14657
+ }
14658
+ if (shouldReplaceWatcher) {
14659
+ void this.enqueue(async () => {
14660
+ const watcher = this.watcher;
14661
+ if (watcher) {
14662
+ await watcher.stop();
14663
+ if (this.watcher === watcher) this.watcher = null;
14664
+ }
14665
+ if (this.lease && !this.stopped) this.startLeaderWork();
14666
+ }).catch((error) => {
14667
+ console.error("[codebase-index] Failed to replace background file watcher:", error);
14668
+ });
14669
+ }
14670
+ this.start();
14671
+ }
14672
+ startAfter(activation) {
14673
+ this.transition = activation.catch(() => void 0);
14674
+ this.start();
14675
+ }
14676
+ start() {
14677
+ if (!this.canRun() || this.losingLeadership) return;
14678
+ if (this.stopping) {
14679
+ this.restartAfterStop = true;
14680
+ return;
14681
+ }
14682
+ this.stopped = false;
14683
+ void this.enqueue(async () => {
14684
+ if (this.stopped || this.stopping || this.losingLeadership || !this.canRun()) return;
14685
+ if (!this.lease) {
14686
+ try {
14687
+ this.lease = acquireLease(this.identity);
14688
+ this.reportedError = null;
14689
+ } catch (error) {
14690
+ this.reportAcquireError(error);
14691
+ this.scheduleRetry();
14692
+ return;
14693
+ }
14694
+ }
14695
+ if (!this.lease) {
14696
+ this.scheduleRetry();
14697
+ return;
14698
+ }
14699
+ this.startHeartbeat();
14700
+ this.startLeaderWork();
14701
+ });
14702
+ }
14703
+ waitForStart() {
14704
+ return this.transition.catch(() => void 0).then(() => this.leaderReady);
14705
+ }
14706
+ requestRefresh(allowDisabledAutoIndex = false) {
14707
+ this.start();
14708
+ if (!this.isLeader()) {
14709
+ requestRefreshFromLeader(leasePathFor(this.identity), allowDisabledAutoIndex);
14710
+ return;
14711
+ }
14712
+ void this.enqueue(async () => {
14713
+ if (this.stopped || !this.lease) return;
14714
+ this.hooks.startAutoIndex("retrieval", allowDisabledAutoIndex);
14715
+ });
14716
+ }
14717
+ isLeader() {
14718
+ return this.lease !== null && !this.stopping && !this.losingLeadership;
14719
+ }
14720
+ isStopping() {
14721
+ return this.stopping;
14722
+ }
14723
+ getHooksForConfig(config) {
14724
+ const watcherFactoryForConfig = this.hooks.watcherFactoryForConfig;
14725
+ if (!watcherFactoryForConfig) return this.hooks;
14726
+ return {
14727
+ ...this.hooks,
14728
+ watcherFactory: watcherFactoryForConfig(config),
14729
+ replaceWatcher: true
14730
+ };
14731
+ }
14732
+ attachWatcher(watcherFactory, watcherFactoryForConfig) {
14733
+ if (this.hooks.watcherFactory !== void 0) return;
14734
+ this.hooks = {
14735
+ ...this.hooks,
14736
+ watcherFactory,
14737
+ watcherFactoryForConfig: watcherFactoryForConfig ?? this.hooks.watcherFactoryForConfig
14738
+ };
14739
+ this.start();
14740
+ }
14741
+ async stop(stopAutoIndex = true) {
14742
+ if (this.stopPromise) return this.stopPromise;
14743
+ this.stopped = true;
14744
+ this.stopping = true;
14745
+ this.stopAutoIndexOnTeardown &&= stopAutoIndex;
14746
+ this.clearRetryTimer();
14747
+ const attempt = this.enqueue(async () => {
14748
+ try {
14749
+ const lease = this.lease;
14750
+ if (this.leaderWorkStopped) {
14751
+ if (lease) {
14752
+ this.releaseStoppedLease(lease);
14753
+ } else {
14754
+ this.finishStoppedLease();
14755
+ }
14756
+ return;
14757
+ }
14758
+ const hadLeaderWork = lease !== null || this.watcher !== null || this.autoIndexStarted;
14759
+ const stopped = await this.stopLeaderWork(hadLeaderWork && this.stopAutoIndexOnTeardown);
14760
+ if (!lease) {
14761
+ this.finishStoppedLease();
14762
+ return;
14763
+ }
14764
+ if (!stopped.completed) {
14765
+ this.releaseLeaseWhenAutoIndexStops(lease, stopped.completion);
14766
+ return;
14767
+ }
14768
+ this.leaderWorkStopped = true;
14769
+ this.releaseStoppedLease(lease);
14770
+ } catch (error) {
14771
+ this.scheduleTeardownRetry();
14772
+ throw error;
14773
+ }
14774
+ });
14775
+ const completion = attempt.finally(() => {
14776
+ if (this.stopPromise === completion) this.stopPromise = null;
14777
+ });
14778
+ this.stopPromise = completion;
14779
+ return completion;
14780
+ }
14781
+ canRun() {
14782
+ return this.config.indexing.autoIndex || this.hooks.watcherFactory != null;
14783
+ }
14784
+ enqueue(operation) {
14785
+ const next = this.transition.catch(() => void 0).then(operation);
14786
+ this.transition = next;
14787
+ return next;
14788
+ }
14789
+ startLeaderWork() {
14790
+ if (this.stopped || this.stopping || this.losingLeadership) return;
14791
+ this.startingLeaderWork = true;
14792
+ try {
14793
+ if (this.config.indexing.autoIndex && !this.autoIndexStarted) {
14794
+ this.autoIndexStarted = true;
14795
+ this.hooks.startAutoIndex("startup");
14796
+ }
14797
+ if (!this.watcher && this.hooks.watcherFactory) {
14798
+ try {
14799
+ const watcher = this.hooks.watcherFactory();
14800
+ this.watcher = watcher;
14801
+ this.leaderReady = watcher.whenReady?.().catch((error) => {
14802
+ console.error("[codebase-index] Failed while waiting for background file watcher startup:", error);
14803
+ }) ?? Promise.resolve();
14804
+ } catch (error) {
14805
+ console.error("[codebase-index] Failed to start background file watcher:", error);
14806
+ this.leaderReady = Promise.resolve();
14807
+ }
14808
+ }
14809
+ } finally {
14810
+ this.startingLeaderWork = false;
14811
+ }
14812
+ }
14813
+ async stopLeaderWork(stopAutoIndex) {
14814
+ const watcher = this.watcher;
14815
+ let watcherError;
14816
+ if (watcher) {
14817
+ try {
14818
+ await watcher.stop();
14819
+ if (this.watcher === watcher) this.watcher = null;
14820
+ } catch (error) {
14821
+ watcherError = error;
14822
+ }
14823
+ }
14824
+ let autoIndexError;
14825
+ let autoIndexStop = {
14826
+ completed: true,
14827
+ completion: Promise.resolve()
14828
+ };
14829
+ if (stopAutoIndex) {
14830
+ try {
14831
+ autoIndexStop = await this.hooks.stopAutoIndex();
14832
+ this.autoIndexStarted = false;
14833
+ } catch (error) {
14834
+ autoIndexError = error;
14835
+ }
14836
+ }
14837
+ if (watcherError !== void 0 || autoIndexError !== void 0) {
14838
+ throw new BackgroundWorkerStopError(watcherError, autoIndexError);
14839
+ }
14840
+ return autoIndexStop;
14841
+ }
14842
+ releaseLeaseWhenAutoIndexStops(lease, completion) {
14843
+ void completion.then(
14844
+ () => {
14845
+ void this.enqueue(async () => {
14846
+ if (this.lease !== lease || !this.stopping) return;
14847
+ this.leaderWorkStopped = true;
14848
+ this.releaseStoppedLease(lease);
14849
+ }).catch((error) => {
14850
+ console.error("[codebase-index] Failed to release background worker lease after automatic indexing stopped:", error);
14851
+ this.scheduleTeardownRetry();
14852
+ });
14853
+ },
14854
+ (error) => {
14855
+ console.error("[codebase-index] Failed while waiting for automatic indexing to stop:", error);
14856
+ this.scheduleTeardownRetry();
14857
+ }
14858
+ );
14859
+ }
14860
+ releaseStoppedLease(lease) {
14861
+ if (this.lease !== lease) {
14862
+ this.finishStoppedLease();
14863
+ return;
14864
+ }
14865
+ releaseLease(lease);
14866
+ this.lease = null;
14867
+ this.finishStoppedLease();
14868
+ }
14869
+ finishStoppedLease() {
14870
+ this.leaderWorkStopped = false;
14871
+ this.stopAutoIndexOnTeardown = true;
14872
+ this.stopping = false;
14873
+ this.clearTimers();
14874
+ this.restartAfterTeardown();
14875
+ if (!this.stopped || this.stopping) return;
14876
+ const projectKey = projectLookupKey(this.projectRoot, this.host);
14877
+ const key = controllerKey(this.identity, this.host);
14878
+ if (workers.get(key) === this) workers.delete(key);
14879
+ if (workerKeysByProject.get(projectKey) === key) workerKeysByProject.delete(projectKey);
14880
+ }
14881
+ startHeartbeat() {
14882
+ if (this.heartbeatTimer) return;
14883
+ const heartbeat = () => {
14884
+ void this.heartbeat();
14885
+ };
14886
+ this.heartbeatTimer = setInterval(heartbeat, HEARTBEAT_INTERVAL_MS);
14887
+ this.heartbeatTimer.unref?.();
14888
+ }
14889
+ async heartbeat() {
14890
+ const lease = this.lease;
14891
+ if (!lease || this.losingLeadership || this.stopped && !this.stopping) return;
14892
+ if (hasActiveReclaimMarker(lease.leasePath, lease.owner)) {
14893
+ await this.loseLeadership();
14894
+ return;
14895
+ }
14896
+ const currentOwner = readOwner(lease.leasePath);
14897
+ if (!currentOwner || !sameOwner2(currentOwner, lease.owner)) {
14898
+ await this.loseLeadership();
14899
+ return;
14900
+ }
14901
+ try {
14902
+ const nextOwner = { ...lease.owner, heartbeatAt: (/* @__PURE__ */ new Date()).toISOString() };
14903
+ if (!writeHeartbeat(lease.leasePath, nextOwner)) {
14904
+ await this.loseLeadership();
14905
+ return;
14906
+ }
14907
+ lease.owner = nextOwner;
14908
+ const refreshRequest = !this.stopping ? consumeRefreshRequest(lease.leasePath) : null;
14909
+ if (refreshRequest) {
14910
+ this.hooks.startAutoIndex("retrieval", refreshRequest.allowDisabledAutoIndex);
14911
+ }
14912
+ } catch (error) {
14913
+ const ownerAfterError = readOwner(lease.leasePath);
14914
+ if (hasActiveReclaimMarker(lease.leasePath, lease.owner) || !ownerAfterError || !sameOwner2(ownerAfterError, lease.owner)) {
14915
+ await this.loseLeadership();
14916
+ return;
14917
+ }
14918
+ console.error("[codebase-index] Failed to renew background worker lease:", error);
14919
+ }
14920
+ }
14921
+ async loseLeadership() {
14922
+ if (this.losingLeadership) return;
14923
+ this.losingLeadership = true;
14924
+ this.clearHeartbeat();
14925
+ await this.enqueue(async () => this.stopAfterLeadershipLoss());
14926
+ }
14927
+ async stopAfterLeadershipLoss() {
14928
+ const lease = this.lease;
14929
+ if (!lease) {
14930
+ this.losingLeadership = false;
14931
+ return;
14932
+ }
14933
+ try {
14934
+ const stopped = await this.stopLeaderWork(true);
14935
+ this.lease = null;
14936
+ this.losingLeadership = false;
14937
+ if (stopped.completed) {
14938
+ this.scheduleRetry();
14939
+ } else {
14940
+ void stopped.completion.then(() => this.scheduleRetry());
14941
+ }
14942
+ } catch (error) {
14943
+ console.error("[codebase-index] Failed to stop background work after losing its lease:", error);
14944
+ this.scheduleLostLeadershipTeardownRetry();
14945
+ }
14946
+ }
14947
+ scheduleRetry() {
14948
+ if (this.stopped || !this.canRun() || this.retryTimer) return;
14949
+ this.retryTimer = setTimeout(() => {
14950
+ this.retryTimer = null;
14951
+ this.start();
14952
+ }, RETRY_DELAY_MS);
14953
+ this.retryTimer.unref?.();
14954
+ }
14955
+ scheduleTeardownRetry() {
14956
+ if (!this.stopping || this.teardownRetryTimer) return;
14957
+ this.teardownRetryTimer = setTimeout(() => {
14958
+ this.teardownRetryTimer = null;
14959
+ void this.stop(this.stopAutoIndexOnTeardown).catch((error) => {
14960
+ console.error("[codebase-index] Failed to retry background worker teardown:", error);
14961
+ });
14962
+ }, RETRY_DELAY_MS);
14963
+ this.teardownRetryTimer.unref?.();
14964
+ }
14965
+ restartAfterTeardown() {
14966
+ if (!this.restartAfterStop || !this.canRun() || this.losingLeadership) return;
14967
+ this.restartAfterStop = false;
14968
+ this.stopped = false;
14969
+ this.start();
14970
+ }
14971
+ scheduleLostLeadershipTeardownRetry() {
14972
+ if (this.stopped || !this.losingLeadership || this.retryTimer) return;
14973
+ this.retryTimer = setTimeout(() => {
14974
+ this.retryTimer = null;
14975
+ void this.enqueue(async () => this.stopAfterLeadershipLoss());
14976
+ }, RETRY_DELAY_MS);
14977
+ this.retryTimer.unref?.();
14978
+ }
14979
+ clearHeartbeat() {
14980
+ if (!this.heartbeatTimer) return;
14981
+ clearInterval(this.heartbeatTimer);
14982
+ this.heartbeatTimer = null;
14983
+ }
14984
+ clearTimers() {
14985
+ this.clearHeartbeat();
14986
+ this.clearRetryTimer();
14987
+ if (this.teardownRetryTimer) {
14988
+ clearTimeout(this.teardownRetryTimer);
14989
+ this.teardownRetryTimer = null;
14990
+ }
14991
+ }
14992
+ clearRetryTimer() {
14993
+ if (!this.retryTimer) return;
14994
+ clearTimeout(this.retryTimer);
14995
+ this.retryTimer = null;
14996
+ }
14997
+ reportAcquireError(error) {
14998
+ const message = error instanceof Error ? error.message : String(error);
14999
+ if (this.reportedError === message) return;
15000
+ this.reportedError = message;
15001
+ console.error("[codebase-index] Failed to acquire background worker lease:", error);
15002
+ }
15003
+ };
15004
+ function configureBackgroundWorker(projectRoot, host, config, hooks, options = {}) {
15005
+ const projectKey = projectLookupKey(projectRoot, host);
15006
+ const identity = resolveIdentity(projectRoot, config, host);
15007
+ const key = controllerKey(identity, host);
15008
+ const previousKey = workerKeysByProject.get(projectKey);
15009
+ if (previousKey && previousKey !== key) {
15010
+ const previous = workers.get(previousKey);
15011
+ const previousBarrier = workerReplacementBarriers.get(projectKey) ?? Promise.resolve();
15012
+ const stopPrevious = previous?.stop(options.stopPreviousAutoIndex ?? true) ?? Promise.resolve();
15013
+ const activation = Promise.all([previousBarrier, stopPrevious]).then(() => void 0);
15014
+ workerReplacementBarriers.set(projectKey, activation);
15015
+ workers.delete(previousKey);
15016
+ const worker2 = new BackgroundWorkerController(projectRoot, host, config, hooks, identity);
15017
+ worker2.startAfter(activation);
15018
+ workers.set(key, worker2);
15019
+ workerKeysByProject.set(projectKey, key);
15020
+ return;
15021
+ }
15022
+ let worker = workers.get(key);
15023
+ if (!worker) {
15024
+ worker = new BackgroundWorkerController(projectRoot, host, config, hooks, identity);
15025
+ workers.set(key, worker);
15026
+ } else {
15027
+ worker.update(config, hooks, options);
15028
+ }
15029
+ workerKeysByProject.set(projectKey, key);
15030
+ worker.start();
15031
+ }
15032
+ function attachBackgroundWorkerWatcher(projectRoot, host, watcherFactory, watcherFactoryForConfig) {
15033
+ const key = workerKeysByProject.get(projectLookupKey(projectRoot, host));
15034
+ workers.get(key ?? "")?.attachWatcher(watcherFactory, watcherFactoryForConfig);
15035
+ }
15036
+ function updateBackgroundWorkerConfig(projectRoot, host, config) {
15037
+ const projectKey = projectLookupKey(projectRoot, host);
15038
+ const key = workerKeysByProject.get(projectKey);
15039
+ const worker = key ? workers.get(key) : void 0;
15040
+ if (!worker) return;
15041
+ configureBackgroundWorker(projectRoot, host, config, worker.getHooksForConfig(config), {
15042
+ stopPreviousAutoIndex: false,
15043
+ restartAutoIndex: true
15044
+ });
15045
+ }
15046
+ function requestBackgroundWorker(projectRoot, host) {
15047
+ const key = workerKeysByProject.get(projectLookupKey(projectRoot, host));
15048
+ workers.get(key ?? "")?.start();
15049
+ }
15050
+ function waitForBackgroundWorkerStart(projectRoot, host) {
15051
+ const key = workerKeysByProject.get(projectLookupKey(projectRoot, host));
15052
+ return workers.get(key ?? "")?.waitForStart() ?? Promise.resolve();
15053
+ }
15054
+ function requestBackgroundWorkerRefresh(projectRoot, host, allowDisabledAutoIndex = false) {
15055
+ const key = workerKeysByProject.get(projectLookupKey(projectRoot, host));
15056
+ workers.get(key ?? "")?.requestRefresh(allowDisabledAutoIndex);
15057
+ }
15058
+ function isBackgroundWorkerManaged(projectRoot, host) {
15059
+ const key = workerKeysByProject.get(projectLookupKey(projectRoot, host));
15060
+ return key !== void 0 && workers.has(key);
15061
+ }
15062
+ function isBackgroundWorkerLeader(projectRoot, host) {
15063
+ const key = workerKeysByProject.get(projectLookupKey(projectRoot, host));
15064
+ return key !== void 0 && workers.get(key)?.isLeader() === true;
15065
+ }
15066
+ function isBackgroundWorkerStopping(projectRoot, host) {
15067
+ const key = workerKeysByProject.get(projectLookupKey(projectRoot, host));
15068
+ return key !== void 0 && workers.get(key)?.isStopping() === true;
15069
+ }
15070
+ async function stopBackgroundWorker(projectRoot, host) {
15071
+ const projectKey = projectLookupKey(projectRoot, host);
15072
+ const key = workerKeysByProject.get(projectKey);
15073
+ const worker = key ? workers.get(key) : void 0;
15074
+ if (!worker) return;
15075
+ await worker.stop();
15076
+ }
14161
15077
 
14162
15078
  // src/utils/power-source.ts
14163
15079
  var childProcess = __toESM(require("child_process"), 1);
@@ -14167,7 +15083,7 @@ function getErrorMessage4(error) {
14167
15083
  return error instanceof Error ? error.message : String(error);
14168
15084
  }
14169
15085
  function runCommand(file, args, options) {
14170
- return new Promise((resolve20, reject) => {
15086
+ return new Promise((resolve21, reject) => {
14171
15087
  childProcess.execFile(
14172
15088
  file,
14173
15089
  args,
@@ -14177,7 +15093,7 @@ function runCommand(file, args, options) {
14177
15093
  reject(error);
14178
15094
  return;
14179
15095
  }
14180
- resolve20(stdout);
15096
+ resolve21(stdout);
14181
15097
  }
14182
15098
  );
14183
15099
  });
@@ -14269,8 +15185,8 @@ var AutoIndexCancelledError = class extends Error {
14269
15185
  function now() {
14270
15186
  return (/* @__PURE__ */ new Date()).toISOString();
14271
15187
  }
14272
- function canonicalizePath(targetPath) {
14273
- const resolved = path17.resolve(targetPath);
15188
+ function canonicalizePath2(targetPath) {
15189
+ const resolved = path18.resolve(targetPath);
14274
15190
  if ((0, import_fs11.existsSync)(resolved)) {
14275
15191
  try {
14276
15192
  return import_fs11.realpathSync.native(resolved);
@@ -14278,20 +15194,20 @@ function canonicalizePath(targetPath) {
14278
15194
  return resolved;
14279
15195
  }
14280
15196
  }
14281
- const parent = path17.dirname(resolved);
15197
+ const parent = path18.dirname(resolved);
14282
15198
  if (parent === resolved) return resolved;
14283
- return path17.join(canonicalizePath(parent), path17.basename(resolved));
15199
+ return path18.join(canonicalizePath2(parent), path18.basename(resolved));
14284
15200
  }
14285
15201
  function isHomeDirectory(projectRoot) {
14286
- return canonicalizePath(projectRoot) === canonicalizePath(os6.homedir());
15202
+ return canonicalizePath2(projectRoot) === canonicalizePath2(os7.homedir());
14287
15203
  }
14288
- function projectLookupKey(projectRoot, host) {
14289
- return `${host}::${canonicalizePath(projectRoot)}`;
15204
+ function projectLookupKey2(projectRoot, host) {
15205
+ return `${host}::${canonicalizePath2(projectRoot)}`;
14290
15206
  }
14291
15207
  function coordinatorKey(projectRoot, config, host) {
14292
- const canonicalProjectRoot = canonicalizePath(projectRoot);
15208
+ const canonicalProjectRoot = canonicalizePath2(projectRoot);
14293
15209
  const indexPath = resolveProjectIndexPath(projectRoot, config.scope, host);
14294
- return `${canonicalizePath(indexPath)}::${canonicalProjectRoot}`;
15210
+ return `${canonicalizePath2(indexPath)}::${canonicalProjectRoot}`;
14295
15211
  }
14296
15212
  function getProjectSafety(projectRoot, config) {
14297
15213
  if (isHomeDirectory(projectRoot)) {
@@ -14322,10 +15238,10 @@ function safeFailureMessage(error) {
14322
15238
  }
14323
15239
  function cancellableDelay(delayMs, signal) {
14324
15240
  if (signal.aborted) return Promise.reject(new AutoIndexCancelledError());
14325
- return new Promise((resolve20, reject) => {
15241
+ return new Promise((resolve21, reject) => {
14326
15242
  const timer = setTimeout(() => {
14327
15243
  signal.removeEventListener("abort", onAbort);
14328
- resolve20();
15244
+ resolve21();
14329
15245
  }, delayMs);
14330
15246
  timer.unref?.();
14331
15247
  const onAbort = () => {
@@ -14337,18 +15253,44 @@ function cancellableDelay(delayMs, signal) {
14337
15253
  }
14338
15254
  function withTimeout(promise, timeoutMs) {
14339
15255
  if (timeoutMs <= 0) return Promise.resolve(void 0);
14340
- return new Promise((resolve20) => {
14341
- const timer = setTimeout(() => resolve20(void 0), timeoutMs);
15256
+ return new Promise((resolve21) => {
15257
+ const timer = setTimeout(() => resolve21(void 0), timeoutMs);
14342
15258
  timer.unref?.();
14343
15259
  void promise.then((value) => {
14344
15260
  clearTimeout(timer);
14345
- resolve20(value);
15261
+ resolve21(value);
14346
15262
  }, () => {
14347
15263
  clearTimeout(timer);
14348
- resolve20(void 0);
15264
+ resolve21(void 0);
14349
15265
  });
14350
15266
  });
14351
15267
  }
15268
+ function settlesWithin(promise, timeoutMs) {
15269
+ if (timeoutMs <= 0) return Promise.resolve(false);
15270
+ return new Promise((resolve21) => {
15271
+ let settled = false;
15272
+ const timer = setTimeout(() => {
15273
+ if (settled) return;
15274
+ settled = true;
15275
+ resolve21(false);
15276
+ }, timeoutMs);
15277
+ timer.unref?.();
15278
+ void promise.then(
15279
+ () => {
15280
+ if (settled) return;
15281
+ settled = true;
15282
+ clearTimeout(timer);
15283
+ resolve21(true);
15284
+ },
15285
+ () => {
15286
+ if (settled) return;
15287
+ settled = true;
15288
+ clearTimeout(timer);
15289
+ resolve21(true);
15290
+ }
15291
+ );
15292
+ });
15293
+ }
14352
15294
  function requestPriority(request) {
14353
15295
  if (request.force) return 4;
14354
15296
  if (request.source === "manual") return 3;
@@ -14359,6 +15301,7 @@ function mergeRequests(current, next) {
14359
15301
  if (!current) return next;
14360
15302
  const preferred = requestPriority(next) > requestPriority(current) ? next : current;
14361
15303
  return {
15304
+ allowDisabledAutoIndex: current.allowDisabledAutoIndex || next.allowDisabledAutoIndex,
14362
15305
  checkFreshness: current.checkFreshness && next.checkFreshness,
14363
15306
  force: current.force || next.force,
14364
15307
  onProgress: next.onProgress ?? current.onProgress,
@@ -14420,11 +15363,11 @@ var AutoIndexCoordinator = class {
14420
15363
  progress: this.status.progress ? { ...this.status.progress } : void 0
14421
15364
  };
14422
15365
  }
14423
- start(source) {
15366
+ start(source, allowDisabledAutoIndex = false) {
14424
15367
  this.refreshSafety();
14425
- if (!this.registration.config.indexing.autoIndex || !this.registration.safeToRun) return null;
15368
+ if (!this.registration.config.indexing.autoIndex && !allowDisabledAutoIndex || !this.registration.safeToRun) return null;
14426
15369
  if (this.status.state === "failed") return this.inFlight;
14427
- return this.request({ checkFreshness: true, force: false, source });
15370
+ return this.request({ allowDisabledAutoIndex, checkFreshness: true, force: false, source });
14428
15371
  }
14429
15372
  request(request) {
14430
15373
  if (this.stopped) {
@@ -14499,13 +15442,15 @@ var AutoIndexCoordinator = class {
14499
15442
  retryAttempt: void 0
14500
15443
  });
14501
15444
  const inFlight = this.inFlight;
14502
- if (inFlight) {
14503
- if (waitForCompletion) {
14504
- await inFlight;
14505
- } else {
14506
- await withTimeout(inFlight, SHUTDOWN_WAIT_MS);
14507
- }
15445
+ const completion = inFlight ? inFlight.then(() => void 0, () => void 0) : Promise.resolve();
15446
+ if (!inFlight) {
15447
+ return { completed: true, completion };
14508
15448
  }
15449
+ if (waitForCompletion) {
15450
+ await completion;
15451
+ return { completed: true, completion };
15452
+ }
15453
+ return { completed: await settlesWithin(completion, SHUTDOWN_WAIT_MS), completion };
14509
15454
  }
14510
15455
  startRequest(request) {
14511
15456
  if (this.stopped || !this.canRun(request)) {
@@ -14694,7 +15639,7 @@ var AutoIndexCoordinator = class {
14694
15639
  if (request.source === "manual" || request.source === "watcher") {
14695
15640
  return true;
14696
15641
  }
14697
- return this.registration.safeToRun && this.registration.config.indexing.autoIndex;
15642
+ return this.registration.safeToRun && (this.registration.config.indexing.autoIndex || request.allowDisabledAutoIndex === true);
14698
15643
  }
14699
15644
  shouldDeferForBattery(request) {
14700
15645
  return this.registration.backgroundIndexingPolicy !== null && (request.source === "startup" || request.source === "watcher");
@@ -14727,17 +15672,17 @@ var AutoIndexCoordinator = class {
14727
15672
  }
14728
15673
  }
14729
15674
  waitForBatteryRetry(delayMs) {
14730
- return new Promise((resolve20) => {
15675
+ return new Promise((resolve21) => {
14731
15676
  const timer = setTimeout(() => {
14732
15677
  if (this.batteryRetryTimer === timer) {
14733
15678
  this.batteryRetryTimer = null;
14734
15679
  this.resolveBatteryRetry = null;
14735
15680
  }
14736
- resolve20();
15681
+ resolve21();
14737
15682
  }, delayMs);
14738
15683
  timer.unref?.();
14739
15684
  this.batteryRetryTimer = timer;
14740
- this.resolveBatteryRetry = resolve20;
15685
+ this.resolveBatteryRetry = resolve21;
14741
15686
  });
14742
15687
  }
14743
15688
  cancelBatteryRetry() {
@@ -14745,9 +15690,9 @@ var AutoIndexCoordinator = class {
14745
15690
  clearTimeout(this.batteryRetryTimer);
14746
15691
  this.batteryRetryTimer = null;
14747
15692
  }
14748
- const resolve20 = this.resolveBatteryRetry;
15693
+ const resolve21 = this.resolveBatteryRetry;
14749
15694
  this.resolveBatteryRetry = null;
14750
- resolve20?.();
15695
+ resolve21?.();
14751
15696
  }
14752
15697
  finishBatteryCheck(batteryCheck) {
14753
15698
  if (this.batteryCheck !== batteryCheck) return;
@@ -14760,12 +15705,25 @@ var AutoIndexCoordinator = class {
14760
15705
  }
14761
15706
  };
14762
15707
  function getCoordinator(projectRoot, host) {
14763
- const key = coordinatorKeysByProject.get(projectLookupKey(projectRoot, host));
15708
+ const key = coordinatorKeysByProject.get(projectLookupKey2(projectRoot, host));
14764
15709
  return key ? coordinators.get(key) ?? null : null;
14765
15710
  }
14766
- function configureAutoIndex(projectRoot, host, config, getIndexer) {
14767
- const projectKey = projectLookupKey(projectRoot, host);
15711
+ function synchronizeBackgroundWorker(projectRoot, host, config, safeToRun) {
15712
+ if (safeToRun) {
15713
+ updateBackgroundWorkerConfig(projectRoot, host, config);
15714
+ return;
15715
+ }
15716
+ void stopBackgroundWorker(projectRoot, host).catch((error) => {
15717
+ console.error("[codebase-index] Failed to stop background worker after project safety changed:", error);
15718
+ });
15719
+ }
15720
+ function configureAutoIndex(projectRoot, host, config, getIndexer, options = {}) {
15721
+ const projectKey = projectLookupKey2(projectRoot, host);
14768
15722
  const safety = getProjectSafety(projectRoot, config);
15723
+ const synchronizeWorker = options.synchronizeBackgroundWorker ?? true;
15724
+ if (options.preserveManagedWorker === true && isBackgroundWorkerManaged(projectRoot, host)) {
15725
+ return;
15726
+ }
14769
15727
  const registration = {
14770
15728
  backgroundIndexingPolicy: createBackgroundIndexingPolicy(
14771
15729
  config.indexing.pauseBackgroundIndexingOnBattery
@@ -14783,6 +15741,9 @@ function configureAutoIndex(projectRoot, host, config, getIndexer) {
14783
15741
  const stopPrevious = previousCoordinator?.stop(true) ?? Promise.resolve();
14784
15742
  const activation = Promise.all([previousBarrier, stopPrevious]).then(() => void 0);
14785
15743
  coordinatorReplacementBarriers.set(projectKey, activation);
15744
+ if (synchronizeWorker) {
15745
+ synchronizeBackgroundWorker(projectRoot, host, config, safety.safeToRun);
15746
+ }
14786
15747
  coordinators.delete(previousKey);
14787
15748
  const coordinator2 = new AutoIndexCoordinator(registration);
14788
15749
  coordinator2.activateAfter(activation);
@@ -14798,11 +15759,17 @@ function configureAutoIndex(projectRoot, host, config, getIndexer) {
14798
15759
  coordinator.update(registration);
14799
15760
  }
14800
15761
  coordinatorKeysByProject.set(projectKey, key);
15762
+ if (synchronizeWorker) {
15763
+ synchronizeBackgroundWorker(projectRoot, host, config, safety.safeToRun);
15764
+ }
14801
15765
  }
14802
- function startAutoIndex(projectRoot, host, source = "startup") {
14803
- return getCoordinator(projectRoot, host)?.start(source) ?? null;
15766
+ function startAutoIndexForBackgroundWorker(projectRoot, host, source = "startup", allowDisabledAutoIndex = false) {
15767
+ return getCoordinator(projectRoot, host)?.start(source, allowDisabledAutoIndex) ?? null;
14804
15768
  }
14805
15769
  function requestBackgroundIndex(projectRoot, host) {
15770
+ if (isBackgroundWorkerManaged(projectRoot, host) && !isBackgroundWorkerLeader(projectRoot, host)) {
15771
+ return null;
15772
+ }
14806
15773
  return getCoordinator(projectRoot, host)?.request({
14807
15774
  checkFreshness: false,
14808
15775
  force: false,
@@ -14842,15 +15809,23 @@ async function waitForAutoIndexForRetrieval(projectRoot, host) {
14842
15809
  };
14843
15810
  }
14844
15811
  try {
14845
- if (await hasReadableCurrentIndex(coordinator)) return { ready: true };
15812
+ const readiness = await getSearchReadiness(coordinator);
15813
+ if (readiness.searchable) {
15814
+ return { ready: true };
15815
+ }
15816
+ if (readiness.blocked) return unavailableSnapshotResult(readiness.reason);
14846
15817
  } catch {
14847
15818
  }
14848
- const job = coordinator.start("retrieval") ?? coordinator.currentJob();
15819
+ const job = startRetrievalRefresh(projectRoot, host, coordinator);
14849
15820
  if (job) {
14850
15821
  await withTimeout(job, coordinator.getWaitMs());
15822
+ } else if (isBackgroundWorkerManaged(projectRoot, host)) {
15823
+ await waitForPublishedSnapshot(coordinator, coordinator.getWaitMs());
14851
15824
  }
14852
15825
  try {
14853
- if (await hasReadableCurrentIndex(coordinator)) return { ready: true };
15826
+ const readiness = await getSearchReadiness(coordinator);
15827
+ if (readiness.searchable) return { ready: true };
15828
+ if (readiness.blocked) return unavailableSnapshotResult(readiness.reason);
14854
15829
  } catch {
14855
15830
  }
14856
15831
  const status = coordinator.snapshot();
@@ -14871,31 +15846,62 @@ async function waitForAutoIndexForRetrieval(projectRoot, host) {
14871
15846
  text: `Automatic indexing is ${status.state}. Retry shortly or call index_status for progress. You can also run index_codebase explicitly.`
14872
15847
  };
14873
15848
  }
14874
- async function stopAutoIndex(projectRoot, host) {
14875
- await getCoordinator(projectRoot, host)?.stop();
15849
+ async function stopAutoIndexForBackgroundWorker(projectRoot, host, waitForCompletion = false) {
15850
+ const coordinator = getCoordinator(projectRoot, host);
15851
+ if (!coordinator) {
15852
+ return { completed: true, completion: Promise.resolve() };
15853
+ }
15854
+ return coordinator.stop(waitForCompletion);
14876
15855
  }
14877
- async function hasReadableCurrentIndex(coordinator) {
15856
+ async function getSearchReadiness(coordinator) {
14878
15857
  const indexer = coordinator.getIndexer();
14879
15858
  if (indexer.getIndexFreshness) {
14880
15859
  const freshness = await indexer.getIndexFreshness();
14881
- return freshness.readable && freshness.current;
15860
+ const searchable = freshness.readable && freshness.current && freshness.reason === "current";
15861
+ return {
15862
+ blocked: freshness.reason === "unreadable" || freshness.reason === "incompatible" || freshness.reason === "failed-batches" || freshness.reason === "migration-required",
15863
+ reason: freshness.reason,
15864
+ searchable
15865
+ };
15866
+ }
15867
+ const indexed = (await indexer.getStatus()).indexed;
15868
+ return { blocked: false, searchable: indexed };
15869
+ }
15870
+ function unavailableSnapshotResult(reason) {
15871
+ 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.";
15872
+ return {
15873
+ ready: false,
15874
+ text: `${detail} Run index_codebase before retrying retrieval.`
15875
+ };
15876
+ }
15877
+ function startRetrievalRefresh(projectRoot, host, coordinator) {
15878
+ if (isBackgroundWorkerManaged(projectRoot, host)) {
15879
+ requestBackgroundWorkerRefresh(projectRoot, host, true);
15880
+ return isBackgroundWorkerLeader(projectRoot, host) ? coordinator.currentJob() : null;
15881
+ }
15882
+ return coordinator.start("retrieval") ?? coordinator.currentJob();
15883
+ }
15884
+ async function waitForPublishedSnapshot(coordinator, waitMs) {
15885
+ const deadline = Date.now() + waitMs;
15886
+ while (Date.now() < deadline) {
15887
+ if ((await getSearchReadiness(coordinator)).searchable) return;
15888
+ await new Promise((resolve21) => setTimeout(resolve21, Math.min(250, deadline - Date.now())));
14882
15889
  }
14883
- return (await indexer.getStatus()).indexed;
14884
15890
  }
14885
15891
 
14886
15892
  // src/tools/config-state.ts
14887
15893
  var import_fs13 = require("fs");
14888
- var path20 = __toESM(require("path"), 1);
15894
+ var path21 = __toESM(require("path"), 1);
14889
15895
 
14890
15896
  // src/config/merger.ts
14891
15897
  var import_fs12 = require("fs");
14892
- var path19 = __toESM(require("path"), 1);
15898
+ var path20 = __toESM(require("path"), 1);
14893
15899
 
14894
15900
  // src/config/rebase.ts
14895
- var path18 = __toESM(require("path"), 1);
15901
+ var path19 = __toESM(require("path"), 1);
14896
15902
  function isWithinRoot(rootDir, targetPath) {
14897
- const relativePath = path18.relative(rootDir, targetPath);
14898
- return relativePath === "" || !relativePath.startsWith("..") && !path18.isAbsolute(relativePath);
15903
+ const relativePath = path19.relative(rootDir, targetPath);
15904
+ return relativePath === "" || !relativePath.startsWith("..") && !path19.isAbsolute(relativePath);
14899
15905
  }
14900
15906
  function rebasePathEntries(values, fromDir, toDir) {
14901
15907
  if (!Array.isArray(values)) {
@@ -14903,10 +15909,10 @@ function rebasePathEntries(values, fromDir, toDir) {
14903
15909
  }
14904
15910
  return values.filter((value) => typeof value === "string").map((value) => {
14905
15911
  const trimmed = value.trim();
14906
- if (!trimmed || path18.isAbsolute(trimmed)) {
15912
+ if (!trimmed || path19.isAbsolute(trimmed)) {
14907
15913
  return trimmed;
14908
15914
  }
14909
- return normalizePathSeparators(path18.normalize(path18.relative(toDir, path18.resolve(fromDir, trimmed))));
15915
+ return normalizePathSeparators(path19.normalize(path19.relative(toDir, path19.resolve(fromDir, trimmed))));
14910
15916
  }).filter(Boolean);
14911
15917
  }
14912
15918
  function resolveInheritedKnowledgeBaseEntries(values, sourceRoot, targetRoot) {
@@ -14918,17 +15924,17 @@ function resolveInheritedKnowledgeBaseEntries(values, sourceRoot, targetRoot) {
14918
15924
  if (!trimmed) {
14919
15925
  return trimmed;
14920
15926
  }
14921
- if (path18.isAbsolute(trimmed)) {
15927
+ if (path19.isAbsolute(trimmed)) {
14922
15928
  if (isWithinRoot(sourceRoot, trimmed)) {
14923
- return normalizePathSeparators(path18.normalize(path18.relative(sourceRoot, trimmed) || "."));
15929
+ return normalizePathSeparators(path19.normalize(path19.relative(sourceRoot, trimmed) || "."));
14924
15930
  }
14925
- return path18.normalize(trimmed);
15931
+ return path19.normalize(trimmed);
14926
15932
  }
14927
- const resolvedFromSource = path18.resolve(sourceRoot, trimmed);
15933
+ const resolvedFromSource = path19.resolve(sourceRoot, trimmed);
14928
15934
  if (isWithinRoot(sourceRoot, resolvedFromSource)) {
14929
- return normalizePathSeparators(path18.normalize(trimmed));
15935
+ return normalizePathSeparators(path19.normalize(trimmed));
14930
15936
  }
14931
- return normalizePathSeparators(path18.normalize(path18.relative(targetRoot, resolvedFromSource)));
15937
+ return normalizePathSeparators(path19.normalize(path19.relative(targetRoot, resolvedFromSource)));
14932
15938
  }).filter(Boolean);
14933
15939
  }
14934
15940
 
@@ -14966,8 +15972,8 @@ function mergeUniqueStringArray(values) {
14966
15972
  return [...new Set(values.map((value) => String(value).trim()))];
14967
15973
  }
14968
15974
  function normalizeKnowledgeBasePath2(value) {
14969
- let normalized = path19.normalize(String(value).trim());
14970
- const root = path19.parse(normalized).root;
15975
+ let normalized = path20.normalize(String(value).trim());
15976
+ const root = path20.parse(normalized).root;
14971
15977
  while (normalized.length > root.length && /[\\/]$/.test(normalized)) {
14972
15978
  normalized = normalized.slice(0, -1);
14973
15979
  }
@@ -15025,7 +16031,7 @@ function loadProjectConfigLayer(projectRoot, host) {
15025
16031
  return {};
15026
16032
  }
15027
16033
  const normalizedConfig = { ...projectConfig };
15028
- const projectConfigBaseDir = path19.dirname(path19.dirname(projectConfigPath));
16034
+ const projectConfigBaseDir = path20.dirname(path20.dirname(projectConfigPath));
15029
16035
  if (Array.isArray(normalizedConfig.knowledgeBases)) {
15030
16036
  normalizedConfig.knowledgeBases = resolveInheritedKnowledgeBaseEntries(
15031
16037
  normalizedConfig.knowledgeBases,
@@ -15115,8 +16121,8 @@ function loadEditableConfig(projectRoot, host) {
15115
16121
  }
15116
16122
  function saveConfig(projectRoot, config, host) {
15117
16123
  const configPath = getConfigPath(projectRoot, host);
15118
- const configDir = path20.dirname(configPath);
15119
- const configBaseDir = path20.dirname(configDir);
16124
+ const configDir = path21.dirname(configPath);
16125
+ const configBaseDir = path21.dirname(configDir);
15120
16126
  if (!(0, import_fs13.existsSync)(configDir)) {
15121
16127
  (0, import_fs13.mkdirSync)(configDir, { recursive: true });
15122
16128
  }
@@ -15205,15 +16211,24 @@ function getOrCreateIndexer(projectRoot, host) {
15205
16211
  }
15206
16212
  const indexer = new Indexer(projectRoot, config, host);
15207
16213
  indexerCache.set(key, indexer);
15208
- configureAutoIndex(projectRoot, host, config, () => getOrCreateIndexer(projectRoot, host));
16214
+ configureAutoIndex(projectRoot, host, config, () => getOrCreateIndexer(projectRoot, host), {
16215
+ preserveManagedWorker: true,
16216
+ synchronizeBackgroundWorker: false
16217
+ });
15209
16218
  return indexer;
15210
16219
  }
15211
- function initializeTools(projectRoot, config, host) {
16220
+ function initializeTools(projectRoot, config, host, options = {}) {
15212
16221
  defaultProjectRoots.set(host, projectRoot);
15213
16222
  const key = getIndexerCacheKey(projectRoot, host);
16223
+ if (options.preserveManagedWorker === true && isBackgroundWorkerManaged(projectRoot, host) && indexerCache.has(key)) {
16224
+ return;
16225
+ }
15214
16226
  configCache.set(key, config);
15215
16227
  indexerCache.set(key, new Indexer(projectRoot, config, host));
15216
- configureAutoIndex(projectRoot, host, config, () => getOrCreateIndexer(projectRoot, host));
16228
+ configureAutoIndex(projectRoot, host, config, () => getOrCreateIndexer(projectRoot, host), {
16229
+ preserveManagedWorker: options.preserveManagedWorker,
16230
+ synchronizeBackgroundWorker: false
16231
+ });
15217
16232
  }
15218
16233
  function getIndexerForProject(projectRoot, host) {
15219
16234
  const root = getProjectRoot(projectRoot, host);
@@ -15227,7 +16242,9 @@ function refreshIndexerForDirectory(projectRoot, host, config = parseConfig(load
15227
16242
  const key = getIndexerCacheKey(projectRoot, host);
15228
16243
  configCache.set(key, config);
15229
16244
  indexerCache.set(key, new Indexer(projectRoot, config, host));
15230
- configureAutoIndex(projectRoot, host, config, () => getOrCreateIndexer(projectRoot, host));
16245
+ configureAutoIndex(projectRoot, host, config, () => getOrCreateIndexer(projectRoot, host), {
16246
+ synchronizeBackgroundWorker: true
16247
+ });
15231
16248
  return config;
15232
16249
  }
15233
16250
  var AutoIndexRetrievalUnavailableError = class extends Error {
@@ -15254,7 +16271,7 @@ function trimOrUndefined(value) {
15254
16271
  return normalized || void 0;
15255
16272
  }
15256
16273
  function normalizeCallGraphPath(value) {
15257
- let normalized = path21.posix.normalize(value.trim().replaceAll("\\", "/"));
16274
+ let normalized = path22.posix.normalize(value.trim().replaceAll("\\", "/"));
15258
16275
  if (normalized.startsWith("./")) {
15259
16276
  normalized = normalized.slice(2);
15260
16277
  }
@@ -15447,12 +16464,12 @@ async function getCallGraphPath(projectRoot, host, from, to, maxDepth, fromFileP
15447
16464
  if (fromResolution.status !== "resolved" || toResolution.status !== "resolved") {
15448
16465
  return { from: fromResolution, to: toResolution, path: [] };
15449
16466
  }
15450
- const path33 = await indexer.findCallPathBySymbolIds(
16467
+ const path34 = await indexer.findCallPathBySymbolIds(
15451
16468
  fromResolution.symbolId,
15452
16469
  toResolution.symbolId,
15453
16470
  maxDepth
15454
16471
  );
15455
- return { from: fromResolution, to: toResolution, path: path33 };
16472
+ return { from: fromResolution, to: toResolution, path: path34 };
15456
16473
  }
15457
16474
  async function runIndexCodebase(projectRoot, host, args, onProgress) {
15458
16475
  const root = getProjectRoot(projectRoot, host);
@@ -15650,8 +16667,8 @@ async function getIndexLogs(projectRoot, host, args) {
15650
16667
  function addKnowledgeBase(projectRoot, host, knowledgeBasePath) {
15651
16668
  const root = getProjectRoot(projectRoot, host);
15652
16669
  const inputPath = knowledgeBasePath.trim();
15653
- const normalizedPath3 = path21.resolve(
15654
- path21.isAbsolute(inputPath) ? inputPath : resolveKnowledgeBasePath(inputPath, root)
16670
+ const normalizedPath3 = path22.resolve(
16671
+ path22.isAbsolute(inputPath) ? inputPath : resolveKnowledgeBasePath(inputPath, root)
15655
16672
  );
15656
16673
  if (!(0, import_fs14.existsSync)(normalizedPath3)) {
15657
16674
  return `Error: Directory does not exist: ${normalizedPath3}`;
@@ -15687,7 +16704,7 @@ function addKnowledgeBase(projectRoot, host, knowledgeBasePath) {
15687
16704
  }
15688
16705
  }
15689
16706
  for (const dotDir of sensitiveDotDirs) {
15690
- const sensitiveDir = path21.join(homeDir, dotDir);
16707
+ const sensitiveDir = path22.join(homeDir, dotDir);
15691
16708
  if (sensitiveDir && (realPath === sensitiveDir || realPath.startsWith(`${sensitiveDir}/`))) {
15692
16709
  return `Error: Adding sensitive directory as knowledge base is not allowed: ${normalizedPath3}`;
15693
16710
  }
@@ -15750,7 +16767,7 @@ function listKnowledgeBases(projectRoot, host) {
15750
16767
  }
15751
16768
  result += "\n";
15752
16769
  }
15753
- const hasHostConfig = (0, import_fs14.existsSync)(path21.join(root, getHostProjectConfigRelativePath(host)));
16770
+ const hasHostConfig = (0, import_fs14.existsSync)(path22.join(root, getHostProjectConfigRelativePath(host)));
15754
16771
  if (hasHostConfig) {
15755
16772
  result += `
15756
16773
  Config sources: 1 file(s).`;
@@ -16223,7 +17240,7 @@ async function resolveCodebaseContextUnmeasured(projectRoot, host, input) {
16223
17240
  const directory = input.directory ?? void 0;
16224
17241
  const tokenBudget = input.tokenBudget ?? void 0;
16225
17242
  if (from && to) {
16226
- const path33 = await getCallGraphPath(
17243
+ const path34 = await getCallGraphPath(
16227
17244
  projectRoot,
16228
17245
  host,
16229
17246
  from,
@@ -16232,25 +17249,25 @@ async function resolveCodebaseContextUnmeasured(projectRoot, host, input) {
16232
17249
  fromFilePath,
16233
17250
  toFilePath
16234
17251
  );
16235
- const pathText = formatCallGraphPathResult(path33);
16236
- if (path33.path.length > 0) {
17252
+ const pathText = formatCallGraphPathResult(path34);
17253
+ if (path34.path.length > 0) {
16237
17254
  const fitted2 = fitTextToContextBudget(
16238
17255
  pathText,
16239
17256
  tokenBudget
16240
17257
  );
16241
17258
  return {
16242
17259
  text: fitted2.text,
16243
- details: fittedDetails("path", fitted2, path33.path.length)
17260
+ details: fittedDetails("path", fitted2, path34.path.length)
16244
17261
  };
16245
17262
  }
16246
- if (path33.from.status !== "resolved" || path33.to.status !== "resolved") {
17263
+ if (path34.from.status !== "resolved" || path34.to.status !== "resolved") {
16247
17264
  const fitted2 = fitTextToContextBudget(pathText, tokenBudget);
16248
17265
  return {
16249
17266
  text: fitted2.text,
16250
17267
  details: fittedDetails("path", fitted2, 0)
16251
17268
  };
16252
17269
  }
16253
- const resolvedFrom = path33.from;
17270
+ const resolvedFrom = path34.from;
16254
17271
  const { callers } = await getCallGraphData(projectRoot, host, {
16255
17272
  name: to,
16256
17273
  direction: "callers",
@@ -16728,9 +17745,9 @@ function getRelevantEvidence(query) {
16728
17745
  });
16729
17746
  }
16730
17747
  if (query.expected.acceptableFiles) {
16731
- for (const path33 of query.expected.acceptableFiles) {
17748
+ for (const path34 of query.expected.acceptableFiles) {
16732
17749
  legacyEvidence.push({
16733
- path: path33,
17750
+ path: path34,
16734
17751
  ...query.expected.symbol !== void 0 ? { symbol: query.expected.symbol } : {},
16735
17752
  relevance: 1
16736
17753
  });
@@ -17053,8 +18070,8 @@ function computeEvalMetrics(queries, perQuery, embeddingCallCount, embeddingToke
17053
18070
 
17054
18071
  // src/eval/runner-config.ts
17055
18072
  var import_fs15 = require("fs");
17056
- var os7 = __toESM(require("os"), 1);
17057
- var path22 = __toESM(require("path"), 1);
18073
+ var os8 = __toESM(require("os"), 1);
18074
+ var path23 = __toESM(require("path"), 1);
17058
18075
  function isRecord2(value) {
17059
18076
  return typeof value === "object" && value !== null && !Array.isArray(value);
17060
18077
  }
@@ -17098,20 +18115,20 @@ function parseJsonConfigFile(filePath) {
17098
18115
  }
17099
18116
  }
17100
18117
  function toAbsolute(projectRoot, maybeRelative) {
17101
- return path22.isAbsolute(maybeRelative) ? maybeRelative : path22.join(projectRoot, maybeRelative);
18118
+ return path23.isAbsolute(maybeRelative) ? maybeRelative : path23.join(projectRoot, maybeRelative);
17102
18119
  }
17103
18120
  function isProjectScopedConfigPath(configPath) {
17104
- return path22.basename(configPath) === "codebase-index.json" && path22.basename(path22.dirname(configPath)) === ".opencode";
18121
+ return path23.basename(configPath) === "codebase-index.json" && path23.basename(path23.dirname(configPath)) === ".opencode";
17105
18122
  }
17106
18123
  function normalizeEvalConfigKnowledgeBases(rawConfig, projectRoot, resolvedConfigPath) {
17107
18124
  const config = rawConfig && typeof rawConfig === "object" ? { ...rawConfig } : {};
17108
18125
  const rebaseEntries = (values) => isProjectScopedConfigPath(resolvedConfigPath) ? resolveInheritedKnowledgeBaseEntries(
17109
18126
  values,
17110
- path22.dirname(path22.dirname(resolvedConfigPath)),
18127
+ path23.dirname(path23.dirname(resolvedConfigPath)),
17111
18128
  projectRoot
17112
18129
  ) : rebasePathEntries(
17113
18130
  values,
17114
- path22.dirname(resolvedConfigPath),
18131
+ path23.dirname(resolvedConfigPath),
17115
18132
  projectRoot
17116
18133
  );
17117
18134
  if (Array.isArray(config.knowledgeBases)) {
@@ -17139,7 +18156,7 @@ function loadRawConfig(projectRoot, configPath) {
17139
18156
  projectConfig
17140
18157
  );
17141
18158
  }
17142
- const globalConfig = path22.join(os7.homedir(), ".config", "opencode", "codebase-index.json");
18159
+ const globalConfig = path23.join(os8.homedir(), ".config", "opencode", "codebase-index.json");
17143
18160
  if ((0, import_fs15.existsSync)(globalConfig)) {
17144
18161
  return parseJsonConfigFile(globalConfig);
17145
18162
  }
@@ -17149,10 +18166,10 @@ function getIndexRootPath(projectRoot, scope) {
17149
18166
  return scope === "global" ? getGlobalIndexPath("opencode") : resolveProjectIndexPath(projectRoot, scope, "opencode");
17150
18167
  }
17151
18168
  function getLocalProjectIndexRoot(projectRoot) {
17152
- return path22.join(projectRoot, ".opencode", "index");
18169
+ return path23.join(projectRoot, ".opencode", "index");
17153
18170
  }
17154
18171
  function getLocalProjectConfigPath(projectRoot) {
17155
- return path22.join(projectRoot, ".opencode", "codebase-index.json");
18172
+ return path23.join(projectRoot, ".opencode", "codebase-index.json");
17156
18173
  }
17157
18174
  function clearIndexRoot(projectRoot, scope) {
17158
18175
  const indexRoot = scope === "global" ? getIndexRootPath(projectRoot, scope) : getLocalProjectIndexRoot(projectRoot);
@@ -17174,7 +18191,7 @@ function ensureLocalEvalProjectConfig(projectRoot, configPath) {
17174
18191
  projectRoot,
17175
18192
  resolvedConfigPath
17176
18193
  );
17177
- (0, import_fs15.mkdirSync)(path22.dirname(localConfigPath), { recursive: true });
18194
+ (0, import_fs15.mkdirSync)(path23.dirname(localConfigPath), { recursive: true });
17178
18195
  (0, import_fs15.writeFileSync)(localConfigPath, JSON.stringify(sourceConfig, null, 2), "utf-8");
17179
18196
  return localConfigPath;
17180
18197
  }
@@ -17227,68 +18244,68 @@ function isStringArray4(value) {
17227
18244
  function isNonEmptyString(value) {
17228
18245
  return typeof value === "string" && value.trim().length > 0;
17229
18246
  }
17230
- function asPositiveNumber(value, path33) {
18247
+ function asPositiveNumber(value, path34) {
17231
18248
  if (typeof value !== "number" || Number.isNaN(value) || value < 0) {
17232
- throw new Error(`${path33} must be a non-negative number`);
18249
+ throw new Error(`${path34} must be a non-negative number`);
17233
18250
  }
17234
18251
  return value;
17235
18252
  }
17236
- function parseQueryType(value, path33) {
18253
+ function parseQueryType(value, path34) {
17237
18254
  if (value === "definition" || value === "implementation-intent" || value === "similarity" || value === "keyword-heavy" || value === "conceptual") {
17238
18255
  return value;
17239
18256
  }
17240
18257
  throw new Error(
17241
- `${path33} must be one of: definition, implementation-intent, similarity, keyword-heavy, conceptual`
18258
+ `${path34} must be one of: definition, implementation-intent, similarity, keyword-heavy, conceptual`
17242
18259
  );
17243
18260
  }
17244
- function parseExpectedRoute(value, path33) {
18261
+ function parseExpectedRoute(value, path34) {
17245
18262
  if (value === void 0) return void 0;
17246
18263
  if (value === "search" || value === "definition") return value;
17247
- throw new Error(`${path33} must be one of: search, definition`);
18264
+ throw new Error(`${path34} must be one of: search, definition`);
17248
18265
  }
17249
- function parseExpectedOutcome(value, path33) {
18266
+ function parseExpectedOutcome(value, path34) {
17250
18267
  if (value === void 0) return void 0;
17251
18268
  if (value === "results" || value === "no-results") {
17252
18269
  return value;
17253
18270
  }
17254
- throw new Error(`${path33} must be one of: results, no-results`);
18271
+ throw new Error(`${path34} must be one of: results, no-results`);
17255
18272
  }
17256
- function parseRecoveryExpectation(value, path33) {
18273
+ function parseRecoveryExpectation(value, path34) {
17257
18274
  if (value === void 0) return void 0;
17258
18275
  if (value === "none" || value === "filter-relaxed") {
17259
18276
  return value;
17260
18277
  }
17261
- throw new Error(`${path33} must be one of: none, filter-relaxed`);
18278
+ throw new Error(`${path34} must be one of: none, filter-relaxed`);
17262
18279
  }
17263
- function parseQueryDifficulty(value, path33) {
18280
+ function parseQueryDifficulty(value, path34) {
17264
18281
  if (value === void 0) return void 0;
17265
18282
  if (value === "easy" || value === "medium" || value === "hard") {
17266
18283
  return value;
17267
18284
  }
17268
- throw new Error(`${path33} must be one of: easy, medium, hard`);
18285
+ throw new Error(`${path34} must be one of: easy, medium, hard`);
17269
18286
  }
17270
- function parseQueryTags(value, path33) {
18287
+ function parseQueryTags(value, path34) {
17271
18288
  if (value === void 0) return void 0;
17272
18289
  if (!isStringArray4(value) || value.some((tag) => tag.trim().length === 0)) {
17273
- throw new Error(`${path33} must be an array of non-empty strings`);
18290
+ throw new Error(`${path34} must be an array of non-empty strings`);
17274
18291
  }
17275
18292
  if (value.length > 16) {
17276
- throw new Error(`${path33} must contain at most 16 tags`);
18293
+ throw new Error(`${path34} must contain at most 16 tags`);
17277
18294
  }
17278
18295
  return value;
17279
18296
  }
17280
- function parseQueryArgs(value, path33) {
18297
+ function parseQueryArgs(value, path34) {
17281
18298
  if (value === void 0) return void 0;
17282
18299
  if (!isRecord3(value)) {
17283
- throw new Error(`${path33} must be an object`);
17284
- }
17285
- const symbol = parseStringOrUndefined(value.symbol, `${path33}.symbol`);
17286
- const filePath = parseStringOrUndefined(value.filePath, `${path33}.filePath`);
17287
- const fileType = parseStringOrUndefined(value.fileType, `${path33}.fileType`);
17288
- const directory = parseStringOrUndefined(value.directory, `${path33}.directory`);
17289
- const callerLimit = parsePositiveIntegerOrUndefined(value.callerLimit, `${path33}.callerLimit`);
17290
- const calleeLimit = parsePositiveIntegerOrUndefined(value.calleeLimit, `${path33}.calleeLimit`);
17291
- const tokenBudget = parsePositiveIntegerOrUndefined(value.tokenBudget, `${path33}.tokenBudget`);
18300
+ throw new Error(`${path34} must be an object`);
18301
+ }
18302
+ const symbol = parseStringOrUndefined(value.symbol, `${path34}.symbol`);
18303
+ const filePath = parseStringOrUndefined(value.filePath, `${path34}.filePath`);
18304
+ const fileType = parseStringOrUndefined(value.fileType, `${path34}.fileType`);
18305
+ const directory = parseStringOrUndefined(value.directory, `${path34}.directory`);
18306
+ const callerLimit = parsePositiveIntegerOrUndefined(value.callerLimit, `${path34}.callerLimit`);
18307
+ const calleeLimit = parsePositiveIntegerOrUndefined(value.calleeLimit, `${path34}.calleeLimit`);
18308
+ const tokenBudget = parsePositiveIntegerOrUndefined(value.tokenBudget, `${path34}.tokenBudget`);
17292
18309
  return {
17293
18310
  ...symbol !== void 0 ? { symbol } : {},
17294
18311
  ...filePath !== void 0 ? { filePath } : {},
@@ -17299,50 +18316,50 @@ function parseQueryArgs(value, path33) {
17299
18316
  ...tokenBudget !== void 0 ? { tokenBudget } : {}
17300
18317
  };
17301
18318
  }
17302
- function parsePositiveIntegerOrUndefined(value, path33) {
18319
+ function parsePositiveIntegerOrUndefined(value, path34) {
17303
18320
  if (value === void 0 || value === null) return void 0;
17304
18321
  if (typeof value !== "number" || !Number.isInteger(value) || value <= 0) {
17305
- throw new Error(`${path33} must be a positive integer`);
18322
+ throw new Error(`${path34} must be a positive integer`);
17306
18323
  }
17307
18324
  return value;
17308
18325
  }
17309
18326
  var SEMVER_VERSION_PATTERN = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
17310
- function parseSemanticVersion(value, path33) {
18327
+ function parseSemanticVersion(value, path34) {
17311
18328
  if (!isNonEmptyString(value)) {
17312
- throw new Error(`${path33} must be a non-empty string`);
18329
+ throw new Error(`${path34} must be a non-empty string`);
17313
18330
  }
17314
18331
  if (!SEMVER_VERSION_PATTERN.test(value)) {
17315
- throw new Error(`${path33} must be a valid semantic version (MAJOR.MINOR.PATCH)`);
18332
+ throw new Error(`${path34} must be a valid semantic version (MAJOR.MINOR.PATCH)`);
17316
18333
  }
17317
18334
  return value;
17318
18335
  }
17319
- function parseRetrievalMode(value, path33) {
18336
+ function parseRetrievalMode(value, path34) {
17320
18337
  if (value === void 0 || value === "search") return "search";
17321
18338
  if (value === "context" || value === "edit-context") return value;
17322
- throw new Error(`${path33} must be one of: search, context, edit-context`);
18339
+ throw new Error(`${path34} must be one of: search, context, edit-context`);
17323
18340
  }
17324
- function parseStringOrUndefined(value, path33) {
18341
+ function parseStringOrUndefined(value, path34) {
17325
18342
  if (value === void 0 || value === null) return void 0;
17326
18343
  if (!isNonEmptyString(value)) {
17327
- throw new Error(`${path33} must be a non-empty string`);
18344
+ throw new Error(`${path34} must be a non-empty string`);
17328
18345
  }
17329
18346
  return value;
17330
18347
  }
17331
- function parseGradedEvidence(value, path33) {
18348
+ function parseGradedEvidence(value, path34) {
17332
18349
  if (value === void 0) return [];
17333
18350
  if (!Array.isArray(value)) {
17334
- throw new Error(`${path33} must be an array`);
18351
+ throw new Error(`${path34} must be an array`);
17335
18352
  }
17336
18353
  return value.map((entry, index) => {
17337
18354
  if (!isRecord3(entry)) {
17338
- throw new Error(`${path33}[${index}] must be an object`);
18355
+ throw new Error(`${path34}[${index}] must be an object`);
17339
18356
  }
17340
- const evidencePath = parseStringOrUndefined(entry.path, `${path33}[${index}].path`);
18357
+ const evidencePath = parseStringOrUndefined(entry.path, `${path34}[${index}].path`);
17341
18358
  if (evidencePath === void 0) {
17342
- throw new Error(`${path33}[${index}].path is required`);
18359
+ throw new Error(`${path34}[${index}].path is required`);
17343
18360
  }
17344
- const symbol = parseStringOrUndefined(entry.symbol, `${path33}[${index}].symbol`);
17345
- const relevance = parseEvidenceRelevance(entry.relevance, `${path33}[${index}].relevance`);
18361
+ const symbol = parseStringOrUndefined(entry.symbol, `${path34}[${index}].symbol`);
18362
+ const relevance = parseEvidenceRelevance(entry.relevance, `${path34}[${index}].relevance`);
17346
18363
  return {
17347
18364
  path: evidencePath,
17348
18365
  ...symbol !== void 0 ? { symbol } : {},
@@ -17350,27 +18367,27 @@ function parseGradedEvidence(value, path33) {
17350
18367
  };
17351
18368
  });
17352
18369
  }
17353
- function parseEvidenceRelevance(value, path33) {
18370
+ function parseEvidenceRelevance(value, path34) {
17354
18371
  if (value === void 0) {
17355
- throw new Error(`${path33} is required`);
18372
+ throw new Error(`${path34} is required`);
17356
18373
  }
17357
18374
  if (value !== 1 && value !== 2 && value !== 3) {
17358
- throw new Error(`${path33} must be 1, 2, or 3`);
18375
+ throw new Error(`${path34} must be 1, 2, or 3`);
17359
18376
  }
17360
18377
  return value;
17361
18378
  }
17362
- function parseExpectedGraphNeighbor(value, path33) {
18379
+ function parseExpectedGraphNeighbor(value, path34) {
17363
18380
  if (value === void 0) return void 0;
17364
18381
  if (!isRecord3(value)) {
17365
- throw new Error(`${path33} must be an object`);
18382
+ throw new Error(`${path34} must be an object`);
17366
18383
  }
17367
18384
  if (value.direction !== "caller" && value.direction !== "callee") {
17368
- throw new Error(`${path33}.direction must be one of: caller, callee`);
18385
+ throw new Error(`${path34}.direction must be one of: caller, callee`);
17369
18386
  }
17370
- const filePath = parseStringOrUndefined(value.filePath, `${path33}.filePath`);
17371
- const symbol = parseStringOrUndefined(value.symbol, `${path33}.symbol`);
18387
+ const filePath = parseStringOrUndefined(value.filePath, `${path34}.filePath`);
18388
+ const symbol = parseStringOrUndefined(value.symbol, `${path34}.symbol`);
17372
18389
  if (filePath === void 0 && symbol === void 0) {
17373
- throw new Error(`${path33} must include filePath or symbol`);
18390
+ throw new Error(`${path34} must include filePath or symbol`);
17374
18391
  }
17375
18392
  return {
17376
18393
  direction: value.direction,
@@ -17378,9 +18395,9 @@ function parseExpectedGraphNeighbor(value, path33) {
17378
18395
  ...symbol !== void 0 ? { symbol } : {}
17379
18396
  };
17380
18397
  }
17381
- function parseExpected(input, path33) {
18398
+ function parseExpected(input, path34) {
17382
18399
  if (!isRecord3(input)) {
17383
- throw new Error(`${path33} must be an object`);
18400
+ throw new Error(`${path34} must be an object`);
17384
18401
  }
17385
18402
  const filePathRaw = input.filePath;
17386
18403
  const acceptableFilesRaw = input.acceptableFiles;
@@ -17391,29 +18408,29 @@ function parseExpected(input, path33) {
17391
18408
  const recoveryExpectationRaw = input.recoveryExpectation;
17392
18409
  const gradedEvidenceRaw = input.gradedEvidence;
17393
18410
  const graphNeighborRaw = input.graphNeighbor;
17394
- const filePath = parseStringOrUndefined(filePathRaw, `${path33}.filePath`);
18411
+ const filePath = parseStringOrUndefined(filePathRaw, `${path34}.filePath`);
17395
18412
  const acceptableFiles = isStringArray4(acceptableFilesRaw) ? acceptableFilesRaw : void 0;
17396
- const gradedEvidence = parseGradedEvidence(gradedEvidenceRaw, `${path33}.gradedEvidence`);
17397
- const graphNeighbor = parseExpectedGraphNeighbor(graphNeighborRaw, `${path33}.graphNeighbor`);
17398
- const expectedOutcome = parseExpectedOutcome(expectedOutcomeRaw, `${path33}.expectedOutcome`);
18413
+ const gradedEvidence = parseGradedEvidence(gradedEvidenceRaw, `${path34}.gradedEvidence`);
18414
+ const graphNeighbor = parseExpectedGraphNeighbor(graphNeighborRaw, `${path34}.graphNeighbor`);
18415
+ const expectedOutcome = parseExpectedOutcome(expectedOutcomeRaw, `${path34}.expectedOutcome`);
17399
18416
  if (expectedOutcome !== "no-results" && !filePath && (!acceptableFiles || acceptableFiles.length === 0) && gradedEvidence.length === 0) {
17400
18417
  throw new Error(
17401
- `${path33} must include expected.filePath, expected.acceptableFiles, or expected.gradedEvidence`
18418
+ `${path34} must include expected.filePath, expected.acceptableFiles, or expected.gradedEvidence`
17402
18419
  );
17403
18420
  }
17404
18421
  if (acceptableFilesRaw !== void 0 && !isStringArray4(acceptableFilesRaw)) {
17405
- throw new Error(`${path33}.acceptableFiles must be an array of strings`);
18422
+ throw new Error(`${path34}.acceptableFiles must be an array of strings`);
17406
18423
  }
17407
18424
  if (symbolRaw !== void 0 && typeof symbolRaw !== "string") {
17408
- throw new Error(`${path33}.symbol must be a string when provided`);
18425
+ throw new Error(`${path34}.symbol must be a string when provided`);
17409
18426
  }
17410
18427
  if (branchRaw !== void 0 && typeof branchRaw !== "string") {
17411
- throw new Error(`${path33}.branch must be a string when provided`);
18428
+ throw new Error(`${path34}.branch must be a string when provided`);
17412
18429
  }
17413
- const expectedRoute = parseExpectedRoute(expectedRouteRaw, `${path33}.expectedRoute`);
18430
+ const expectedRoute = parseExpectedRoute(expectedRouteRaw, `${path34}.expectedRoute`);
17414
18431
  const recoveryExpectation = parseRecoveryExpectation(
17415
18432
  recoveryExpectationRaw,
17416
- `${path33}.recoveryExpectation`
18433
+ `${path34}.recoveryExpectation`
17417
18434
  );
17418
18435
  return {
17419
18436
  filePath,
@@ -17427,13 +18444,13 @@ function parseExpected(input, path33) {
17427
18444
  ...graphNeighbor !== void 0 ? { graphNeighbor } : {}
17428
18445
  };
17429
18446
  }
17430
- function parseQueryLanguage(value, path33) {
17431
- return parseStringOrUndefined(value, path33);
18447
+ function parseQueryLanguage(value, path34) {
18448
+ return parseStringOrUndefined(value, path34);
17432
18449
  }
17433
18450
  function parseQuery(input, index) {
17434
- const path33 = `queries[${index}]`;
18451
+ const path34 = `queries[${index}]`;
17435
18452
  if (!isRecord3(input)) {
17436
- throw new Error(`${path33} must be an object`);
18453
+ throw new Error(`${path34} must be an object`);
17437
18454
  }
17438
18455
  const id = input.id;
17439
18456
  const query = input.query;
@@ -17445,21 +18462,21 @@ function parseQuery(input, index) {
17445
18462
  const tags = input.tags;
17446
18463
  const args = input.args;
17447
18464
  if (typeof id !== "string" || id.trim().length === 0) {
17448
- throw new Error(`${path33}.id must be a non-empty string`);
18465
+ throw new Error(`${path34}.id must be a non-empty string`);
17449
18466
  }
17450
18467
  if (typeof query !== "string" || query.trim().length === 0) {
17451
- throw new Error(`${path33}.query must be a non-empty string`);
18468
+ throw new Error(`${path34}.query must be a non-empty string`);
17452
18469
  }
17453
18470
  return {
17454
18471
  id,
17455
18472
  query,
17456
- queryType: parseQueryType(queryType, `${path33}.queryType`),
17457
- retrievalMode: parseRetrievalMode(retrievalMode, `${path33}.retrievalMode`),
17458
- language: parseQueryLanguage(language, `${path33}.language`),
17459
- difficulty: parseQueryDifficulty(difficulty, `${path33}.difficulty`),
17460
- args: parseQueryArgs(args, `${path33}.args`),
17461
- tags: parseQueryTags(tags, `${path33}.tags`),
17462
- expected: parseExpected(expected, `${path33}.expected`)
18473
+ queryType: parseQueryType(queryType, `${path34}.queryType`),
18474
+ retrievalMode: parseRetrievalMode(retrievalMode, `${path34}.retrievalMode`),
18475
+ language: parseQueryLanguage(language, `${path34}.language`),
18476
+ difficulty: parseQueryDifficulty(difficulty, `${path34}.difficulty`),
18477
+ args: parseQueryArgs(args, `${path34}.args`),
18478
+ tags: parseQueryTags(tags, `${path34}.tags`),
18479
+ expected: parseExpected(expected, `${path34}.expected`)
17463
18480
  };
17464
18481
  }
17465
18482
  function parseGoldenDataset(raw, sourceLabel) {
@@ -17875,13 +18892,13 @@ async function runEvaluation(options) {
17875
18892
  };
17876
18893
  const outputDir = createRunDirectory(toAbsolute(options.projectRoot, options.outputRoot));
17877
18894
  const perQueryArtifact = buildPerQueryArtifact(perQuery);
17878
- writeJson(path23.join(outputDir, "summary.json"), summary);
17879
- writeJson(path23.join(outputDir, "per-query.json"), perQueryArtifact);
18895
+ writeJson(path24.join(outputDir, "summary.json"), summary);
18896
+ writeJson(path24.join(outputDir, "per-query.json"), perQueryArtifact);
17880
18897
  let comparison;
17881
18898
  if (againstPath) {
17882
18899
  const baseline = loadSummary(againstPath);
17883
18900
  comparison = compareSummaries(summary, baseline, againstPath);
17884
- writeJson(path23.join(outputDir, "compare.json"), comparison);
18901
+ writeJson(path24.join(outputDir, "compare.json"), comparison);
17885
18902
  }
17886
18903
  let gate;
17887
18904
  if (options.ciMode) {
@@ -17894,7 +18911,7 @@ async function runEvaluation(options) {
17894
18911
  if ((0, import_fs17.existsSync)(resolvedBaseline)) {
17895
18912
  const baselineSummary = loadSummary(resolvedBaseline);
17896
18913
  comparison = compareSummaries(summary, baselineSummary, resolvedBaseline);
17897
- writeJson(path23.join(outputDir, "compare.json"), comparison);
18914
+ writeJson(path24.join(outputDir, "compare.json"), comparison);
17898
18915
  } else if (budget.failOnMissingBaseline) {
17899
18916
  throw new Error(
17900
18917
  `Budget baseline is missing: ${resolvedBaseline}. Set failOnMissingBaseline=false to allow CI run without baseline.`
@@ -17904,7 +18921,7 @@ async function runEvaluation(options) {
17904
18921
  gate = evaluateBudgetGate(budget, summary, comparison);
17905
18922
  }
17906
18923
  const markdown = createSummaryMarkdown(summary, comparison, gate);
17907
- writeText(path23.join(outputDir, "summary.md"), markdown);
18924
+ writeText(path24.join(outputDir, "summary.md"), markdown);
17908
18925
  return { outputDir, summary, perQuery, comparison, gate };
17909
18926
  } finally {
17910
18927
  await indexer.close();
@@ -17962,23 +18979,23 @@ async function runSweep(options, sweep) {
17962
18979
  bestByMrrAt10,
17963
18980
  bestByP95Latency
17964
18981
  };
17965
- writeJson(path23.join(outputDir, "compare.json"), aggregate);
18982
+ writeJson(path24.join(outputDir, "compare.json"), aggregate);
17966
18983
  const md = createSummaryMarkdown(
17967
18984
  bestByHitAt5?.summary ?? runs[0].summary,
17968
18985
  bestByHitAt5?.comparison,
17969
18986
  void 0,
17970
18987
  aggregate
17971
18988
  );
17972
- writeText(path23.join(outputDir, "summary.md"), md);
17973
- writeJson(path23.join(outputDir, "summary.json"), bestByHitAt5?.summary ?? runs[0].summary);
18989
+ writeText(path24.join(outputDir, "summary.md"), md);
18990
+ writeJson(path24.join(outputDir, "summary.json"), bestByHitAt5?.summary ?? runs[0].summary);
17974
18991
  return { outputDir, aggregate };
17975
18992
  }
17976
18993
 
17977
18994
  // src/eval/cli.ts
17978
- var path25 = __toESM(require("path"), 1);
18995
+ var path26 = __toESM(require("path"), 1);
17979
18996
 
17980
18997
  // src/eval/cli-parser.ts
17981
- var path24 = __toESM(require("path"), 1);
18998
+ var path25 = __toESM(require("path"), 1);
17982
18999
  function printUsage() {
17983
19000
  console.log(`
17984
19001
  Usage:
@@ -18050,12 +19067,12 @@ function parseEvalArgs(argv, cwd) {
18050
19067
  const arg = argv[i];
18051
19068
  const next = argv[i + 1];
18052
19069
  if (arg === "--project" && next) {
18053
- parsed.projectRoot = path24.resolve(cwd, next);
19070
+ parsed.projectRoot = path25.resolve(cwd, next);
18054
19071
  i += 1;
18055
19072
  continue;
18056
19073
  }
18057
19074
  if (arg === "--config" && next) {
18058
- parsed.configPath = path24.resolve(cwd, next);
19075
+ parsed.configPath = path25.resolve(cwd, next);
18059
19076
  i += 1;
18060
19077
  continue;
18061
19078
  }
@@ -18251,22 +19268,22 @@ async function handleEvalCommand(args, cwd) {
18251
19268
  if (!parsed.againstPath.endsWith(".json")) {
18252
19269
  throw new Error("eval diff --against must point to a summary JSON file");
18253
19270
  }
18254
- const currentSummary = loadSummary(path25.resolve(parsed.projectRoot, currentPath), {
19271
+ const currentSummary = loadSummary(path26.resolve(parsed.projectRoot, currentPath), {
18255
19272
  allowLegacyDiversityMetrics: true
18256
19273
  });
18257
- const baselineSummary = loadSummary(path25.resolve(parsed.projectRoot, parsed.againstPath), {
19274
+ const baselineSummary = loadSummary(path26.resolve(parsed.projectRoot, parsed.againstPath), {
18258
19275
  allowLegacyDiversityMetrics: true
18259
19276
  });
18260
19277
  const comparison = compareSummaries(
18261
19278
  currentSummary,
18262
19279
  baselineSummary,
18263
- path25.resolve(parsed.projectRoot, parsed.againstPath)
19280
+ path26.resolve(parsed.projectRoot, parsed.againstPath)
18264
19281
  );
18265
- const outputDir = createRunDirectory(path25.resolve(parsed.projectRoot, parsed.outputRoot));
19282
+ const outputDir = createRunDirectory(path26.resolve(parsed.projectRoot, parsed.outputRoot));
18266
19283
  const summaryMd = createSummaryMarkdown(currentSummary, comparison);
18267
- writeJson(path25.join(outputDir, "compare.json"), comparison);
18268
- writeText(path25.join(outputDir, "summary.md"), summaryMd);
18269
- writeJson(path25.join(outputDir, "summary.json"), currentSummary);
19284
+ writeJson(path26.join(outputDir, "compare.json"), comparison);
19285
+ writeText(path26.join(outputDir, "summary.md"), summaryMd);
19286
+ writeJson(path26.join(outputDir, "summary.json"), currentSummary);
18270
19287
  console.log(`Eval diff complete. Artifacts: ${outputDir}`);
18271
19288
  return 0;
18272
19289
  }
@@ -18428,7 +19445,7 @@ async function executeCallGraph(projectRoot, host, args) {
18428
19445
  return { text: formatCallGraphResult(await getCallGraphData(projectRoot, host, args)) };
18429
19446
  }
18430
19447
  async function executeCallGraphPath(projectRoot, host, args) {
18431
- const path33 = await getCallGraphPath(
19448
+ const path34 = await getCallGraphPath(
18432
19449
  projectRoot,
18433
19450
  host,
18434
19451
  args.from,
@@ -18437,7 +19454,7 @@ async function executeCallGraphPath(projectRoot, host, args) {
18437
19454
  args.fromFilePath,
18438
19455
  args.toFilePath
18439
19456
  );
18440
- return { text: formatCallGraphPathResult(path33) };
19457
+ return { text: formatCallGraphPathResult(path34) };
18441
19458
  }
18442
19459
  async function executeCodeCommunities(projectRoot, host, args) {
18443
19460
  const result = await getCodeCommunities(projectRoot, host, args);
@@ -18932,10 +19949,65 @@ ${formatSearchResults(results)}` }] };
18932
19949
  }
18933
19950
 
18934
19951
  // src/adapters/mcp/server.ts
19952
+ var mcpWorkerReferences = /* @__PURE__ */ new Map();
19953
+ var mcpWorkerTeardowns = /* @__PURE__ */ new Map();
19954
+ function retainMcpBackgroundWorker(projectRoot, host) {
19955
+ const key = getBackgroundWorkerProjectKey(projectRoot, host);
19956
+ mcpWorkerReferences.set(key, (mcpWorkerReferences.get(key) ?? 0) + 1);
19957
+ }
19958
+ async function releaseMcpBackgroundWorker(projectRoot, host) {
19959
+ const key = getBackgroundWorkerProjectKey(projectRoot, host);
19960
+ const references = mcpWorkerReferences.get(key) ?? 0;
19961
+ if (references > 1) {
19962
+ mcpWorkerReferences.set(key, references - 1);
19963
+ return;
19964
+ }
19965
+ mcpWorkerReferences.delete(key);
19966
+ const teardown = stopBackgroundWorker(projectRoot, host);
19967
+ mcpWorkerTeardowns.set(key, teardown);
19968
+ try {
19969
+ await teardown;
19970
+ } finally {
19971
+ if (mcpWorkerTeardowns.get(key) === teardown) {
19972
+ mcpWorkerTeardowns.delete(key);
19973
+ }
19974
+ }
19975
+ }
18935
19976
  function getServerInstructions(host) {
18936
19977
  const hostText = `host ${host}`;
18937
19978
  return `This MCP server is the preferred codebase-understanding path for ${hostText}. Start a repository task with index_status when index readiness or freshness is unknown. Use codebase_context as the preferred first entry point because it returns a token-budgeted location pack and routes to definitions or call-graph helpers when symbol intent is present. For code changes with a known or suspected symbol target, optionally call codebase_edit_context as a compact pre-edit step for bounded source plus direct callers and callees before broad file reads. Keep the default tokenBudget for normal discovery, then use implementation_lookup, codebase_search, or a targeted file read only for selected locations that need source content. Use codebase_peek for direct conceptual location lookup. For exact identifiers or exhaustive matches, use grep. After identifying symbols, use call_graph or call_graph_path to trace dependencies. If the index is unavailable, run index_codebase, then retry the retrieval tool.`;
18938
19979
  }
19980
+ function configureMcpBackgroundWorker(projectRoot, config, host, watcherFactory, watcherFactoryForConfig) {
19981
+ if (!getProjectSafety(projectRoot, config).safeToRun) {
19982
+ return { managesWorker: false };
19983
+ }
19984
+ if (isBackgroundWorkerManaged(projectRoot, host)) {
19985
+ const key = getBackgroundWorkerProjectKey(projectRoot, host);
19986
+ if ((mcpWorkerReferences.get(key) ?? 0) === 0 && !mcpWorkerTeardowns.has(key)) {
19987
+ return { managesWorker: false };
19988
+ }
19989
+ if (watcherFactory !== void 0) {
19990
+ attachBackgroundWorkerWatcher(projectRoot, host, watcherFactory, watcherFactoryForConfig);
19991
+ }
19992
+ if (mcpWorkerTeardowns.has(key) || isBackgroundWorkerStopping(projectRoot, host)) {
19993
+ requestBackgroundWorker(projectRoot, host);
19994
+ }
19995
+ return { managesWorker: true };
19996
+ }
19997
+ configureBackgroundWorker(projectRoot, host, config, {
19998
+ startAutoIndex: (source, allowDisabledAutoIndex) => {
19999
+ startAutoIndexForBackgroundWorker(projectRoot, host, source, allowDisabledAutoIndex);
20000
+ },
20001
+ stopAutoIndex: () => stopAutoIndexForBackgroundWorker(projectRoot, host),
20002
+ watcherFactory,
20003
+ watcherFactoryForConfig
20004
+ });
20005
+ return { managesWorker: true };
20006
+ }
20007
+ function attachMcpBackgroundWatcher(projectRoot, config, host, watcherFactory, watcherFactoryForConfig) {
20008
+ configureMcpBackgroundWorker(projectRoot, config, host, watcherFactory, watcherFactoryForConfig);
20009
+ return waitForBackgroundWorkerStart(projectRoot, host);
20010
+ }
18939
20011
  function createMcpServer(projectRoot, config, host) {
18940
20012
  const server = new import_mcp.McpServer({
18941
20013
  name: MCP_SERVER_CURRENT_NAME,
@@ -18943,11 +20015,14 @@ function createMcpServer(projectRoot, config, host) {
18943
20015
  }, {
18944
20016
  instructions: getServerInstructions(host)
18945
20017
  });
18946
- initializeTools(projectRoot, config, host);
18947
- startAutoIndex(projectRoot, host, "startup");
20018
+ initializeTools(projectRoot, config, host, { preserveManagedWorker: true });
20019
+ const backgroundWorker = configureMcpBackgroundWorker(projectRoot, config, host);
20020
+ if (backgroundWorker.managesWorker) {
20021
+ retainMcpBackgroundWorker(projectRoot, host);
20022
+ }
18948
20023
  let stopCoordinationPromise = null;
18949
20024
  const stopCoordination = () => {
18950
- stopCoordinationPromise ??= stopAutoIndex(projectRoot, host);
20025
+ stopCoordinationPromise ??= backgroundWorker.managesWorker ? releaseMcpBackgroundWorker(projectRoot, host) : Promise.resolve();
18951
20026
  return stopCoordinationPromise;
18952
20027
  };
18953
20028
  const closeProtocol = server.server.close.bind(server.server);
@@ -18963,7 +20038,9 @@ function createMcpServer(projectRoot, config, host) {
18963
20038
  const onServerClose = server.server.onclose;
18964
20039
  server.server.onclose = () => {
18965
20040
  onServerClose?.();
18966
- void stopCoordination();
20041
+ void stopCoordination().catch((error) => {
20042
+ console.error("[codebase-index] Failed to stop MCP background worker after transport close:", error);
20043
+ });
18967
20044
  };
18968
20045
  registerMcpTools(server, {
18969
20046
  projectRoot,
@@ -18978,7 +20055,7 @@ var import_fs19 = require("fs");
18978
20055
 
18979
20056
  // node_modules/chokidar/index.js
18980
20057
  var import_node_events = require("events");
18981
- var import_node_fs2 = require("fs");
20058
+ var import_node_fs3 = require("fs");
18982
20059
  var import_promises3 = require("fs/promises");
18983
20060
  var sp2 = __toESM(require("path"), 1);
18984
20061
 
@@ -19066,7 +20143,7 @@ var ReaddirpStream = class extends import_node_stream.Readable {
19066
20143
  this._directoryFilter = normalizeFilter(opts.directoryFilter);
19067
20144
  const statMethod = opts.lstat ? import_promises.lstat : import_promises.stat;
19068
20145
  if (wantBigintFsStats) {
19069
- this._stat = (path33) => statMethod(path33, { bigint: true });
20146
+ this._stat = (path34) => statMethod(path34, { bigint: true });
19070
20147
  } else {
19071
20148
  this._stat = statMethod;
19072
20149
  }
@@ -19091,8 +20168,8 @@ var ReaddirpStream = class extends import_node_stream.Readable {
19091
20168
  const par = this.parent;
19092
20169
  const fil = par && par.files;
19093
20170
  if (fil && fil.length > 0) {
19094
- const { path: path33, depth } = par;
19095
- const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path33));
20171
+ const { path: path34, depth } = par;
20172
+ const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path34));
19096
20173
  const awaited = await Promise.all(slice);
19097
20174
  for (const entry of awaited) {
19098
20175
  if (!entry)
@@ -19132,21 +20209,21 @@ var ReaddirpStream = class extends import_node_stream.Readable {
19132
20209
  this.reading = false;
19133
20210
  }
19134
20211
  }
19135
- async _exploreDir(path33, depth) {
20212
+ async _exploreDir(path34, depth) {
19136
20213
  let files;
19137
20214
  try {
19138
- files = await (0, import_promises.readdir)(path33, this._rdOptions);
20215
+ files = await (0, import_promises.readdir)(path34, this._rdOptions);
19139
20216
  } catch (error) {
19140
20217
  this._onError(error);
19141
20218
  }
19142
- return { files, depth, path: path33 };
20219
+ return { files, depth, path: path34 };
19143
20220
  }
19144
- async _formatEntry(dirent, path33) {
20221
+ async _formatEntry(dirent, path34) {
19145
20222
  let entry;
19146
- const basename8 = this._isDirent ? dirent.name : dirent;
20223
+ const basename9 = this._isDirent ? dirent.name : dirent;
19147
20224
  try {
19148
- const fullPath = (0, import_node_path.resolve)((0, import_node_path.join)(path33, basename8));
19149
- entry = { path: (0, import_node_path.relative)(this._root, fullPath), fullPath, basename: basename8 };
20225
+ const fullPath = (0, import_node_path.resolve)((0, import_node_path.join)(path34, basename9));
20226
+ entry = { path: (0, import_node_path.relative)(this._root, fullPath), fullPath, basename: basename9 };
19150
20227
  entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
19151
20228
  } catch (err) {
19152
20229
  this._onError(err);
@@ -19216,7 +20293,7 @@ function readdirp(root, options = {}) {
19216
20293
  }
19217
20294
 
19218
20295
  // node_modules/chokidar/handler.js
19219
- var import_node_fs = require("fs");
20296
+ var import_node_fs2 = require("fs");
19220
20297
  var import_promises2 = require("fs/promises");
19221
20298
  var import_node_os = require("os");
19222
20299
  var sp = __toESM(require("path"), 1);
@@ -19545,16 +20622,16 @@ var delFromSet = (main, prop, item) => {
19545
20622
  };
19546
20623
  var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
19547
20624
  var FsWatchInstances = /* @__PURE__ */ new Map();
19548
- function createFsWatchInstance(path33, options, listener, errHandler, emitRaw) {
20625
+ function createFsWatchInstance(path34, options, listener, errHandler, emitRaw) {
19549
20626
  const handleEvent = (rawEvent, evPath) => {
19550
- listener(path33);
19551
- emitRaw(rawEvent, evPath, { watchedPath: path33 });
19552
- if (evPath && path33 !== evPath) {
19553
- fsWatchBroadcast(sp.resolve(path33, evPath), KEY_LISTENERS, sp.join(path33, evPath));
20627
+ listener(path34);
20628
+ emitRaw(rawEvent, evPath, { watchedPath: path34 });
20629
+ if (evPath && path34 !== evPath) {
20630
+ fsWatchBroadcast(sp.resolve(path34, evPath), KEY_LISTENERS, sp.join(path34, evPath));
19554
20631
  }
19555
20632
  };
19556
20633
  try {
19557
- return (0, import_node_fs.watch)(path33, {
20634
+ return (0, import_node_fs2.watch)(path34, {
19558
20635
  persistent: options.persistent
19559
20636
  }, handleEvent);
19560
20637
  } catch (error) {
@@ -19570,12 +20647,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
19570
20647
  listener(val1, val2, val3);
19571
20648
  });
19572
20649
  };
19573
- var setFsWatchListener = (path33, fullPath, options, handlers) => {
20650
+ var setFsWatchListener = (path34, fullPath, options, handlers) => {
19574
20651
  const { listener, errHandler, rawEmitter } = handlers;
19575
20652
  let cont = FsWatchInstances.get(fullPath);
19576
20653
  let watcher;
19577
20654
  if (!options.persistent) {
19578
- watcher = createFsWatchInstance(path33, options, listener, errHandler, rawEmitter);
20655
+ watcher = createFsWatchInstance(path34, options, listener, errHandler, rawEmitter);
19579
20656
  if (!watcher)
19580
20657
  return;
19581
20658
  return watcher.close.bind(watcher);
@@ -19586,7 +20663,7 @@ var setFsWatchListener = (path33, fullPath, options, handlers) => {
19586
20663
  addAndConvert(cont, KEY_RAW, rawEmitter);
19587
20664
  } else {
19588
20665
  watcher = createFsWatchInstance(
19589
- path33,
20666
+ path34,
19590
20667
  options,
19591
20668
  fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
19592
20669
  errHandler,
@@ -19601,7 +20678,7 @@ var setFsWatchListener = (path33, fullPath, options, handlers) => {
19601
20678
  cont.watcherUnusable = true;
19602
20679
  if (isWindows && error.code === "EPERM") {
19603
20680
  try {
19604
- const fd = await (0, import_promises2.open)(path33, "r");
20681
+ const fd = await (0, import_promises2.open)(path34, "r");
19605
20682
  await fd.close();
19606
20683
  broadcastErr(error);
19607
20684
  } catch (err) {
@@ -19632,12 +20709,12 @@ var setFsWatchListener = (path33, fullPath, options, handlers) => {
19632
20709
  };
19633
20710
  };
19634
20711
  var FsWatchFileInstances = /* @__PURE__ */ new Map();
19635
- var setFsWatchFileListener = (path33, fullPath, options, handlers) => {
20712
+ var setFsWatchFileListener = (path34, fullPath, options, handlers) => {
19636
20713
  const { listener, rawEmitter } = handlers;
19637
20714
  let cont = FsWatchFileInstances.get(fullPath);
19638
20715
  const copts = cont && cont.options;
19639
20716
  if (copts && (copts.persistent < options.persistent || copts.interval > options.interval)) {
19640
- (0, import_node_fs.unwatchFile)(fullPath);
20717
+ (0, import_node_fs2.unwatchFile)(fullPath);
19641
20718
  cont = void 0;
19642
20719
  }
19643
20720
  if (cont) {
@@ -19648,13 +20725,13 @@ var setFsWatchFileListener = (path33, fullPath, options, handlers) => {
19648
20725
  listeners: listener,
19649
20726
  rawEmitters: rawEmitter,
19650
20727
  options,
19651
- watcher: (0, import_node_fs.watchFile)(fullPath, options, (curr, prev) => {
20728
+ watcher: (0, import_node_fs2.watchFile)(fullPath, options, (curr, prev) => {
19652
20729
  foreach(cont.rawEmitters, (rawEmitter2) => {
19653
20730
  rawEmitter2(EV.CHANGE, fullPath, { curr, prev });
19654
20731
  });
19655
20732
  const currmtime = curr.mtimeMs;
19656
20733
  if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
19657
- foreach(cont.listeners, (listener2) => listener2(path33, curr));
20734
+ foreach(cont.listeners, (listener2) => listener2(path34, curr));
19658
20735
  }
19659
20736
  })
19660
20737
  };
@@ -19665,7 +20742,7 @@ var setFsWatchFileListener = (path33, fullPath, options, handlers) => {
19665
20742
  delFromSet(cont, KEY_RAW, rawEmitter);
19666
20743
  if (isEmptySet(cont.listeners)) {
19667
20744
  FsWatchFileInstances.delete(fullPath);
19668
- (0, import_node_fs.unwatchFile)(fullPath);
20745
+ (0, import_node_fs2.unwatchFile)(fullPath);
19669
20746
  cont.options = cont.watcher = void 0;
19670
20747
  Object.freeze(cont);
19671
20748
  }
@@ -19684,13 +20761,13 @@ var NodeFsHandler = class {
19684
20761
  * @param listener on fs change
19685
20762
  * @returns closer for the watcher instance
19686
20763
  */
19687
- _watchWithNodeFs(path33, listener) {
20764
+ _watchWithNodeFs(path34, listener) {
19688
20765
  const opts = this.fsw.options;
19689
- const directory = sp.dirname(path33);
19690
- const basename8 = sp.basename(path33);
20766
+ const directory = sp.dirname(path34);
20767
+ const basename9 = sp.basename(path34);
19691
20768
  const parent = this.fsw._getWatchedDir(directory);
19692
- parent.add(basename8);
19693
- const absolutePath = sp.resolve(path33);
20769
+ parent.add(basename9);
20770
+ const absolutePath = sp.resolve(path34);
19694
20771
  const options = {
19695
20772
  persistent: opts.persistent
19696
20773
  };
@@ -19699,13 +20776,13 @@ var NodeFsHandler = class {
19699
20776
  let closer;
19700
20777
  if (opts.usePolling) {
19701
20778
  const enableBin = opts.interval !== opts.binaryInterval;
19702
- options.interval = enableBin && isBinaryPath(basename8) ? opts.binaryInterval : opts.interval;
19703
- closer = setFsWatchFileListener(path33, absolutePath, options, {
20779
+ options.interval = enableBin && isBinaryPath(basename9) ? opts.binaryInterval : opts.interval;
20780
+ closer = setFsWatchFileListener(path34, absolutePath, options, {
19704
20781
  listener,
19705
20782
  rawEmitter: this.fsw._emitRaw
19706
20783
  });
19707
20784
  } else {
19708
- closer = setFsWatchListener(path33, absolutePath, options, {
20785
+ closer = setFsWatchListener(path34, absolutePath, options, {
19709
20786
  listener,
19710
20787
  errHandler: this._boundHandleError,
19711
20788
  rawEmitter: this.fsw._emitRaw
@@ -19721,13 +20798,13 @@ var NodeFsHandler = class {
19721
20798
  if (this.fsw.closed) {
19722
20799
  return;
19723
20800
  }
19724
- const dirname15 = sp.dirname(file);
19725
- const basename8 = sp.basename(file);
19726
- const parent = this.fsw._getWatchedDir(dirname15);
20801
+ const dirname16 = sp.dirname(file);
20802
+ const basename9 = sp.basename(file);
20803
+ const parent = this.fsw._getWatchedDir(dirname16);
19727
20804
  let prevStats = stats;
19728
- if (parent.has(basename8))
20805
+ if (parent.has(basename9))
19729
20806
  return;
19730
- const listener = async (path33, newStats) => {
20807
+ const listener = async (path34, newStats) => {
19731
20808
  if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
19732
20809
  return;
19733
20810
  if (!newStats || newStats.mtimeMs === 0) {
@@ -19741,18 +20818,18 @@ var NodeFsHandler = class {
19741
20818
  this.fsw._emit(EV.CHANGE, file, newStats2);
19742
20819
  }
19743
20820
  if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
19744
- this.fsw._closeFile(path33);
20821
+ this.fsw._closeFile(path34);
19745
20822
  prevStats = newStats2;
19746
20823
  const closer2 = this._watchWithNodeFs(file, listener);
19747
20824
  if (closer2)
19748
- this.fsw._addPathCloser(path33, closer2);
20825
+ this.fsw._addPathCloser(path34, closer2);
19749
20826
  } else {
19750
20827
  prevStats = newStats2;
19751
20828
  }
19752
20829
  } catch (error) {
19753
- this.fsw._remove(dirname15, basename8);
20830
+ this.fsw._remove(dirname16, basename9);
19754
20831
  }
19755
- } else if (parent.has(basename8)) {
20832
+ } else if (parent.has(basename9)) {
19756
20833
  const at = newStats.atimeMs;
19757
20834
  const mt = newStats.mtimeMs;
19758
20835
  if (!at || at <= mt || mt !== prevStats.mtimeMs) {
@@ -19777,7 +20854,7 @@ var NodeFsHandler = class {
19777
20854
  * @param item basename of this item
19778
20855
  * @returns true if no more processing is needed for this entry.
19779
20856
  */
19780
- async _handleSymlink(entry, directory, path33, item) {
20857
+ async _handleSymlink(entry, directory, path34, item) {
19781
20858
  if (this.fsw.closed) {
19782
20859
  return;
19783
20860
  }
@@ -19787,7 +20864,7 @@ var NodeFsHandler = class {
19787
20864
  this.fsw._incrReadyCount();
19788
20865
  let linkPath;
19789
20866
  try {
19790
- linkPath = await (0, import_promises2.realpath)(path33);
20867
+ linkPath = await (0, import_promises2.realpath)(path34);
19791
20868
  } catch (e) {
19792
20869
  this.fsw._emitReady();
19793
20870
  return true;
@@ -19797,12 +20874,12 @@ var NodeFsHandler = class {
19797
20874
  if (dir.has(item)) {
19798
20875
  if (this.fsw._symlinkPaths.get(full) !== linkPath) {
19799
20876
  this.fsw._symlinkPaths.set(full, linkPath);
19800
- this.fsw._emit(EV.CHANGE, path33, entry.stats);
20877
+ this.fsw._emit(EV.CHANGE, path34, entry.stats);
19801
20878
  }
19802
20879
  } else {
19803
20880
  dir.add(item);
19804
20881
  this.fsw._symlinkPaths.set(full, linkPath);
19805
- this.fsw._emit(EV.ADD, path33, entry.stats);
20882
+ this.fsw._emit(EV.ADD, path34, entry.stats);
19806
20883
  }
19807
20884
  this.fsw._emitReady();
19808
20885
  return true;
@@ -19832,9 +20909,9 @@ var NodeFsHandler = class {
19832
20909
  return;
19833
20910
  }
19834
20911
  const item = entry.path;
19835
- let path33 = sp.join(directory, item);
20912
+ let path34 = sp.join(directory, item);
19836
20913
  current.add(item);
19837
- if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path33, item)) {
20914
+ if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path34, item)) {
19838
20915
  return;
19839
20916
  }
19840
20917
  if (this.fsw.closed) {
@@ -19843,11 +20920,11 @@ var NodeFsHandler = class {
19843
20920
  }
19844
20921
  if (item === target || !target && !previous.has(item)) {
19845
20922
  this.fsw._incrReadyCount();
19846
- path33 = sp.join(dir, sp.relative(dir, path33));
19847
- this._addToNodeFs(path33, initialAdd, wh, depth + 1);
20923
+ path34 = sp.join(dir, sp.relative(dir, path34));
20924
+ this._addToNodeFs(path34, initialAdd, wh, depth + 1);
19848
20925
  }
19849
20926
  }).on(EV.ERROR, this._boundHandleError);
19850
- return new Promise((resolve20, reject) => {
20927
+ return new Promise((resolve21, reject) => {
19851
20928
  if (!stream)
19852
20929
  return reject();
19853
20930
  stream.once(STR_END, () => {
@@ -19856,7 +20933,7 @@ var NodeFsHandler = class {
19856
20933
  return;
19857
20934
  }
19858
20935
  const wasThrottled = throttler ? throttler.clear() : false;
19859
- resolve20(void 0);
20936
+ resolve21(void 0);
19860
20937
  previous.getChildren().filter((item) => {
19861
20938
  return item !== directory && !current.has(item);
19862
20939
  }).forEach((item) => {
@@ -19913,13 +20990,13 @@ var NodeFsHandler = class {
19913
20990
  * @param depth Child path actually targeted for watch
19914
20991
  * @param target Child path actually targeted for watch
19915
20992
  */
19916
- async _addToNodeFs(path33, initialAdd, priorWh, depth, target) {
20993
+ async _addToNodeFs(path34, initialAdd, priorWh, depth, target) {
19917
20994
  const ready = this.fsw._emitReady;
19918
- if (this.fsw._isIgnored(path33) || this.fsw.closed) {
20995
+ if (this.fsw._isIgnored(path34) || this.fsw.closed) {
19919
20996
  ready();
19920
20997
  return false;
19921
20998
  }
19922
- const wh = this.fsw._getWatchHelpers(path33);
20999
+ const wh = this.fsw._getWatchHelpers(path34);
19923
21000
  if (priorWh) {
19924
21001
  wh.filterPath = (entry) => priorWh.filterPath(entry);
19925
21002
  wh.filterDir = (entry) => priorWh.filterDir(entry);
@@ -19935,8 +21012,8 @@ var NodeFsHandler = class {
19935
21012
  const follow = this.fsw.options.followSymlinks;
19936
21013
  let closer;
19937
21014
  if (stats.isDirectory()) {
19938
- const absPath = sp.resolve(path33);
19939
- const targetPath = follow ? await (0, import_promises2.realpath)(path33) : path33;
21015
+ const absPath = sp.resolve(path34);
21016
+ const targetPath = follow ? await (0, import_promises2.realpath)(path34) : path34;
19940
21017
  if (this.fsw.closed)
19941
21018
  return;
19942
21019
  closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
@@ -19946,29 +21023,29 @@ var NodeFsHandler = class {
19946
21023
  this.fsw._symlinkPaths.set(absPath, targetPath);
19947
21024
  }
19948
21025
  } else if (stats.isSymbolicLink()) {
19949
- const targetPath = follow ? await (0, import_promises2.realpath)(path33) : path33;
21026
+ const targetPath = follow ? await (0, import_promises2.realpath)(path34) : path34;
19950
21027
  if (this.fsw.closed)
19951
21028
  return;
19952
21029
  const parent = sp.dirname(wh.watchPath);
19953
21030
  this.fsw._getWatchedDir(parent).add(wh.watchPath);
19954
21031
  this.fsw._emit(EV.ADD, wh.watchPath, stats);
19955
- closer = await this._handleDir(parent, stats, initialAdd, depth, path33, wh, targetPath);
21032
+ closer = await this._handleDir(parent, stats, initialAdd, depth, path34, wh, targetPath);
19956
21033
  if (this.fsw.closed)
19957
21034
  return;
19958
21035
  if (targetPath !== void 0) {
19959
- this.fsw._symlinkPaths.set(sp.resolve(path33), targetPath);
21036
+ this.fsw._symlinkPaths.set(sp.resolve(path34), targetPath);
19960
21037
  }
19961
21038
  } else {
19962
21039
  closer = this._handleFile(wh.watchPath, stats, initialAdd);
19963
21040
  }
19964
21041
  ready();
19965
21042
  if (closer)
19966
- this.fsw._addPathCloser(path33, closer);
21043
+ this.fsw._addPathCloser(path34, closer);
19967
21044
  return false;
19968
21045
  } catch (error) {
19969
21046
  if (this.fsw._handleError(error)) {
19970
21047
  ready();
19971
- return path33;
21048
+ return path34;
19972
21049
  }
19973
21050
  }
19974
21051
  }
@@ -20011,24 +21088,24 @@ function createPattern(matcher) {
20011
21088
  }
20012
21089
  return () => false;
20013
21090
  }
20014
- function normalizePath3(path33) {
20015
- if (typeof path33 !== "string")
21091
+ function normalizePath3(path34) {
21092
+ if (typeof path34 !== "string")
20016
21093
  throw new Error("string expected");
20017
- path33 = sp2.normalize(path33);
20018
- path33 = path33.replace(/\\/g, "/");
21094
+ path34 = sp2.normalize(path34);
21095
+ path34 = path34.replace(/\\/g, "/");
20019
21096
  let prepend = false;
20020
- if (path33.startsWith("//"))
21097
+ if (path34.startsWith("//"))
20021
21098
  prepend = true;
20022
- path33 = path33.replace(DOUBLE_SLASH_RE, "/");
21099
+ path34 = path34.replace(DOUBLE_SLASH_RE, "/");
20023
21100
  if (prepend)
20024
- path33 = "/" + path33;
20025
- return path33;
21101
+ path34 = "/" + path34;
21102
+ return path34;
20026
21103
  }
20027
21104
  function matchPatterns(patterns, testString, stats) {
20028
- const path33 = normalizePath3(testString);
21105
+ const path34 = normalizePath3(testString);
20029
21106
  for (let index = 0; index < patterns.length; index++) {
20030
21107
  const pattern = patterns[index];
20031
- if (pattern(path33, stats)) {
21108
+ if (pattern(path34, stats)) {
20032
21109
  return true;
20033
21110
  }
20034
21111
  }
@@ -20066,19 +21143,19 @@ var toUnix = (string) => {
20066
21143
  }
20067
21144
  return str;
20068
21145
  };
20069
- var normalizePathToUnix = (path33) => toUnix(sp2.normalize(toUnix(path33)));
20070
- var normalizeIgnored = (cwd = "") => (path33) => {
20071
- if (typeof path33 === "string") {
20072
- return normalizePathToUnix(sp2.isAbsolute(path33) ? path33 : sp2.join(cwd, path33));
21146
+ var normalizePathToUnix = (path34) => toUnix(sp2.normalize(toUnix(path34)));
21147
+ var normalizeIgnored = (cwd = "") => (path34) => {
21148
+ if (typeof path34 === "string") {
21149
+ return normalizePathToUnix(sp2.isAbsolute(path34) ? path34 : sp2.join(cwd, path34));
20073
21150
  } else {
20074
- return path33;
21151
+ return path34;
20075
21152
  }
20076
21153
  };
20077
- var getAbsolutePath = (path33, cwd) => {
20078
- if (sp2.isAbsolute(path33)) {
20079
- return path33;
21154
+ var getAbsolutePath = (path34, cwd) => {
21155
+ if (sp2.isAbsolute(path34)) {
21156
+ return path34;
20080
21157
  }
20081
- return sp2.join(cwd, path33);
21158
+ return sp2.join(cwd, path34);
20082
21159
  };
20083
21160
  var EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
20084
21161
  var DirEntry = class {
@@ -20143,10 +21220,10 @@ var WatchHelper = class {
20143
21220
  dirParts;
20144
21221
  followSymlinks;
20145
21222
  statMethod;
20146
- constructor(path33, follow, fsw) {
21223
+ constructor(path34, follow, fsw) {
20147
21224
  this.fsw = fsw;
20148
- const watchPath = path33;
20149
- this.path = path33 = path33.replace(REPLACER_RE, "");
21225
+ const watchPath = path34;
21226
+ this.path = path34 = path34.replace(REPLACER_RE, "");
20150
21227
  this.watchPath = watchPath;
20151
21228
  this.fullWatchPath = sp2.resolve(watchPath);
20152
21229
  this.dirParts = [];
@@ -20286,20 +21363,20 @@ var FSWatcher = class extends import_node_events.EventEmitter {
20286
21363
  this._closePromise = void 0;
20287
21364
  let paths = unifyPaths(paths_);
20288
21365
  if (cwd) {
20289
- paths = paths.map((path33) => {
20290
- const absPath = getAbsolutePath(path33, cwd);
21366
+ paths = paths.map((path34) => {
21367
+ const absPath = getAbsolutePath(path34, cwd);
20291
21368
  return absPath;
20292
21369
  });
20293
21370
  }
20294
- paths.forEach((path33) => {
20295
- this._removeIgnoredPath(path33);
21371
+ paths.forEach((path34) => {
21372
+ this._removeIgnoredPath(path34);
20296
21373
  });
20297
21374
  this._userIgnored = void 0;
20298
21375
  if (!this._readyCount)
20299
21376
  this._readyCount = 0;
20300
21377
  this._readyCount += paths.length;
20301
- Promise.all(paths.map(async (path33) => {
20302
- const res = await this._nodeFsHandler._addToNodeFs(path33, !_internal, void 0, 0, _origAdd);
21378
+ Promise.all(paths.map(async (path34) => {
21379
+ const res = await this._nodeFsHandler._addToNodeFs(path34, !_internal, void 0, 0, _origAdd);
20303
21380
  if (res)
20304
21381
  this._emitReady();
20305
21382
  return res;
@@ -20321,17 +21398,17 @@ var FSWatcher = class extends import_node_events.EventEmitter {
20321
21398
  return this;
20322
21399
  const paths = unifyPaths(paths_);
20323
21400
  const { cwd } = this.options;
20324
- paths.forEach((path33) => {
20325
- if (!sp2.isAbsolute(path33) && !this._closers.has(path33)) {
21401
+ paths.forEach((path34) => {
21402
+ if (!sp2.isAbsolute(path34) && !this._closers.has(path34)) {
20326
21403
  if (cwd)
20327
- path33 = sp2.join(cwd, path33);
20328
- path33 = sp2.resolve(path33);
21404
+ path34 = sp2.join(cwd, path34);
21405
+ path34 = sp2.resolve(path34);
20329
21406
  }
20330
- this._closePath(path33);
20331
- this._addIgnoredPath(path33);
20332
- if (this._watched.has(path33)) {
21407
+ this._closePath(path34);
21408
+ this._addIgnoredPath(path34);
21409
+ if (this._watched.has(path34)) {
20333
21410
  this._addIgnoredPath({
20334
- path: path33,
21411
+ path: path34,
20335
21412
  recursive: true
20336
21413
  });
20337
21414
  }
@@ -20395,38 +21472,38 @@ var FSWatcher = class extends import_node_events.EventEmitter {
20395
21472
  * @param stats arguments to be passed with event
20396
21473
  * @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
20397
21474
  */
20398
- async _emit(event, path33, stats) {
21475
+ async _emit(event, path34, stats) {
20399
21476
  if (this.closed)
20400
21477
  return;
20401
21478
  const opts = this.options;
20402
21479
  if (isWindows)
20403
- path33 = sp2.normalize(path33);
21480
+ path34 = sp2.normalize(path34);
20404
21481
  if (opts.cwd)
20405
- path33 = sp2.relative(opts.cwd, path33);
20406
- const args = [path33];
21482
+ path34 = sp2.relative(opts.cwd, path34);
21483
+ const args = [path34];
20407
21484
  if (stats != null)
20408
21485
  args.push(stats);
20409
21486
  const awf = opts.awaitWriteFinish;
20410
21487
  let pw;
20411
- if (awf && (pw = this._pendingWrites.get(path33))) {
21488
+ if (awf && (pw = this._pendingWrites.get(path34))) {
20412
21489
  pw.lastChange = /* @__PURE__ */ new Date();
20413
21490
  return this;
20414
21491
  }
20415
21492
  if (opts.atomic) {
20416
21493
  if (event === EVENTS.UNLINK) {
20417
- this._pendingUnlinks.set(path33, [event, ...args]);
21494
+ this._pendingUnlinks.set(path34, [event, ...args]);
20418
21495
  setTimeout(() => {
20419
- this._pendingUnlinks.forEach((entry, path34) => {
21496
+ this._pendingUnlinks.forEach((entry, path35) => {
20420
21497
  this.emit(...entry);
20421
21498
  this.emit(EVENTS.ALL, ...entry);
20422
- this._pendingUnlinks.delete(path34);
21499
+ this._pendingUnlinks.delete(path35);
20423
21500
  });
20424
21501
  }, typeof opts.atomic === "number" ? opts.atomic : 100);
20425
21502
  return this;
20426
21503
  }
20427
- if (event === EVENTS.ADD && this._pendingUnlinks.has(path33)) {
21504
+ if (event === EVENTS.ADD && this._pendingUnlinks.has(path34)) {
20428
21505
  event = EVENTS.CHANGE;
20429
- this._pendingUnlinks.delete(path33);
21506
+ this._pendingUnlinks.delete(path34);
20430
21507
  }
20431
21508
  }
20432
21509
  if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
@@ -20444,16 +21521,16 @@ var FSWatcher = class extends import_node_events.EventEmitter {
20444
21521
  this.emitWithAll(event, args);
20445
21522
  }
20446
21523
  };
20447
- this._awaitWriteFinish(path33, awf.stabilityThreshold, event, awfEmit);
21524
+ this._awaitWriteFinish(path34, awf.stabilityThreshold, event, awfEmit);
20448
21525
  return this;
20449
21526
  }
20450
21527
  if (event === EVENTS.CHANGE) {
20451
- const isThrottled = !this._throttle(EVENTS.CHANGE, path33, 50);
21528
+ const isThrottled = !this._throttle(EVENTS.CHANGE, path34, 50);
20452
21529
  if (isThrottled)
20453
21530
  return this;
20454
21531
  }
20455
21532
  if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
20456
- const fullPath = opts.cwd ? sp2.join(opts.cwd, path33) : path33;
21533
+ const fullPath = opts.cwd ? sp2.join(opts.cwd, path34) : path34;
20457
21534
  let stats2;
20458
21535
  try {
20459
21536
  stats2 = await (0, import_promises3.stat)(fullPath);
@@ -20484,23 +21561,23 @@ var FSWatcher = class extends import_node_events.EventEmitter {
20484
21561
  * @param timeout duration of time to suppress duplicate actions
20485
21562
  * @returns tracking object or false if action should be suppressed
20486
21563
  */
20487
- _throttle(actionType, path33, timeout) {
21564
+ _throttle(actionType, path34, timeout) {
20488
21565
  if (!this._throttled.has(actionType)) {
20489
21566
  this._throttled.set(actionType, /* @__PURE__ */ new Map());
20490
21567
  }
20491
21568
  const action = this._throttled.get(actionType);
20492
21569
  if (!action)
20493
21570
  throw new Error("invalid throttle");
20494
- const actionPath = action.get(path33);
21571
+ const actionPath = action.get(path34);
20495
21572
  if (actionPath) {
20496
21573
  actionPath.count++;
20497
21574
  return false;
20498
21575
  }
20499
21576
  let timeoutObject;
20500
21577
  const clear = () => {
20501
- const item = action.get(path33);
21578
+ const item = action.get(path34);
20502
21579
  const count = item ? item.count : 0;
20503
- action.delete(path33);
21580
+ action.delete(path34);
20504
21581
  clearTimeout(timeoutObject);
20505
21582
  if (item)
20506
21583
  clearTimeout(item.timeoutObject);
@@ -20508,7 +21585,7 @@ var FSWatcher = class extends import_node_events.EventEmitter {
20508
21585
  };
20509
21586
  timeoutObject = setTimeout(clear, timeout);
20510
21587
  const thr = { timeoutObject, clear, count: 0 };
20511
- action.set(path33, thr);
21588
+ action.set(path34, thr);
20512
21589
  return thr;
20513
21590
  }
20514
21591
  _incrReadyCount() {
@@ -20522,44 +21599,44 @@ var FSWatcher = class extends import_node_events.EventEmitter {
20522
21599
  * @param event
20523
21600
  * @param awfEmit Callback to be called when ready for event to be emitted.
20524
21601
  */
20525
- _awaitWriteFinish(path33, threshold, event, awfEmit) {
21602
+ _awaitWriteFinish(path34, threshold, event, awfEmit) {
20526
21603
  const awf = this.options.awaitWriteFinish;
20527
21604
  if (typeof awf !== "object")
20528
21605
  return;
20529
21606
  const pollInterval = awf.pollInterval;
20530
21607
  let timeoutHandler;
20531
- let fullPath = path33;
20532
- if (this.options.cwd && !sp2.isAbsolute(path33)) {
20533
- fullPath = sp2.join(this.options.cwd, path33);
21608
+ let fullPath = path34;
21609
+ if (this.options.cwd && !sp2.isAbsolute(path34)) {
21610
+ fullPath = sp2.join(this.options.cwd, path34);
20534
21611
  }
20535
21612
  const now2 = /* @__PURE__ */ new Date();
20536
21613
  const writes = this._pendingWrites;
20537
21614
  function awaitWriteFinishFn(prevStat) {
20538
- (0, import_node_fs2.stat)(fullPath, (err, curStat) => {
20539
- if (err || !writes.has(path33)) {
21615
+ (0, import_node_fs3.stat)(fullPath, (err, curStat) => {
21616
+ if (err || !writes.has(path34)) {
20540
21617
  if (err && err.code !== "ENOENT")
20541
21618
  awfEmit(err);
20542
21619
  return;
20543
21620
  }
20544
21621
  const now3 = Number(/* @__PURE__ */ new Date());
20545
21622
  if (prevStat && curStat.size !== prevStat.size) {
20546
- writes.get(path33).lastChange = now3;
21623
+ writes.get(path34).lastChange = now3;
20547
21624
  }
20548
- const pw = writes.get(path33);
21625
+ const pw = writes.get(path34);
20549
21626
  const df = now3 - pw.lastChange;
20550
21627
  if (df >= threshold) {
20551
- writes.delete(path33);
21628
+ writes.delete(path34);
20552
21629
  awfEmit(void 0, curStat);
20553
21630
  } else {
20554
21631
  timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
20555
21632
  }
20556
21633
  });
20557
21634
  }
20558
- if (!writes.has(path33)) {
20559
- writes.set(path33, {
21635
+ if (!writes.has(path34)) {
21636
+ writes.set(path34, {
20560
21637
  lastChange: now2,
20561
21638
  cancelWait: () => {
20562
- writes.delete(path33);
21639
+ writes.delete(path34);
20563
21640
  clearTimeout(timeoutHandler);
20564
21641
  return event;
20565
21642
  }
@@ -20570,8 +21647,8 @@ var FSWatcher = class extends import_node_events.EventEmitter {
20570
21647
  /**
20571
21648
  * Determines whether user has asked to ignore this path.
20572
21649
  */
20573
- _isIgnored(path33, stats) {
20574
- if (this.options.atomic && DOT_RE.test(path33))
21650
+ _isIgnored(path34, stats) {
21651
+ if (this.options.atomic && DOT_RE.test(path34))
20575
21652
  return true;
20576
21653
  if (!this._userIgnored) {
20577
21654
  const { cwd } = this.options;
@@ -20581,17 +21658,17 @@ var FSWatcher = class extends import_node_events.EventEmitter {
20581
21658
  const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
20582
21659
  this._userIgnored = anymatch(list, void 0);
20583
21660
  }
20584
- return this._userIgnored(path33, stats);
21661
+ return this._userIgnored(path34, stats);
20585
21662
  }
20586
- _isntIgnored(path33, stat5) {
20587
- return !this._isIgnored(path33, stat5);
21663
+ _isntIgnored(path34, stat5) {
21664
+ return !this._isIgnored(path34, stat5);
20588
21665
  }
20589
21666
  /**
20590
21667
  * Provides a set of common helpers and properties relating to symlink handling.
20591
21668
  * @param path file or directory pattern being watched
20592
21669
  */
20593
- _getWatchHelpers(path33) {
20594
- return new WatchHelper(path33, this.options.followSymlinks, this);
21670
+ _getWatchHelpers(path34) {
21671
+ return new WatchHelper(path34, this.options.followSymlinks, this);
20595
21672
  }
20596
21673
  // Directory helpers
20597
21674
  // -----------------
@@ -20623,63 +21700,63 @@ var FSWatcher = class extends import_node_events.EventEmitter {
20623
21700
  * @param item base path of item/directory
20624
21701
  */
20625
21702
  _remove(directory, item, isDirectory) {
20626
- const path33 = sp2.join(directory, item);
20627
- const fullPath = sp2.resolve(path33);
20628
- isDirectory = isDirectory != null ? isDirectory : this._watched.has(path33) || this._watched.has(fullPath);
20629
- if (!this._throttle("remove", path33, 100))
21703
+ const path34 = sp2.join(directory, item);
21704
+ const fullPath = sp2.resolve(path34);
21705
+ isDirectory = isDirectory != null ? isDirectory : this._watched.has(path34) || this._watched.has(fullPath);
21706
+ if (!this._throttle("remove", path34, 100))
20630
21707
  return;
20631
21708
  if (!isDirectory && this._watched.size === 1) {
20632
21709
  this.add(directory, item, true);
20633
21710
  }
20634
- const wp = this._getWatchedDir(path33);
21711
+ const wp = this._getWatchedDir(path34);
20635
21712
  const nestedDirectoryChildren = wp.getChildren();
20636
- nestedDirectoryChildren.forEach((nested) => this._remove(path33, nested));
21713
+ nestedDirectoryChildren.forEach((nested) => this._remove(path34, nested));
20637
21714
  const parent = this._getWatchedDir(directory);
20638
21715
  const wasTracked = parent.has(item);
20639
21716
  parent.remove(item);
20640
21717
  if (this._symlinkPaths.has(fullPath)) {
20641
21718
  this._symlinkPaths.delete(fullPath);
20642
21719
  }
20643
- let relPath = path33;
21720
+ let relPath = path34;
20644
21721
  if (this.options.cwd)
20645
- relPath = sp2.relative(this.options.cwd, path33);
21722
+ relPath = sp2.relative(this.options.cwd, path34);
20646
21723
  if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
20647
21724
  const event = this._pendingWrites.get(relPath).cancelWait();
20648
21725
  if (event === EVENTS.ADD)
20649
21726
  return;
20650
21727
  }
20651
- this._watched.delete(path33);
21728
+ this._watched.delete(path34);
20652
21729
  this._watched.delete(fullPath);
20653
21730
  const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
20654
- if (wasTracked && !this._isIgnored(path33))
20655
- this._emit(eventName, path33);
20656
- this._closePath(path33);
21731
+ if (wasTracked && !this._isIgnored(path34))
21732
+ this._emit(eventName, path34);
21733
+ this._closePath(path34);
20657
21734
  }
20658
21735
  /**
20659
21736
  * Closes all watchers for a path
20660
21737
  */
20661
- _closePath(path33) {
20662
- this._closeFile(path33);
20663
- const dir = sp2.dirname(path33);
20664
- this._getWatchedDir(dir).remove(sp2.basename(path33));
21738
+ _closePath(path34) {
21739
+ this._closeFile(path34);
21740
+ const dir = sp2.dirname(path34);
21741
+ this._getWatchedDir(dir).remove(sp2.basename(path34));
20665
21742
  }
20666
21743
  /**
20667
21744
  * Closes only file-specific watchers
20668
21745
  */
20669
- _closeFile(path33) {
20670
- const closers = this._closers.get(path33);
21746
+ _closeFile(path34) {
21747
+ const closers = this._closers.get(path34);
20671
21748
  if (!closers)
20672
21749
  return;
20673
21750
  closers.forEach((closer) => closer());
20674
- this._closers.delete(path33);
21751
+ this._closers.delete(path34);
20675
21752
  }
20676
- _addPathCloser(path33, closer) {
21753
+ _addPathCloser(path34, closer) {
20677
21754
  if (!closer)
20678
21755
  return;
20679
- let list = this._closers.get(path33);
21756
+ let list = this._closers.get(path34);
20680
21757
  if (!list) {
20681
21758
  list = [];
20682
- this._closers.set(path33, list);
21759
+ this._closers.set(path34, list);
20683
21760
  }
20684
21761
  list.push(closer);
20685
21762
  }
@@ -20709,11 +21786,11 @@ function watch(paths, options = {}) {
20709
21786
  var chokidar_default = { watch, FSWatcher };
20710
21787
 
20711
21788
  // src/watcher/file-watcher.ts
20712
- var path28 = __toESM(require("path"), 1);
21789
+ var path29 = __toESM(require("path"), 1);
20713
21790
 
20714
21791
  // src/watcher/native-recursive-watcher.ts
20715
- var import_node_fs3 = require("fs");
20716
- var path26 = __toESM(require("path"), 1);
21792
+ var import_node_fs4 = require("fs");
21793
+ var path27 = __toESM(require("path"), 1);
20717
21794
  var NativeRecursiveWatcher = class {
20718
21795
  constructor(root, onChange, options = {}) {
20719
21796
  this.root = root;
@@ -20761,26 +21838,26 @@ var NativeRecursiveWatcher = class {
20761
21838
  toAbsolutePath(filename) {
20762
21839
  if (filename == null) return null;
20763
21840
  const normalizedFilename = typeof filename === "string" ? filename : filename.toString();
20764
- const absolutePath = path26.resolve(this.root, normalizedFilename);
20765
- const relativePath = path26.relative(this.root, absolutePath);
20766
- const outsideRoot = relativePath === ".." || relativePath.startsWith(`..${path26.sep}`) || path26.isAbsolute(relativePath);
21841
+ const absolutePath = path27.resolve(this.root, normalizedFilename);
21842
+ const relativePath = path27.relative(this.root, absolutePath);
21843
+ const outsideRoot = relativePath === ".." || relativePath.startsWith(`..${path27.sep}`) || path27.isAbsolute(relativePath);
20767
21844
  return outsideRoot ? null : absolutePath;
20768
21845
  }
20769
- defaultWatchFactory = (root, listener, options) => (0, import_node_fs3.watch)(root, options, listener);
21846
+ defaultWatchFactory = (root, listener, options) => (0, import_node_fs4.watch)(root, options, listener);
20770
21847
  };
20771
21848
 
20772
21849
  // src/watcher/snapshot.ts
20773
21850
  var fsPromises4 = __toESM(require("fs/promises"), 1);
20774
- var path27 = __toESM(require("path"), 1);
21851
+ var path28 = __toESM(require("path"), 1);
20775
21852
  async function buildFileSnapshotScan(projectRoot, config, configPaths = []) {
20776
- const normalizedProjectRoot = path27.resolve(projectRoot);
21853
+ const normalizedProjectRoot = path28.resolve(projectRoot);
20777
21854
  const ignoreFilter = createIgnoreFilter(normalizedProjectRoot);
20778
21855
  const includePatterns = [...config.include, ...config.additionalInclude ?? []];
20779
21856
  const maxDepth = config.indexing?.maxDepth ?? -1;
20780
21857
  const snapshot = /* @__PURE__ */ new Map();
20781
21858
  const unreadablePrefixes = /* @__PURE__ */ new Set();
20782
21859
  const includeFile = async (filePath) => {
20783
- const normalizedPath3 = path27.resolve(filePath);
21860
+ const normalizedPath3 = path28.resolve(filePath);
20784
21861
  if (!shouldIncludeFile(normalizedPath3, normalizedProjectRoot, includePatterns, config.exclude, ignoreFilter)) return;
20785
21862
  const stat5 = await readStatIfFile(normalizedPath3, unreadablePrefixes);
20786
21863
  if (stat5) snapshot.set(normalizedPath3, { size: stat5.size, mtimeMs: stat5.mtimeMs });
@@ -20792,16 +21869,16 @@ async function buildFileSnapshotScan(projectRoot, config, configPaths = []) {
20792
21869
  } catch (error) {
20793
21870
  if (isMissingFsError(error)) return;
20794
21871
  if (isPermissionFsError(error)) {
20795
- unreadablePrefixes.add(path27.resolve(directoryPath));
21872
+ unreadablePrefixes.add(path28.resolve(directoryPath));
20796
21873
  return;
20797
21874
  }
20798
21875
  throw error;
20799
21876
  }
20800
21877
  for (const entry of entries) {
20801
- const fullPath = path27.join(directoryPath, entry.name);
20802
- const relativePath = path27.relative(normalizedProjectRoot, fullPath);
21878
+ const fullPath = path28.join(directoryPath, entry.name);
21879
+ const relativePath = path28.relative(normalizedProjectRoot, fullPath);
20803
21880
  if (entry.isDirectory()) {
20804
- if (hasFilteredPathSegment(relativePath, path27.sep) || isRestrictedDirectory(relativePath, path27.sep)) continue;
21881
+ if (hasFilteredPathSegment(relativePath, path28.sep) || isRestrictedDirectory(relativePath, path28.sep)) continue;
20805
21882
  if (ignoreFilter.ignores(relativePath)) continue;
20806
21883
  if (maxDepth === -1 || depth < maxDepth) await walk(fullPath, depth + 1);
20807
21884
  } else if (entry.isFile()) {
@@ -20814,19 +21891,19 @@ async function buildFileSnapshotScan(projectRoot, config, configPaths = []) {
20814
21891
  return { entries: snapshot, unreadablePrefixes };
20815
21892
  }
20816
21893
  async function buildFileSnapshotForPathScan(projectRoot, config, configPaths, targetPath) {
20817
- const normalizedProjectRoot = path27.resolve(projectRoot);
20818
- const normalizedTargetPath = path27.resolve(targetPath);
21894
+ const normalizedProjectRoot = path28.resolve(projectRoot);
21895
+ const normalizedTargetPath = path28.resolve(targetPath);
20819
21896
  if (!isWithinPath(normalizedProjectRoot, normalizedTargetPath)) {
20820
21897
  return { entries: /* @__PURE__ */ new Map(), unreadablePrefixes: /* @__PURE__ */ new Set() };
20821
21898
  }
20822
21899
  const ignoreFilter = createIgnoreFilter(normalizedProjectRoot);
20823
21900
  const includePatterns = [...config.include, ...config.additionalInclude ?? []];
20824
21901
  const maxDepth = config.indexing?.maxDepth ?? -1;
20825
- const explicitConfigPaths = new Set(configPaths.map((configPath) => path27.resolve(configPath)));
21902
+ const explicitConfigPaths = new Set(configPaths.map((configPath) => path28.resolve(configPath)));
20826
21903
  const snapshot = /* @__PURE__ */ new Map();
20827
21904
  const unreadablePrefixes = /* @__PURE__ */ new Set();
20828
21905
  const includeFile = async (filePath) => {
20829
- const normalizedPath3 = path27.resolve(filePath);
21906
+ const normalizedPath3 = path28.resolve(filePath);
20830
21907
  if (!explicitConfigPaths.has(normalizedPath3) && !shouldIncludeFile(
20831
21908
  normalizedPath3,
20832
21909
  normalizedProjectRoot,
@@ -20844,16 +21921,16 @@ async function buildFileSnapshotForPathScan(projectRoot, config, configPaths, ta
20844
21921
  } catch (error) {
20845
21922
  if (isMissingFsError(error)) return;
20846
21923
  if (isPermissionFsError(error)) {
20847
- unreadablePrefixes.add(path27.resolve(directoryPath));
21924
+ unreadablePrefixes.add(path28.resolve(directoryPath));
20848
21925
  return;
20849
21926
  }
20850
21927
  throw error;
20851
21928
  }
20852
21929
  for (const entry of entries) {
20853
- const fullPath = path27.join(directoryPath, entry.name);
20854
- const relativePath = path27.relative(normalizedProjectRoot, fullPath);
21930
+ const fullPath = path28.join(directoryPath, entry.name);
21931
+ const relativePath = path28.relative(normalizedProjectRoot, fullPath);
20855
21932
  if (entry.isDirectory()) {
20856
- if (hasFilteredPathSegment(relativePath, path27.sep) || isRestrictedDirectory(relativePath, path27.sep)) continue;
21933
+ if (hasFilteredPathSegment(relativePath, path28.sep) || isRestrictedDirectory(relativePath, path28.sep)) continue;
20857
21934
  if (ignoreFilter.ignores(relativePath)) continue;
20858
21935
  if (maxDepth === -1 || depth < maxDepth) await walk(fullPath, depth + 1);
20859
21936
  } else if (entry.isFile()) {
@@ -20877,7 +21954,7 @@ function completeFileSnapshot(previous, scan) {
20877
21954
  return completed;
20878
21955
  }
20879
21956
  async function includeExplicitConfigPaths(snapshot, unreadablePrefixes, configPaths) {
20880
- for (const configPath of [...new Set(configPaths.map((value) => path27.resolve(value)))]) {
21957
+ for (const configPath of [...new Set(configPaths.map((value) => path28.resolve(value)))]) {
20881
21958
  if (snapshot.has(configPath)) continue;
20882
21959
  const stat5 = await readStatIfFile(configPath, unreadablePrefixes);
20883
21960
  if (stat5) snapshot.set(configPath, { size: stat5.size, mtimeMs: stat5.mtimeMs });
@@ -20887,12 +21964,12 @@ async function includeExplicitConfigPathsInPath(snapshot, unreadablePrefixes, co
20887
21964
  await includeExplicitConfigPaths(
20888
21965
  snapshot,
20889
21966
  unreadablePrefixes,
20890
- configPaths.filter((configPath) => isWithinPath(targetPath, path27.resolve(configPath)))
21967
+ configPaths.filter((configPath) => isWithinPath(targetPath, path28.resolve(configPath)))
20891
21968
  );
20892
21969
  }
20893
21970
  function isWithinPath(parentPath, childPath) {
20894
- const relativePath = path27.relative(parentPath, childPath);
20895
- return relativePath === "" || !relativePath.startsWith(`..${path27.sep}`) && relativePath !== ".." && !path27.isAbsolute(relativePath);
21971
+ const relativePath = path28.relative(parentPath, childPath);
21972
+ return relativePath === "" || !relativePath.startsWith(`..${path28.sep}`) && relativePath !== ".." && !path28.isAbsolute(relativePath);
20896
21973
  }
20897
21974
  async function readStatIfFile(filePath, unreadablePrefixes) {
20898
21975
  try {
@@ -20901,7 +21978,7 @@ async function readStatIfFile(filePath, unreadablePrefixes) {
20901
21978
  } catch (error) {
20902
21979
  if (isMissingFsError(error)) return null;
20903
21980
  if (isPermissionFsError(error)) {
20904
- unreadablePrefixes.add(path27.resolve(filePath));
21981
+ unreadablePrefixes.add(path28.resolve(filePath));
20905
21982
  return null;
20906
21983
  }
20907
21984
  throw error;
@@ -21038,8 +22115,8 @@ var FileWatcher = class {
21038
22115
  this.createWatcher();
21039
22116
  }
21040
22117
  resetReady() {
21041
- this.readyPromise = new Promise((resolve20) => {
21042
- this.resolveReady = resolve20;
22118
+ this.readyPromise = new Promise((resolve21) => {
22119
+ this.resolveReady = resolve21;
21043
22120
  });
21044
22121
  this.startupReadySignals = 1;
21045
22122
  }
@@ -21070,7 +22147,7 @@ var FileWatcher = class {
21070
22147
  const resolvedWatchTargets = watchTargets ?? this.getFullChokidarWatchTargets();
21071
22148
  const watcherOptions = {
21072
22149
  ignored: (filePath) => {
21073
- const relativePath = path28.relative(this.projectRoot, filePath);
22150
+ const relativePath = path29.relative(this.projectRoot, filePath);
21074
22151
  if (!relativePath) return false;
21075
22152
  if (this.isProjectConfigPathOrAncestor(relativePath)) {
21076
22153
  return false;
@@ -21078,10 +22155,10 @@ var FileWatcher = class {
21078
22155
  if (this.isOutsideProjectPath(relativePath)) {
21079
22156
  return true;
21080
22157
  }
21081
- if (hasFilteredPathSegment(relativePath, path28.sep)) {
22158
+ if (hasFilteredPathSegment(relativePath, path29.sep)) {
21082
22159
  return true;
21083
22160
  }
21084
- if (isRestrictedDirectory(relativePath, path28.sep)) {
22161
+ if (isRestrictedDirectory(relativePath, path29.sep)) {
21085
22162
  return true;
21086
22163
  }
21087
22164
  if (ignoreFilter.ignores(relativePath)) {
@@ -21172,13 +22249,13 @@ var FileWatcher = class {
21172
22249
  getExternalConfigWatchTargets() {
21173
22250
  return [...new Set(
21174
22251
  this.projectConfigPaths.filter((projectConfigPath) => {
21175
- const relativeConfigPath = path28.relative(this.projectRoot, projectConfigPath);
22252
+ const relativeConfigPath = path29.relative(this.projectRoot, projectConfigPath);
21176
22253
  return this.isOutsideProjectPath(relativeConfigPath);
21177
22254
  }).map((projectConfigPath) => {
21178
22255
  if ((0, import_fs19.existsSync)(projectConfigPath)) {
21179
22256
  return projectConfigPath;
21180
22257
  }
21181
- return this.getNearestExistingDirectory(path28.dirname(projectConfigPath));
22258
+ return this.getNearestExistingDirectory(path29.dirname(projectConfigPath));
21182
22259
  })
21183
22260
  )];
21184
22261
  }
@@ -21240,7 +22317,7 @@ var FileWatcher = class {
21240
22317
  }
21241
22318
  scheduleNativeReconciliation(generation, filePath) {
21242
22319
  if (!this.isCurrentNativeSetup(generation)) return;
21243
- const requiresFullReconciliation = filePath === path28.join(this.projectRoot, ".gitignore");
22320
+ const requiresFullReconciliation = filePath === path29.join(this.projectRoot, ".gitignore");
21244
22321
  const invalidatedPath = requiresFullReconciliation ? null : filePath;
21245
22322
  this.nativeInvalidatedPaths.set(invalidatedPath, invalidatedPath !== null);
21246
22323
  if (this.nativeReconcileTimer) {
@@ -21335,23 +22412,23 @@ var FileWatcher = class {
21335
22412
  this.scheduleFlush();
21336
22413
  }
21337
22414
  isProjectConfigPath(filePath) {
21338
- const relativePath = path28.relative(this.projectRoot, filePath);
21339
- const normalizedRelativePath = path28.normalize(relativePath);
22415
+ const relativePath = path29.relative(this.projectRoot, filePath);
22416
+ const normalizedRelativePath = path29.normalize(relativePath);
21340
22417
  return this.getProjectConfigRelativePaths().some((configPath) => configPath === normalizedRelativePath);
21341
22418
  }
21342
22419
  isProjectConfigPathOrAncestor(relativePath) {
21343
- const normalizedRelativePath = path28.normalize(relativePath);
22420
+ const normalizedRelativePath = path29.normalize(relativePath);
21344
22421
  return this.getProjectConfigRelativePaths().some(
21345
- (configPath) => configPath === normalizedRelativePath || configPath.startsWith(`${normalizedRelativePath}${path28.sep}`)
22422
+ (configPath) => configPath === normalizedRelativePath || configPath.startsWith(`${normalizedRelativePath}${path29.sep}`)
21346
22423
  );
21347
22424
  }
21348
22425
  isOutsideProjectPath(relativePath) {
21349
- return relativePath === ".." || relativePath.startsWith(`..${path28.sep}`) || path28.isAbsolute(relativePath);
22426
+ return relativePath === ".." || relativePath.startsWith(`..${path29.sep}`) || path29.isAbsolute(relativePath);
21350
22427
  }
21351
22428
  getNearestExistingDirectory(directoryPath) {
21352
22429
  let candidate = directoryPath;
21353
22430
  while (!(0, import_fs19.existsSync)(candidate)) {
21354
- const parent = path28.dirname(candidate);
22431
+ const parent = path29.dirname(candidate);
21355
22432
  if (parent === candidate) break;
21356
22433
  candidate = parent;
21357
22434
  }
@@ -21359,7 +22436,7 @@ var FileWatcher = class {
21359
22436
  }
21360
22437
  getProjectConfigRelativePaths() {
21361
22438
  return this.projectConfigPaths.map(
21362
- (configPath) => path28.normalize(path28.relative(this.projectRoot, configPath))
22439
+ (configPath) => path29.normalize(path29.relative(this.projectRoot, configPath))
21363
22440
  );
21364
22441
  }
21365
22442
  getConfigPathStates() {
@@ -21417,7 +22494,7 @@ var FileWatcher = class {
21417
22494
  return;
21418
22495
  }
21419
22496
  const changes = Array.from(this.pendingChanges.entries()).map(
21420
- ([path33, type]) => ({ path: path33, type })
22497
+ ([path34, type]) => ({ path: path34, type })
21421
22498
  );
21422
22499
  this.pendingChanges.clear();
21423
22500
  try {
@@ -21463,7 +22540,7 @@ var FileWatcher = class {
21463
22540
  };
21464
22541
 
21465
22542
  // src/watcher/git-head-watcher.ts
21466
- var path29 = __toESM(require("path"), 1);
22543
+ var path30 = __toESM(require("path"), 1);
21467
22544
  var GitHeadWatcher = class {
21468
22545
  watcher = null;
21469
22546
  projectRoot;
@@ -21485,13 +22562,13 @@ var GitHeadWatcher = class {
21485
22562
  this.readyPromise = Promise.resolve();
21486
22563
  return;
21487
22564
  }
21488
- this.readyPromise = new Promise((resolve20) => {
21489
- this.resolveReady = resolve20;
22565
+ this.readyPromise = new Promise((resolve21) => {
22566
+ this.resolveReady = resolve21;
21490
22567
  });
21491
22568
  this.onBranchChange = handler;
21492
22569
  this.currentBranch = getCurrentBranch(this.projectRoot);
21493
22570
  const headPath = getHeadPath(this.projectRoot);
21494
- const refsPath = path29.join(this.projectRoot, ".git", "refs", "heads");
22571
+ const refsPath = path30.join(this.projectRoot, ".git", "refs", "heads");
21495
22572
  this.watcher = chokidar_default.watch([headPath, refsPath], {
21496
22573
  persistent: true,
21497
22574
  ignoreInitial: true,
@@ -21559,7 +22636,9 @@ var GitHeadWatcher = class {
21559
22636
  function createWatcherWithIndexer(getIndexer, projectRoot, config, host, options = {}) {
21560
22637
  const fileWatcher = new FileWatcher(projectRoot, config, host, options);
21561
22638
  const configPaths = getConfigPaths(projectRoot, host, options);
21562
- configureAutoIndex(projectRoot, host, parseConfig(config), getIndexer);
22639
+ configureAutoIndex(projectRoot, host, parseConfig(config), getIndexer, {
22640
+ synchronizeBackgroundWorker: false
22641
+ });
21563
22642
  let stopped = false;
21564
22643
  const requestReindex = () => {
21565
22644
  if (stopped) return;
@@ -21579,7 +22658,9 @@ function createWatcherWithIndexer(getIndexer, projectRoot, config, host, options
21579
22658
  const parsedConfig = options.configPath ? parseConfig(loadConfigFile(options.configPath)) : void 0;
21580
22659
  const refreshedConfig = refreshIndexerForDirectory(projectRoot, host, parsedConfig);
21581
22660
  if (refreshedConfig) {
21582
- configureAutoIndex(projectRoot, host, refreshedConfig, getIndexer);
22661
+ configureAutoIndex(projectRoot, host, refreshedConfig, getIndexer, {
22662
+ synchronizeBackgroundWorker: false
22663
+ });
21583
22664
  }
21584
22665
  }
21585
22666
  requestReindex();
@@ -21627,7 +22708,7 @@ function getConfigPaths(projectRoot, host, options) {
21627
22708
 
21628
22709
  // src/tools/visualize/activity.ts
21629
22710
  var import_child_process5 = require("child_process");
21630
- var path30 = __toESM(require("path"), 1);
22711
+ var path31 = __toESM(require("path"), 1);
21631
22712
  function attachRecentActivity(data, projectRoot) {
21632
22713
  const activity = readGitActivity(projectRoot);
21633
22714
  const changes = activity.size > 0 ? buildGitChanges(data, activity, projectRoot) : buildGraphChanges(data);
@@ -21789,7 +22870,7 @@ function normalizePath4(filePath) {
21789
22870
  return filePath.replace(/\\/g, "/");
21790
22871
  }
21791
22872
  function toGitRelativePath(projectRoot, filePath) {
21792
- const relativePath = path30.isAbsolute(filePath) ? path30.relative(projectRoot, filePath) : filePath;
22873
+ const relativePath = path31.isAbsolute(filePath) ? path31.relative(projectRoot, filePath) : filePath;
21793
22874
  return normalizePath4(relativePath);
21794
22875
  }
21795
22876
 
@@ -22047,7 +23128,7 @@ render();
22047
23128
  }
22048
23129
 
22049
23130
  // src/tools/visualize/transform.ts
22050
- var path31 = __toESM(require("path"), 1);
23131
+ var path32 = __toESM(require("path"), 1);
22051
23132
 
22052
23133
  // src/tools/visualize/modules.ts
22053
23134
  var MAX_MODULES = 18;
@@ -22307,7 +23388,7 @@ function transformForVisualization(symbols, edges, options = {}) {
22307
23388
  filePath: s.filePath,
22308
23389
  kind: s.kind,
22309
23390
  line: s.startLine,
22310
- directory: path31.dirname(s.filePath),
23391
+ directory: path32.dirname(s.filePath),
22311
23392
  moduleId: "",
22312
23393
  moduleLabel: ""
22313
23394
  }));
@@ -22335,9 +23416,9 @@ function parseArgs(argv) {
22335
23416
  let host = "opencode";
22336
23417
  for (let i = 2; i < argv.length; i++) {
22337
23418
  if (argv[i] === "--project" && argv[i + 1]) {
22338
- project = path32.resolve(argv[++i]);
23419
+ project = path33.resolve(argv[++i]);
22339
23420
  } else if (argv[i] === "--config" && argv[i + 1]) {
22340
- config = path32.resolve(argv[++i]);
23421
+ config = path33.resolve(argv[++i]);
22341
23422
  } else if (argv[i] === "--host" && argv[i + 1]) {
22342
23423
  host = parseHostMode(argv[++i]);
22343
23424
  } else if (argv[i] === "--host") {
@@ -22365,7 +23446,7 @@ function parseIndexArgs(argv, cwd) {
22365
23446
  if (!arg.startsWith("--project=")) {
22366
23447
  i += 1;
22367
23448
  }
22368
- project = path32.resolve(cwd, value);
23449
+ project = path33.resolve(cwd, value);
22369
23450
  continue;
22370
23451
  }
22371
23452
  if (arg === "--config" || arg.startsWith("--config=")) {
@@ -22376,7 +23457,7 @@ function parseIndexArgs(argv, cwd) {
22376
23457
  if (!arg.startsWith("--config=")) {
22377
23458
  i += 1;
22378
23459
  }
22379
- config = path32.resolve(cwd, value);
23460
+ config = path33.resolve(cwd, value);
22380
23461
  continue;
22381
23462
  }
22382
23463
  if (arg === "--host" || arg.startsWith("--host=")) {
@@ -22446,7 +23527,7 @@ function parseVisualizeArgs(argv, cwd) {
22446
23527
  for (let i = 0; i < argv.length; i++) {
22447
23528
  const arg = argv[i];
22448
23529
  if (arg === "--project" && argv[i + 1]) {
22449
- project = path32.resolve(argv[++i]);
23530
+ project = path33.resolve(argv[++i]);
22450
23531
  } else if (arg === "--max" && argv[i + 1]) {
22451
23532
  maxNodes = Number(argv[++i]);
22452
23533
  } else if (arg.startsWith("--max=") || arg.startsWith("max=")) {
@@ -22483,7 +23564,7 @@ async function handleVisualizeCommand(argv, cwd) {
22483
23564
  console.error("No connected symbols found. Retry with: npm run visualize -- orphans");
22484
23565
  return 1;
22485
23566
  }
22486
- const outputPath = path32.join(os8.tmpdir(), `call-graph-${Date.now()}.html`);
23567
+ const outputPath = path33.join(os9.tmpdir(), `call-graph-${Date.now()}.html`);
22487
23568
  (0, import_fs20.writeFileSync)(outputPath, generateVisualizationHtml(vizData), "utf-8");
22488
23569
  console.log(`Temporal call graph visualization generated: ${outputPath}`);
22489
23570
  console.log(`Nodes: ${vizData.nodes.length} | Edges: ${vizData.edges.length}`);
@@ -22515,7 +23596,6 @@ async function runMcpCli(argv) {
22515
23596
  const config = parseConfig(rawConfig);
22516
23597
  const server = createMcpServer(args.project, config, args.host);
22517
23598
  const transport = new import_stdio.StdioServerTransport();
22518
- let watcher = null;
22519
23599
  let shutdownPromise;
22520
23600
  const onServerClose = server.server.onclose;
22521
23601
  const shutdown = () => {
@@ -22529,16 +23609,19 @@ async function runMcpCli(argv) {
22529
23609
  shutdownPromise = (async () => {
22530
23610
  let exitCode = 0;
22531
23611
  try {
22532
- await watcher?.stop();
22533
- } catch (error) {
22534
- exitCode = 1;
22535
- console.error("Failed to stop MCP file watcher cleanly:", error);
22536
- }
22537
- try {
22538
- await stopAutoIndex(args.project, args.host);
23612
+ await stopBackgroundWorker(args.project, args.host);
22539
23613
  } catch (error) {
22540
23614
  exitCode = 1;
22541
- console.error("Failed to stop automatic indexing cleanly:", error);
23615
+ if (error instanceof BackgroundWorkerStopError) {
23616
+ if (error.watcherError !== void 0) {
23617
+ console.error("Failed to stop MCP file watcher cleanly:", error.watcherError);
23618
+ }
23619
+ if (error.autoIndexError !== void 0) {
23620
+ console.error("Failed to stop automatic indexing cleanly:", error.autoIndexError);
23621
+ }
23622
+ } else {
23623
+ console.error("Failed to stop automatic indexing cleanly:", error);
23624
+ }
22542
23625
  }
22543
23626
  try {
22544
23627
  await server.close();
@@ -22567,19 +23650,25 @@ async function runMcpCli(argv) {
22567
23650
  process.once("SIGHUP", requestShutdown);
22568
23651
  process.once("SIGTERM", requestShutdown);
22569
23652
  }
22570
- await server.connect(transport);
22571
- if (shutdownPromise) return;
22572
23653
  const isHomeDir = isHomeDirectory(args.project);
22573
23654
  const isValidProject = !isHomeDir && (!config.indexing.requireProjectMarker || hasProjectMarker(args.project));
22574
- if (config.indexing.watchFiles && isValidProject) {
22575
- watcher = createWatcherWithIndexer(
22576
- () => getIndexerForProject(args.project, args.host),
22577
- args.project,
22578
- config,
22579
- args.host,
22580
- args.config ? { configPath: args.config } : {}
22581
- );
22582
- }
23655
+ const watcherFactoryForConfig = (refreshedConfig) => refreshedConfig.indexing.watchFiles && !isHomeDirectory(args.project) && (!refreshedConfig.indexing.requireProjectMarker || hasProjectMarker(args.project)) ? () => createWatcherWithIndexer(
23656
+ () => getIndexerForProject(args.project, args.host),
23657
+ args.project,
23658
+ refreshedConfig,
23659
+ args.host,
23660
+ args.config ? { configPath: args.config } : {}
23661
+ ) : null;
23662
+ await server.connect(transport);
23663
+ if (shutdownPromise) return;
23664
+ await attachMcpBackgroundWatcher(
23665
+ args.project,
23666
+ config,
23667
+ args.host,
23668
+ config.indexing.watchFiles && isValidProject ? watcherFactoryForConfig(config) : null,
23669
+ watcherFactoryForConfig
23670
+ );
23671
+ if (shutdownPromise) return;
22583
23672
  }
22584
23673
  function printIndexProgress(onProgress, title, metadata) {
22585
23674
  const details = Object.entries(metadata).filter(([, value]) => value !== void 0 && value !== null).map(([key, value]) => `${key}=${isSensitiveKey(key) ? "[REDACTED]" : String(value)}`).join(" ");