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/cbi.js CHANGED
@@ -329,7 +329,7 @@ var require_ignore = __commonJS({
329
329
  // path matching.
330
330
  // - check `string` either `MODE_IGNORE` or `MODE_CHECK_IGNORE`
331
331
  // @returns {TestResult} true if a file is ignored
332
- test(path34, checkUnignored, mode) {
332
+ test(path35, checkUnignored, mode) {
333
333
  let ignored = false;
334
334
  let unignored = false;
335
335
  let matchedRule;
@@ -338,7 +338,7 @@ var require_ignore = __commonJS({
338
338
  if (unignored === negative && ignored !== unignored || negative && !ignored && !unignored && !checkUnignored) {
339
339
  return;
340
340
  }
341
- const matched = rule[mode].test(path34);
341
+ const matched = rule[mode].test(path35);
342
342
  if (!matched) {
343
343
  return;
344
344
  }
@@ -359,17 +359,17 @@ var require_ignore = __commonJS({
359
359
  var throwError = (message, Ctor) => {
360
360
  throw new Ctor(message);
361
361
  };
362
- var checkPath = (path34, originalPath, doThrow) => {
363
- if (!isString(path34)) {
362
+ var checkPath = (path35, originalPath, doThrow) => {
363
+ if (!isString(path35)) {
364
364
  return doThrow(
365
365
  `path must be a string, but got \`${originalPath}\``,
366
366
  TypeError
367
367
  );
368
368
  }
369
- if (!path34) {
369
+ if (!path35) {
370
370
  return doThrow(`path must not be empty`, TypeError);
371
371
  }
372
- if (checkPath.isNotRelative(path34)) {
372
+ if (checkPath.isNotRelative(path35)) {
373
373
  const r = "`path.relative()`d";
374
374
  return doThrow(
375
375
  `path should be a ${r} string, but got "${originalPath}"`,
@@ -378,7 +378,7 @@ var require_ignore = __commonJS({
378
378
  }
379
379
  return true;
380
380
  };
381
- var isNotRelative = (path34) => REGEX_TEST_INVALID_PATH.test(path34);
381
+ var isNotRelative = (path35) => REGEX_TEST_INVALID_PATH.test(path35);
382
382
  checkPath.isNotRelative = isNotRelative;
383
383
  checkPath.convert = (p) => p;
384
384
  var Ignore2 = class {
@@ -408,19 +408,19 @@ var require_ignore = __commonJS({
408
408
  }
409
409
  // @returns {TestResult}
410
410
  _test(originalPath, cache, checkUnignored, slices) {
411
- const path34 = originalPath && checkPath.convert(originalPath);
411
+ const path35 = originalPath && checkPath.convert(originalPath);
412
412
  checkPath(
413
- path34,
413
+ path35,
414
414
  originalPath,
415
415
  this._strictPathCheck ? throwError : RETURN_FALSE
416
416
  );
417
- return this._t(path34, cache, checkUnignored, slices);
417
+ return this._t(path35, cache, checkUnignored, slices);
418
418
  }
419
- checkIgnore(path34) {
420
- if (!REGEX_TEST_TRAILING_SLASH.test(path34)) {
421
- return this.test(path34);
419
+ checkIgnore(path35) {
420
+ if (!REGEX_TEST_TRAILING_SLASH.test(path35)) {
421
+ return this.test(path35);
422
422
  }
423
- const slices = path34.split(SLASH).filter(Boolean);
423
+ const slices = path35.split(SLASH).filter(Boolean);
424
424
  slices.pop();
425
425
  if (slices.length) {
426
426
  const parent = this._t(
@@ -433,18 +433,18 @@ var require_ignore = __commonJS({
433
433
  return parent;
434
434
  }
435
435
  }
436
- return this._rules.test(path34, false, MODE_CHECK_IGNORE);
436
+ return this._rules.test(path35, false, MODE_CHECK_IGNORE);
437
437
  }
438
- _t(path34, cache, checkUnignored, slices) {
439
- if (path34 in cache) {
440
- return cache[path34];
438
+ _t(path35, cache, checkUnignored, slices) {
439
+ if (path35 in cache) {
440
+ return cache[path35];
441
441
  }
442
442
  if (!slices) {
443
- slices = path34.split(SLASH).filter(Boolean);
443
+ slices = path35.split(SLASH).filter(Boolean);
444
444
  }
445
445
  slices.pop();
446
446
  if (!slices.length) {
447
- return cache[path34] = this._rules.test(path34, checkUnignored, MODE_IGNORE);
447
+ return cache[path35] = this._rules.test(path35, checkUnignored, MODE_IGNORE);
448
448
  }
449
449
  const parent = this._t(
450
450
  slices.join(SLASH) + SLASH,
@@ -452,29 +452,29 @@ var require_ignore = __commonJS({
452
452
  checkUnignored,
453
453
  slices
454
454
  );
455
- return cache[path34] = parent.ignored ? parent : this._rules.test(path34, checkUnignored, MODE_IGNORE);
455
+ return cache[path35] = parent.ignored ? parent : this._rules.test(path35, checkUnignored, MODE_IGNORE);
456
456
  }
457
- ignores(path34) {
458
- return this._test(path34, this._ignoreCache, false).ignored;
457
+ ignores(path35) {
458
+ return this._test(path35, this._ignoreCache, false).ignored;
459
459
  }
460
460
  createFilter() {
461
- return (path34) => !this.ignores(path34);
461
+ return (path35) => !this.ignores(path35);
462
462
  }
463
463
  filter(paths) {
464
464
  return makeArray(paths).filter(this.createFilter());
465
465
  }
466
466
  // @returns {TestResult}
467
- test(path34) {
468
- return this._test(path34, this._testCache, true);
467
+ test(path35) {
468
+ return this._test(path35, this._testCache, true);
469
469
  }
470
470
  };
471
471
  var factory = (options) => new Ignore2(options);
472
- var isPathValid = (path34) => checkPath(path34 && checkPath.convert(path34), path34, RETURN_FALSE);
472
+ var isPathValid = (path35) => checkPath(path35 && checkPath.convert(path35), path35, RETURN_FALSE);
473
473
  var setupWindows = () => {
474
474
  const makePosix = (str) => /^\\\\\?\\/.test(str) || /["<>|\u0000-\u001F]+/u.test(str) ? str : str.replace(/\\/g, "/");
475
475
  checkPath.convert = makePosix;
476
476
  const REGEX_TEST_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i;
477
- checkPath.isNotRelative = (path34) => REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path34) || isNotRelative(path34);
477
+ checkPath.isNotRelative = (path35) => REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path35) || isNotRelative(path35);
478
478
  };
479
479
  if (
480
480
  // Detect `process` so that it can run in browsers.
@@ -652,8 +652,8 @@ var require_eventemitter3 = __commonJS({
652
652
  });
653
653
 
654
654
  // src/adapters/cbi.ts
655
- import { realpathSync as realpathSync7 } from "fs";
656
- import * as path33 from "path";
655
+ import { realpathSync as realpathSync8 } from "fs";
656
+ import * as path34 from "path";
657
657
  import { fileURLToPath as fileURLToPath3 } from "url";
658
658
 
659
659
  // src/config/host.ts
@@ -1720,8 +1720,8 @@ var autoDetectProviders = AUTO_DETECT_PROVIDER_ORDER.filter(
1720
1720
  );
1721
1721
 
1722
1722
  // src/tools/operations.ts
1723
- import { existsSync as existsSync12, realpathSync as realpathSync5, statSync as statSync5 } from "fs";
1724
- import * as path20 from "path";
1723
+ import { existsSync as existsSync13, realpathSync as realpathSync6, statSync as statSync5 } from "fs";
1724
+ import * as path21 from "path";
1725
1725
 
1726
1726
  // src/tools/knowledge-base-paths.ts
1727
1727
  import * as path8 from "path";
@@ -2521,9 +2521,9 @@ ${truncateContent(r.content)}
2521
2521
  }
2522
2522
 
2523
2523
  // src/utils/auto-index.ts
2524
- import { existsSync as existsSync7, realpathSync as realpathSync3 } from "fs";
2525
- import * as os3 from "os";
2526
- import * as path11 from "path";
2524
+ import { existsSync as existsSync8, realpathSync as realpathSync4 } from "fs";
2525
+ import * as os4 from "os";
2526
+ import * as path12 from "path";
2527
2527
 
2528
2528
  // src/indexer/index-lock.ts
2529
2529
  import { randomUUID } from "crypto";
@@ -2780,7 +2780,7 @@ function removeDeadReclaimMarker(lockPath, expectedOwner) {
2780
2780
  return true;
2781
2781
  }
2782
2782
  function reclaimDeadOwner(indexPath, lockPath, expectedOwner) {
2783
- const reclaimPath = path9.join(lockPath, RECLAIM_DIRECTORY_NAME);
2783
+ const reclaimPath2 = path9.join(lockPath, RECLAIM_DIRECTORY_NAME);
2784
2784
  const reclaimOwner = {
2785
2785
  pid: process.pid,
2786
2786
  hostname: os2.hostname(),
@@ -2789,19 +2789,19 @@ function reclaimDeadOwner(indexPath, lockPath, expectedOwner) {
2789
2789
  expectedOwnerToken: expectedOwner.token
2790
2790
  };
2791
2791
  for (let attempt = 0; attempt < 2; attempt += 1) {
2792
- if (publishJsonDirectory(reclaimPath, reclaimOwner)) break;
2792
+ if (publishJsonDirectory(reclaimPath2, reclaimOwner)) break;
2793
2793
  if (attempt === 0 && removeDeadReclaimMarker(lockPath, expectedOwner)) continue;
2794
2794
  return false;
2795
2795
  }
2796
2796
  try {
2797
- const currentReclaimer = readReclaimOwner(reclaimPath);
2797
+ const currentReclaimer = readReclaimOwner(reclaimPath2);
2798
2798
  const currentOwner = readDirectoryOwner(lockPath);
2799
2799
  if (!currentReclaimer || !sameReclaimOwner(currentReclaimer, reclaimOwner) || !currentOwner || !sameOwner(currentOwner, expectedOwner) || getOwnerLiveness(currentOwner) !== "dead") {
2800
2800
  return false;
2801
2801
  }
2802
2802
  publishRecoveryMarker(indexPath, expectedOwner);
2803
2803
  const ownerBeforeQuarantine = readDirectoryOwner(lockPath);
2804
- const reclaimerBeforeQuarantine = readReclaimOwner(reclaimPath);
2804
+ const reclaimerBeforeQuarantine = readReclaimOwner(reclaimPath2);
2805
2805
  if (!ownerBeforeQuarantine || !sameOwner(ownerBeforeQuarantine, expectedOwner) || getOwnerLiveness(ownerBeforeQuarantine) !== "dead" || !reclaimerBeforeQuarantine || !sameReclaimOwner(reclaimerBeforeQuarantine, reclaimOwner)) {
2806
2806
  return false;
2807
2807
  }
@@ -2971,10 +2971,889 @@ function completeLeaseRecovery(lease) {
2971
2971
  }
2972
2972
  }
2973
2973
 
2974
+ // src/utils/background-worker.ts
2975
+ import { createHash, randomUUID as randomUUID2 } from "crypto";
2976
+ import {
2977
+ existsSync as existsSync6,
2978
+ lstatSync as lstatSync2,
2979
+ mkdirSync as mkdirSync2,
2980
+ readFileSync as readFileSync5,
2981
+ realpathSync as realpathSync3,
2982
+ renameSync as renameSync2,
2983
+ rmSync as rmSync2,
2984
+ writeFileSync as writeFileSync2
2985
+ } from "fs";
2986
+ import * as os3 from "os";
2987
+ import * as path10 from "path";
2988
+ var OWNER_FILE_NAME2 = "owner.json";
2989
+ var HEARTBEAT_FILE_PREFIX = "heartbeat.";
2990
+ var RECLAIM_DIRECTORY_NAME2 = "reclaim";
2991
+ var REFRESH_REQUEST_FILE_NAME = "refresh-request.json";
2992
+ var HEARTBEAT_INTERVAL_MS = 5e3;
2993
+ var STALE_LEASE_MS = 3e4;
2994
+ var RETRY_DELAY_MS = 5e3;
2995
+ 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;
2996
+ var BackgroundWorkerStopError = class extends Error {
2997
+ constructor(watcherError, autoIndexError) {
2998
+ super("Failed to stop background worker");
2999
+ this.watcherError = watcherError;
3000
+ this.autoIndexError = autoIndexError;
3001
+ this.name = "BackgroundWorkerStopError";
3002
+ }
3003
+ watcherError;
3004
+ autoIndexError;
3005
+ };
3006
+ var workers = /* @__PURE__ */ new Map();
3007
+ var workerKeysByProject = /* @__PURE__ */ new Map();
3008
+ var workerReplacementBarriers = /* @__PURE__ */ new Map();
3009
+ function getErrorCode2(error) {
3010
+ return typeof error === "object" && error !== null && "code" in error ? String(error.code) : void 0;
3011
+ }
3012
+ function canonicalizePath(targetPath) {
3013
+ const resolved = path10.resolve(targetPath);
3014
+ if (existsSync6(resolved)) {
3015
+ try {
3016
+ return realpathSync3.native(resolved);
3017
+ } catch {
3018
+ return resolved;
3019
+ }
3020
+ }
3021
+ const parent = path10.dirname(resolved);
3022
+ if (parent === resolved) return resolved;
3023
+ return path10.join(canonicalizePath(parent), path10.basename(resolved));
3024
+ }
3025
+ function projectLookupKey(projectRoot, host) {
3026
+ return `${host}::${canonicalizePath(projectRoot)}`;
3027
+ }
3028
+ function resolveIdentity(projectRoot, config, host) {
3029
+ const canonicalProjectRoot = canonicalizePath(projectRoot);
3030
+ const canonicalIndexPath = canonicalizePath(resolveProjectIndexPath(projectRoot, config.scope, host));
3031
+ return {
3032
+ canonicalIndexPath,
3033
+ canonicalProjectRoot,
3034
+ key: `${canonicalIndexPath}::${canonicalProjectRoot}`
3035
+ };
3036
+ }
3037
+ function controllerKey(identity, host) {
3038
+ return `${identity.key}::${host}`;
3039
+ }
3040
+ function leaseDirectoryName(identity) {
3041
+ const hash = createHash("sha256").update(identity.key).digest("hex").slice(0, 32);
3042
+ return `background-worker.${hash}.lease`;
3043
+ }
3044
+ function leasePathFor(identity) {
3045
+ return path10.join(identity.canonicalIndexPath, leaseDirectoryName(identity));
3046
+ }
3047
+ function parseOwner2(value) {
3048
+ if (typeof value !== "object" || value === null) return null;
3049
+ const candidate = value;
3050
+ if (candidate.version !== 1) return null;
3051
+ if (!Number.isInteger(candidate.pid) || (candidate.pid ?? 0) <= 0) return null;
3052
+ if (typeof candidate.hostname !== "string" || candidate.hostname.length === 0) return null;
3053
+ if (typeof candidate.startedAt !== "string" || Number.isNaN(Date.parse(candidate.startedAt))) return null;
3054
+ if (typeof candidate.heartbeatAt !== "string" || Number.isNaN(Date.parse(candidate.heartbeatAt))) return null;
3055
+ if (typeof candidate.projectRoot !== "string" || candidate.projectRoot.length === 0) return null;
3056
+ if (typeof candidate.indexPath !== "string" || candidate.indexPath.length === 0) return null;
3057
+ if (typeof candidate.token !== "string" || !UUID_PATTERN2.test(candidate.token)) return null;
3058
+ return candidate;
3059
+ }
3060
+ function parseHeartbeat(value, expectedToken) {
3061
+ if (typeof value !== "object" || value === null) return null;
3062
+ const candidate = value;
3063
+ if (candidate.version !== 1 || candidate.token !== expectedToken) return null;
3064
+ if (typeof candidate.heartbeatAt !== "string" || Number.isNaN(Date.parse(candidate.heartbeatAt))) return null;
3065
+ return candidate;
3066
+ }
3067
+ function parseReclaimOwner2(value) {
3068
+ if (typeof value !== "object" || value === null) return null;
3069
+ const candidate = value;
3070
+ if (candidate.version !== 1) return null;
3071
+ if (!Number.isInteger(candidate.pid) || (candidate.pid ?? 0) <= 0) return null;
3072
+ if (typeof candidate.hostname !== "string" || candidate.hostname.length === 0) return null;
3073
+ if (typeof candidate.startedAt !== "string" || Number.isNaN(Date.parse(candidate.startedAt))) return null;
3074
+ if (typeof candidate.token !== "string" || !UUID_PATTERN2.test(candidate.token)) return null;
3075
+ if (candidate.expectedOwnerToken !== null && (typeof candidate.expectedOwnerToken !== "string" || !UUID_PATTERN2.test(candidate.expectedOwnerToken))) return null;
3076
+ return candidate;
3077
+ }
3078
+ function heartbeatPath(leasePath, token) {
3079
+ return path10.join(leasePath, `${HEARTBEAT_FILE_PREFIX}${token}.json`);
3080
+ }
3081
+ function reclaimPath(leasePath) {
3082
+ return path10.join(leasePath, RECLAIM_DIRECTORY_NAME2);
3083
+ }
3084
+ function refreshRequestPath(leasePath) {
3085
+ return path10.join(leasePath, REFRESH_REQUEST_FILE_NAME);
3086
+ }
3087
+ function readLeaseOwner(leasePath) {
3088
+ try {
3089
+ return parseOwner2(JSON.parse(readFileSync5(path10.join(leasePath, OWNER_FILE_NAME2), "utf-8")));
3090
+ } catch {
3091
+ return null;
3092
+ }
3093
+ }
3094
+ function readOwner(leasePath) {
3095
+ const owner = readLeaseOwner(leasePath);
3096
+ if (!owner) return null;
3097
+ try {
3098
+ const heartbeat = parseHeartbeat(
3099
+ JSON.parse(readFileSync5(heartbeatPath(leasePath, owner.token), "utf-8")),
3100
+ owner.token
3101
+ );
3102
+ return heartbeat ? { ...owner, heartbeatAt: heartbeat.heartbeatAt } : owner;
3103
+ } catch {
3104
+ return owner;
3105
+ }
3106
+ }
3107
+ function readReclaimOwner2(leasePath) {
3108
+ try {
3109
+ return parseReclaimOwner2(JSON.parse(readFileSync5(path10.join(reclaimPath(leasePath), OWNER_FILE_NAME2), "utf-8")));
3110
+ } catch {
3111
+ return null;
3112
+ }
3113
+ }
3114
+ function ownerLiveness(owner) {
3115
+ if (owner.hostname !== os3.hostname()) return "unknown";
3116
+ try {
3117
+ process.kill(owner.pid, 0);
3118
+ return "alive";
3119
+ } catch (error) {
3120
+ const code = getErrorCode2(error);
3121
+ if (code === "ESRCH") return "dead";
3122
+ if (code === "EPERM") return "alive";
3123
+ return "unknown";
3124
+ }
3125
+ }
3126
+ function isHeartbeatExpired(owner) {
3127
+ return Date.now() - Date.parse(owner.heartbeatAt) >= STALE_LEASE_MS;
3128
+ }
3129
+ function sameOwner2(left, right) {
3130
+ return left.pid === right.pid && left.hostname === right.hostname && left.token === right.token;
3131
+ }
3132
+ function writeHeartbeat(leasePath, owner) {
3133
+ const targetPath = heartbeatPath(leasePath, owner.token);
3134
+ const temporaryPath = `${targetPath}.tmp.${process.pid}.${owner.token}.${randomUUID2()}`;
3135
+ const heartbeat = {
3136
+ version: 1,
3137
+ token: owner.token,
3138
+ heartbeatAt: owner.heartbeatAt
3139
+ };
3140
+ try {
3141
+ writeFileSync2(temporaryPath, JSON.stringify(heartbeat), {
3142
+ encoding: "utf-8",
3143
+ flag: "wx",
3144
+ mode: 384
3145
+ });
3146
+ renameSync2(temporaryPath, targetPath);
3147
+ const currentOwner = readLeaseOwner(leasePath);
3148
+ return currentOwner !== null && sameOwner2(currentOwner, owner);
3149
+ } finally {
3150
+ if (existsSync6(temporaryPath)) rmSync2(temporaryPath, { force: true });
3151
+ }
3152
+ }
3153
+ function requestRefreshFromLeader(leasePath, allowDisabledAutoIndex) {
3154
+ const requestPath = refreshRequestPath(leasePath);
3155
+ const temporaryPath = `${requestPath}.tmp.${process.pid}.${randomUUID2()}`;
3156
+ try {
3157
+ const request = {
3158
+ allowDisabledAutoIndex,
3159
+ requestedAt: (/* @__PURE__ */ new Date()).toISOString(),
3160
+ version: 1
3161
+ };
3162
+ writeFileSync2(temporaryPath, JSON.stringify(request), {
3163
+ encoding: "utf-8",
3164
+ flag: "wx",
3165
+ mode: 384
3166
+ });
3167
+ renameSync2(temporaryPath, requestPath);
3168
+ } catch (error) {
3169
+ if (getErrorCode2(error) !== "ENOENT") {
3170
+ console.error("[codebase-index] Failed to request background index refresh from the project worker:", error);
3171
+ }
3172
+ } finally {
3173
+ if (existsSync6(temporaryPath)) rmSync2(temporaryPath, { force: true });
3174
+ }
3175
+ }
3176
+ function consumeRefreshRequest(leasePath) {
3177
+ const requestPath = refreshRequestPath(leasePath);
3178
+ const claimedPath = `${requestPath}.handling.${process.pid}.${randomUUID2()}`;
3179
+ try {
3180
+ renameSync2(requestPath, claimedPath);
3181
+ } catch (error) {
3182
+ if (getErrorCode2(error) === "ENOENT") return null;
3183
+ throw error;
3184
+ }
3185
+ try {
3186
+ const value = JSON.parse(readFileSync5(claimedPath, "utf-8"));
3187
+ return {
3188
+ allowDisabledAutoIndex: value.version === 1 && value.allowDisabledAutoIndex === true,
3189
+ requestedAt: typeof value.requestedAt === "string" ? value.requestedAt : (/* @__PURE__ */ new Date()).toISOString(),
3190
+ version: 1
3191
+ };
3192
+ } catch {
3193
+ return { allowDisabledAutoIndex: false, requestedAt: (/* @__PURE__ */ new Date()).toISOString(), version: 1 };
3194
+ } finally {
3195
+ rmSync2(claimedPath, { force: true });
3196
+ }
3197
+ }
3198
+ function publishLease(leasePath, owner) {
3199
+ const candidatePath = `${leasePath}.candidate.${process.pid}.${owner.token}`;
3200
+ try {
3201
+ mkdirSync2(candidatePath, { mode: 448 });
3202
+ } catch (error) {
3203
+ if (getErrorCode2(error) === "ENOENT") return false;
3204
+ throw error;
3205
+ }
3206
+ try {
3207
+ writeFileSync2(path10.join(candidatePath, OWNER_FILE_NAME2), JSON.stringify(owner), {
3208
+ encoding: "utf-8",
3209
+ flag: "wx",
3210
+ mode: 384
3211
+ });
3212
+ if (existsSync6(leasePath)) return false;
3213
+ try {
3214
+ renameSync2(candidatePath, leasePath);
3215
+ return true;
3216
+ } catch (error) {
3217
+ if (existsSync6(leasePath) || getErrorCode2(error) === "ENOENT") return false;
3218
+ throw error;
3219
+ }
3220
+ } finally {
3221
+ if (existsSync6(candidatePath)) rmSync2(candidatePath, { recursive: true, force: true });
3222
+ }
3223
+ }
3224
+ function sameReclaimOwner2(left, right) {
3225
+ return left.pid === right.pid && left.hostname === right.hostname && left.token === right.token && left.expectedOwnerToken === right.expectedOwnerToken;
3226
+ }
3227
+ function reclaimerLiveness(owner) {
3228
+ return ownerLiveness(owner);
3229
+ }
3230
+ function isReclaimMarkerExpired(leasePath, owner) {
3231
+ const startedAt = owner ? Date.parse(owner.startedAt) : (() => {
3232
+ try {
3233
+ return lstatSync2(reclaimPath(leasePath)).mtimeMs;
3234
+ } catch {
3235
+ return Date.now();
3236
+ }
3237
+ })();
3238
+ return Date.now() - startedAt >= STALE_LEASE_MS;
3239
+ }
3240
+ function hasActiveReclaimMarker(leasePath, owner) {
3241
+ const marker = readReclaimOwner2(leasePath);
3242
+ return marker !== null && marker.expectedOwnerToken === owner.token && (marker.hostname !== os3.hostname() || ownerLiveness(owner) !== "alive");
3243
+ }
3244
+ function publishReclaimMarker(leasePath, expectedOwner) {
3245
+ const markerPath = reclaimPath(leasePath);
3246
+ const owner = {
3247
+ version: 1,
3248
+ pid: process.pid,
3249
+ hostname: os3.hostname(),
3250
+ startedAt: (/* @__PURE__ */ new Date()).toISOString(),
3251
+ token: randomUUID2(),
3252
+ expectedOwnerToken: expectedOwner?.token ?? null
3253
+ };
3254
+ try {
3255
+ mkdirSync2(markerPath, { mode: 448 });
3256
+ } catch (error) {
3257
+ if (getErrorCode2(error) === "EEXIST" || getErrorCode2(error) === "ENOENT") return null;
3258
+ throw error;
3259
+ }
3260
+ try {
3261
+ writeFileSync2(path10.join(markerPath, OWNER_FILE_NAME2), JSON.stringify(owner), {
3262
+ encoding: "utf-8",
3263
+ flag: "wx",
3264
+ mode: 384
3265
+ });
3266
+ return owner;
3267
+ } catch (error) {
3268
+ rmSync2(markerPath, { recursive: true, force: true });
3269
+ throw error;
3270
+ }
3271
+ }
3272
+ function removeExpiredReclaimMarker(leasePath, expectedOwner) {
3273
+ const marker = readReclaimOwner2(leasePath);
3274
+ const markerPath = reclaimPath(leasePath);
3275
+ if (!existsSync6(markerPath)) return false;
3276
+ if (marker && marker.expectedOwnerToken !== (expectedOwner?.token ?? null)) return false;
3277
+ if (marker && (reclaimerLiveness(marker) === "alive" || !isReclaimMarkerExpired(leasePath, marker))) return false;
3278
+ if (!marker && !isReclaimMarkerExpired(leasePath, null)) return false;
3279
+ const staleMarkerPath = `${markerPath}.stale.${marker?.pid ?? process.pid}.${marker?.token ?? randomUUID2()}.${randomUUID2()}`;
3280
+ try {
3281
+ renameSync2(markerPath, staleMarkerPath);
3282
+ } catch (error) {
3283
+ if (getErrorCode2(error) === "ENOENT") return false;
3284
+ throw error;
3285
+ }
3286
+ try {
3287
+ let claimedMarker = null;
3288
+ try {
3289
+ claimedMarker = parseReclaimOwner2(
3290
+ JSON.parse(readFileSync5(path10.join(staleMarkerPath, OWNER_FILE_NAME2), "utf-8"))
3291
+ );
3292
+ } catch {
3293
+ claimedMarker = null;
3294
+ }
3295
+ const markerMatches = marker ? claimedMarker !== null && sameReclaimOwner2(claimedMarker, marker) : claimedMarker === null;
3296
+ if (!markerMatches || !canReclaimLease(leasePath, expectedOwner)) {
3297
+ if (!existsSync6(markerPath) && existsSync6(staleMarkerPath)) renameSync2(staleMarkerPath, markerPath);
3298
+ return false;
3299
+ }
3300
+ rmSync2(staleMarkerPath, { recursive: true, force: true });
3301
+ return true;
3302
+ } catch (error) {
3303
+ if (getErrorCode2(error) === "ENOENT") return false;
3304
+ throw error;
3305
+ }
3306
+ }
3307
+ function canReclaimLease(leasePath, expectedOwner) {
3308
+ if (!existsSync6(leasePath)) return false;
3309
+ if (!expectedOwner) return false;
3310
+ const currentOwner = readOwner(leasePath);
3311
+ if (!currentOwner || !sameOwner2(currentOwner, expectedOwner)) return false;
3312
+ if (currentOwner.hostname === os3.hostname()) {
3313
+ return ownerLiveness(currentOwner) === "dead";
3314
+ }
3315
+ return isHeartbeatExpired(currentOwner);
3316
+ }
3317
+ function reclaimLease(leasePath, expectedOwner) {
3318
+ let marker = null;
3319
+ for (let attempt = 0; attempt < 2; attempt += 1) {
3320
+ marker = publishReclaimMarker(leasePath, expectedOwner);
3321
+ if (marker) break;
3322
+ if (attempt === 0 && removeExpiredReclaimMarker(leasePath, expectedOwner)) continue;
3323
+ return false;
3324
+ }
3325
+ if (!marker) return false;
3326
+ const markerPath = reclaimPath(leasePath);
3327
+ try {
3328
+ const currentMarker = readReclaimOwner2(leasePath);
3329
+ if (!currentMarker || !sameReclaimOwner2(currentMarker, marker) || !canReclaimLease(leasePath, expectedOwner)) {
3330
+ return false;
3331
+ }
3332
+ const stalePath = `${leasePath}.stale.${process.pid}.${marker.token}`;
3333
+ renameSync2(leasePath, stalePath);
3334
+ const quarantinedOwner = readOwner(stalePath);
3335
+ const quarantinedMarker = readReclaimOwner2(stalePath);
3336
+ if (!quarantinedMarker || !sameReclaimOwner2(quarantinedMarker, marker) || expectedOwner !== null && (!quarantinedOwner || !sameOwner2(quarantinedOwner, expectedOwner))) {
3337
+ if (!existsSync6(leasePath) && existsSync6(stalePath)) renameSync2(stalePath, leasePath);
3338
+ return false;
3339
+ }
3340
+ rmSync2(stalePath, { recursive: true, force: true });
3341
+ return true;
3342
+ } catch (error) {
3343
+ if (getErrorCode2(error) === "ENOENT") return false;
3344
+ throw error;
3345
+ } finally {
3346
+ const currentMarker = readReclaimOwner2(leasePath);
3347
+ if (currentMarker && sameReclaimOwner2(currentMarker, marker)) {
3348
+ rmSync2(markerPath, { recursive: true, force: true });
3349
+ }
3350
+ }
3351
+ }
3352
+ function acquireLease(identity) {
3353
+ mkdirSync2(identity.canonicalIndexPath, { recursive: true, mode: 448 });
3354
+ const canonicalIndexPath = realpathSync3.native(identity.canonicalIndexPath);
3355
+ const leasePath = path10.join(canonicalIndexPath, leaseDirectoryName({ ...identity, canonicalIndexPath }));
3356
+ for (let attempt = 0; attempt < 4; attempt += 1) {
3357
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
3358
+ const owner = {
3359
+ version: 1,
3360
+ pid: process.pid,
3361
+ hostname: os3.hostname(),
3362
+ startedAt: timestamp,
3363
+ heartbeatAt: timestamp,
3364
+ projectRoot: identity.canonicalProjectRoot,
3365
+ indexPath: canonicalIndexPath,
3366
+ token: randomUUID2()
3367
+ };
3368
+ if (publishLease(leasePath, owner)) {
3369
+ return { leasePath, owner };
3370
+ }
3371
+ const existingOwner = readOwner(leasePath);
3372
+ if (existingOwner) {
3373
+ if (canReclaimLease(leasePath, existingOwner) && reclaimLease(leasePath, existingOwner)) continue;
3374
+ return null;
3375
+ }
3376
+ return null;
3377
+ }
3378
+ return null;
3379
+ }
3380
+ function releaseLease(lease) {
3381
+ const currentOwner = readOwner(lease.leasePath);
3382
+ if (!currentOwner || !sameOwner2(currentOwner, lease.owner)) return false;
3383
+ const releasePath = `${lease.leasePath}.release.${lease.owner.pid}.${lease.owner.token}`;
3384
+ try {
3385
+ renameSync2(lease.leasePath, releasePath);
3386
+ } catch (error) {
3387
+ if (getErrorCode2(error) === "ENOENT") return false;
3388
+ throw error;
3389
+ }
3390
+ const claimedOwner = readOwner(releasePath);
3391
+ if (!claimedOwner || !sameOwner2(claimedOwner, lease.owner)) {
3392
+ if (!existsSync6(lease.leasePath) && existsSync6(releasePath)) {
3393
+ renameSync2(releasePath, lease.leasePath);
3394
+ }
3395
+ return false;
3396
+ }
3397
+ rmSync2(releasePath, { recursive: true, force: true });
3398
+ return true;
3399
+ }
3400
+ var BackgroundWorkerController = class {
3401
+ constructor(projectRoot, host, config, hooks, identity) {
3402
+ this.projectRoot = projectRoot;
3403
+ this.host = host;
3404
+ this.config = config;
3405
+ this.hooks = hooks;
3406
+ this.identity = identity;
3407
+ }
3408
+ projectRoot;
3409
+ host;
3410
+ config;
3411
+ hooks;
3412
+ identity;
3413
+ lease = null;
3414
+ watcher = null;
3415
+ leaderReady = Promise.resolve();
3416
+ heartbeatTimer = null;
3417
+ retryTimer = null;
3418
+ teardownRetryTimer = null;
3419
+ transition = Promise.resolve();
3420
+ stopPromise = null;
3421
+ stopped = false;
3422
+ stopping = false;
3423
+ losingLeadership = false;
3424
+ restartAfterStop = false;
3425
+ leaderWorkStopped = false;
3426
+ startingLeaderWork = false;
3427
+ stopAutoIndexOnTeardown = true;
3428
+ autoIndexStarted = false;
3429
+ reportedError = null;
3430
+ update(config, hooks, options) {
3431
+ const autoIndexWasEnabled = this.config.indexing.autoIndex;
3432
+ const shouldReplaceWatcher = this.watcher !== null && hooks.watcherFactory !== void 0 && (hooks.watcherFactory === null || hooks.replaceWatcher === true);
3433
+ this.config = config;
3434
+ this.hooks = {
3435
+ ...this.hooks,
3436
+ ...hooks,
3437
+ watcherFactory: hooks.watcherFactory === void 0 ? this.hooks.watcherFactory : hooks.watcherFactory,
3438
+ watcherFactoryForConfig: hooks.watcherFactoryForConfig === void 0 ? this.hooks.watcherFactoryForConfig : hooks.watcherFactoryForConfig
3439
+ };
3440
+ if (autoIndexWasEnabled && !config.indexing.autoIndex || options.restartAutoIndex === true && config.indexing.autoIndex && !this.startingLeaderWork) {
3441
+ this.autoIndexStarted = false;
3442
+ }
3443
+ if (!this.canRun()) {
3444
+ void this.stop().catch((error) => {
3445
+ console.error("[codebase-index] Failed to stop background worker after disabling automatic work:", error);
3446
+ });
3447
+ return;
3448
+ }
3449
+ if (shouldReplaceWatcher) {
3450
+ void this.enqueue(async () => {
3451
+ const watcher = this.watcher;
3452
+ if (watcher) {
3453
+ await watcher.stop();
3454
+ if (this.watcher === watcher) this.watcher = null;
3455
+ }
3456
+ if (this.lease && !this.stopped) this.startLeaderWork();
3457
+ }).catch((error) => {
3458
+ console.error("[codebase-index] Failed to replace background file watcher:", error);
3459
+ });
3460
+ }
3461
+ this.start();
3462
+ }
3463
+ startAfter(activation) {
3464
+ this.transition = activation.catch(() => void 0);
3465
+ this.start();
3466
+ }
3467
+ start() {
3468
+ if (!this.canRun() || this.losingLeadership) return;
3469
+ if (this.stopping) {
3470
+ this.restartAfterStop = true;
3471
+ return;
3472
+ }
3473
+ this.stopped = false;
3474
+ void this.enqueue(async () => {
3475
+ if (this.stopped || this.stopping || this.losingLeadership || !this.canRun()) return;
3476
+ if (!this.lease) {
3477
+ try {
3478
+ this.lease = acquireLease(this.identity);
3479
+ this.reportedError = null;
3480
+ } catch (error) {
3481
+ this.reportAcquireError(error);
3482
+ this.scheduleRetry();
3483
+ return;
3484
+ }
3485
+ }
3486
+ if (!this.lease) {
3487
+ this.scheduleRetry();
3488
+ return;
3489
+ }
3490
+ this.startHeartbeat();
3491
+ this.startLeaderWork();
3492
+ });
3493
+ }
3494
+ waitForStart() {
3495
+ return this.transition.catch(() => void 0).then(() => this.leaderReady);
3496
+ }
3497
+ requestRefresh(allowDisabledAutoIndex = false) {
3498
+ this.start();
3499
+ if (!this.isLeader()) {
3500
+ requestRefreshFromLeader(leasePathFor(this.identity), allowDisabledAutoIndex);
3501
+ return;
3502
+ }
3503
+ void this.enqueue(async () => {
3504
+ if (this.stopped || !this.lease) return;
3505
+ this.hooks.startAutoIndex("retrieval", allowDisabledAutoIndex);
3506
+ });
3507
+ }
3508
+ isLeader() {
3509
+ return this.lease !== null && !this.stopping && !this.losingLeadership;
3510
+ }
3511
+ isStopping() {
3512
+ return this.stopping;
3513
+ }
3514
+ getHooksForConfig(config) {
3515
+ const watcherFactoryForConfig = this.hooks.watcherFactoryForConfig;
3516
+ if (!watcherFactoryForConfig) return this.hooks;
3517
+ return {
3518
+ ...this.hooks,
3519
+ watcherFactory: watcherFactoryForConfig(config),
3520
+ replaceWatcher: true
3521
+ };
3522
+ }
3523
+ attachWatcher(watcherFactory, watcherFactoryForConfig) {
3524
+ if (this.hooks.watcherFactory !== void 0) return;
3525
+ this.hooks = {
3526
+ ...this.hooks,
3527
+ watcherFactory,
3528
+ watcherFactoryForConfig: watcherFactoryForConfig ?? this.hooks.watcherFactoryForConfig
3529
+ };
3530
+ this.start();
3531
+ }
3532
+ async stop(stopAutoIndex = true) {
3533
+ if (this.stopPromise) return this.stopPromise;
3534
+ this.stopped = true;
3535
+ this.stopping = true;
3536
+ this.stopAutoIndexOnTeardown &&= stopAutoIndex;
3537
+ this.clearRetryTimer();
3538
+ const attempt = this.enqueue(async () => {
3539
+ try {
3540
+ const lease = this.lease;
3541
+ if (this.leaderWorkStopped) {
3542
+ if (lease) {
3543
+ this.releaseStoppedLease(lease);
3544
+ } else {
3545
+ this.finishStoppedLease();
3546
+ }
3547
+ return;
3548
+ }
3549
+ const hadLeaderWork = lease !== null || this.watcher !== null || this.autoIndexStarted;
3550
+ const stopped = await this.stopLeaderWork(hadLeaderWork && this.stopAutoIndexOnTeardown);
3551
+ if (!lease) {
3552
+ this.finishStoppedLease();
3553
+ return;
3554
+ }
3555
+ if (!stopped.completed) {
3556
+ this.releaseLeaseWhenAutoIndexStops(lease, stopped.completion);
3557
+ return;
3558
+ }
3559
+ this.leaderWorkStopped = true;
3560
+ this.releaseStoppedLease(lease);
3561
+ } catch (error) {
3562
+ this.scheduleTeardownRetry();
3563
+ throw error;
3564
+ }
3565
+ });
3566
+ const completion = attempt.finally(() => {
3567
+ if (this.stopPromise === completion) this.stopPromise = null;
3568
+ });
3569
+ this.stopPromise = completion;
3570
+ return completion;
3571
+ }
3572
+ canRun() {
3573
+ return this.config.indexing.autoIndex || this.hooks.watcherFactory != null;
3574
+ }
3575
+ enqueue(operation) {
3576
+ const next = this.transition.catch(() => void 0).then(operation);
3577
+ this.transition = next;
3578
+ return next;
3579
+ }
3580
+ startLeaderWork() {
3581
+ if (this.stopped || this.stopping || this.losingLeadership) return;
3582
+ this.startingLeaderWork = true;
3583
+ try {
3584
+ if (this.config.indexing.autoIndex && !this.autoIndexStarted) {
3585
+ this.autoIndexStarted = true;
3586
+ this.hooks.startAutoIndex("startup");
3587
+ }
3588
+ if (!this.watcher && this.hooks.watcherFactory) {
3589
+ try {
3590
+ const watcher = this.hooks.watcherFactory();
3591
+ this.watcher = watcher;
3592
+ this.leaderReady = watcher.whenReady?.().catch((error) => {
3593
+ console.error("[codebase-index] Failed while waiting for background file watcher startup:", error);
3594
+ }) ?? Promise.resolve();
3595
+ } catch (error) {
3596
+ console.error("[codebase-index] Failed to start background file watcher:", error);
3597
+ this.leaderReady = Promise.resolve();
3598
+ }
3599
+ }
3600
+ } finally {
3601
+ this.startingLeaderWork = false;
3602
+ }
3603
+ }
3604
+ async stopLeaderWork(stopAutoIndex) {
3605
+ const watcher = this.watcher;
3606
+ let watcherError;
3607
+ if (watcher) {
3608
+ try {
3609
+ await watcher.stop();
3610
+ if (this.watcher === watcher) this.watcher = null;
3611
+ } catch (error) {
3612
+ watcherError = error;
3613
+ }
3614
+ }
3615
+ let autoIndexError;
3616
+ let autoIndexStop = {
3617
+ completed: true,
3618
+ completion: Promise.resolve()
3619
+ };
3620
+ if (stopAutoIndex) {
3621
+ try {
3622
+ autoIndexStop = await this.hooks.stopAutoIndex();
3623
+ this.autoIndexStarted = false;
3624
+ } catch (error) {
3625
+ autoIndexError = error;
3626
+ }
3627
+ }
3628
+ if (watcherError !== void 0 || autoIndexError !== void 0) {
3629
+ throw new BackgroundWorkerStopError(watcherError, autoIndexError);
3630
+ }
3631
+ return autoIndexStop;
3632
+ }
3633
+ releaseLeaseWhenAutoIndexStops(lease, completion) {
3634
+ void completion.then(
3635
+ () => {
3636
+ void this.enqueue(async () => {
3637
+ if (this.lease !== lease || !this.stopping) return;
3638
+ this.leaderWorkStopped = true;
3639
+ this.releaseStoppedLease(lease);
3640
+ }).catch((error) => {
3641
+ console.error("[codebase-index] Failed to release background worker lease after automatic indexing stopped:", error);
3642
+ this.scheduleTeardownRetry();
3643
+ });
3644
+ },
3645
+ (error) => {
3646
+ console.error("[codebase-index] Failed while waiting for automatic indexing to stop:", error);
3647
+ this.scheduleTeardownRetry();
3648
+ }
3649
+ );
3650
+ }
3651
+ releaseStoppedLease(lease) {
3652
+ if (this.lease !== lease) {
3653
+ this.finishStoppedLease();
3654
+ return;
3655
+ }
3656
+ releaseLease(lease);
3657
+ this.lease = null;
3658
+ this.finishStoppedLease();
3659
+ }
3660
+ finishStoppedLease() {
3661
+ this.leaderWorkStopped = false;
3662
+ this.stopAutoIndexOnTeardown = true;
3663
+ this.stopping = false;
3664
+ this.clearTimers();
3665
+ this.restartAfterTeardown();
3666
+ if (!this.stopped || this.stopping) return;
3667
+ const projectKey = projectLookupKey(this.projectRoot, this.host);
3668
+ const key = controllerKey(this.identity, this.host);
3669
+ if (workers.get(key) === this) workers.delete(key);
3670
+ if (workerKeysByProject.get(projectKey) === key) workerKeysByProject.delete(projectKey);
3671
+ }
3672
+ startHeartbeat() {
3673
+ if (this.heartbeatTimer) return;
3674
+ const heartbeat = () => {
3675
+ void this.heartbeat();
3676
+ };
3677
+ this.heartbeatTimer = setInterval(heartbeat, HEARTBEAT_INTERVAL_MS);
3678
+ this.heartbeatTimer.unref?.();
3679
+ }
3680
+ async heartbeat() {
3681
+ const lease = this.lease;
3682
+ if (!lease || this.losingLeadership || this.stopped && !this.stopping) return;
3683
+ if (hasActiveReclaimMarker(lease.leasePath, lease.owner)) {
3684
+ await this.loseLeadership();
3685
+ return;
3686
+ }
3687
+ const currentOwner = readOwner(lease.leasePath);
3688
+ if (!currentOwner || !sameOwner2(currentOwner, lease.owner)) {
3689
+ await this.loseLeadership();
3690
+ return;
3691
+ }
3692
+ try {
3693
+ const nextOwner = { ...lease.owner, heartbeatAt: (/* @__PURE__ */ new Date()).toISOString() };
3694
+ if (!writeHeartbeat(lease.leasePath, nextOwner)) {
3695
+ await this.loseLeadership();
3696
+ return;
3697
+ }
3698
+ lease.owner = nextOwner;
3699
+ const refreshRequest = !this.stopping ? consumeRefreshRequest(lease.leasePath) : null;
3700
+ if (refreshRequest) {
3701
+ this.hooks.startAutoIndex("retrieval", refreshRequest.allowDisabledAutoIndex);
3702
+ }
3703
+ } catch (error) {
3704
+ const ownerAfterError = readOwner(lease.leasePath);
3705
+ if (hasActiveReclaimMarker(lease.leasePath, lease.owner) || !ownerAfterError || !sameOwner2(ownerAfterError, lease.owner)) {
3706
+ await this.loseLeadership();
3707
+ return;
3708
+ }
3709
+ console.error("[codebase-index] Failed to renew background worker lease:", error);
3710
+ }
3711
+ }
3712
+ async loseLeadership() {
3713
+ if (this.losingLeadership) return;
3714
+ this.losingLeadership = true;
3715
+ this.clearHeartbeat();
3716
+ await this.enqueue(async () => this.stopAfterLeadershipLoss());
3717
+ }
3718
+ async stopAfterLeadershipLoss() {
3719
+ const lease = this.lease;
3720
+ if (!lease) {
3721
+ this.losingLeadership = false;
3722
+ return;
3723
+ }
3724
+ try {
3725
+ const stopped = await this.stopLeaderWork(true);
3726
+ this.lease = null;
3727
+ this.losingLeadership = false;
3728
+ if (stopped.completed) {
3729
+ this.scheduleRetry();
3730
+ } else {
3731
+ void stopped.completion.then(() => this.scheduleRetry());
3732
+ }
3733
+ } catch (error) {
3734
+ console.error("[codebase-index] Failed to stop background work after losing its lease:", error);
3735
+ this.scheduleLostLeadershipTeardownRetry();
3736
+ }
3737
+ }
3738
+ scheduleRetry() {
3739
+ if (this.stopped || !this.canRun() || this.retryTimer) return;
3740
+ this.retryTimer = setTimeout(() => {
3741
+ this.retryTimer = null;
3742
+ this.start();
3743
+ }, RETRY_DELAY_MS);
3744
+ this.retryTimer.unref?.();
3745
+ }
3746
+ scheduleTeardownRetry() {
3747
+ if (!this.stopping || this.teardownRetryTimer) return;
3748
+ this.teardownRetryTimer = setTimeout(() => {
3749
+ this.teardownRetryTimer = null;
3750
+ void this.stop(this.stopAutoIndexOnTeardown).catch((error) => {
3751
+ console.error("[codebase-index] Failed to retry background worker teardown:", error);
3752
+ });
3753
+ }, RETRY_DELAY_MS);
3754
+ this.teardownRetryTimer.unref?.();
3755
+ }
3756
+ restartAfterTeardown() {
3757
+ if (!this.restartAfterStop || !this.canRun() || this.losingLeadership) return;
3758
+ this.restartAfterStop = false;
3759
+ this.stopped = false;
3760
+ this.start();
3761
+ }
3762
+ scheduleLostLeadershipTeardownRetry() {
3763
+ if (this.stopped || !this.losingLeadership || this.retryTimer) return;
3764
+ this.retryTimer = setTimeout(() => {
3765
+ this.retryTimer = null;
3766
+ void this.enqueue(async () => this.stopAfterLeadershipLoss());
3767
+ }, RETRY_DELAY_MS);
3768
+ this.retryTimer.unref?.();
3769
+ }
3770
+ clearHeartbeat() {
3771
+ if (!this.heartbeatTimer) return;
3772
+ clearInterval(this.heartbeatTimer);
3773
+ this.heartbeatTimer = null;
3774
+ }
3775
+ clearTimers() {
3776
+ this.clearHeartbeat();
3777
+ this.clearRetryTimer();
3778
+ if (this.teardownRetryTimer) {
3779
+ clearTimeout(this.teardownRetryTimer);
3780
+ this.teardownRetryTimer = null;
3781
+ }
3782
+ }
3783
+ clearRetryTimer() {
3784
+ if (!this.retryTimer) return;
3785
+ clearTimeout(this.retryTimer);
3786
+ this.retryTimer = null;
3787
+ }
3788
+ reportAcquireError(error) {
3789
+ const message = error instanceof Error ? error.message : String(error);
3790
+ if (this.reportedError === message) return;
3791
+ this.reportedError = message;
3792
+ console.error("[codebase-index] Failed to acquire background worker lease:", error);
3793
+ }
3794
+ };
3795
+ function configureBackgroundWorker(projectRoot, host, config, hooks, options = {}) {
3796
+ const projectKey = projectLookupKey(projectRoot, host);
3797
+ const identity = resolveIdentity(projectRoot, config, host);
3798
+ const key = controllerKey(identity, host);
3799
+ const previousKey = workerKeysByProject.get(projectKey);
3800
+ if (previousKey && previousKey !== key) {
3801
+ const previous = workers.get(previousKey);
3802
+ const previousBarrier = workerReplacementBarriers.get(projectKey) ?? Promise.resolve();
3803
+ const stopPrevious = previous?.stop(options.stopPreviousAutoIndex ?? true) ?? Promise.resolve();
3804
+ const activation = Promise.all([previousBarrier, stopPrevious]).then(() => void 0);
3805
+ workerReplacementBarriers.set(projectKey, activation);
3806
+ workers.delete(previousKey);
3807
+ const worker2 = new BackgroundWorkerController(projectRoot, host, config, hooks, identity);
3808
+ worker2.startAfter(activation);
3809
+ workers.set(key, worker2);
3810
+ workerKeysByProject.set(projectKey, key);
3811
+ return;
3812
+ }
3813
+ let worker = workers.get(key);
3814
+ if (!worker) {
3815
+ worker = new BackgroundWorkerController(projectRoot, host, config, hooks, identity);
3816
+ workers.set(key, worker);
3817
+ } else {
3818
+ worker.update(config, hooks, options);
3819
+ }
3820
+ workerKeysByProject.set(projectKey, key);
3821
+ worker.start();
3822
+ }
3823
+ function updateBackgroundWorkerConfig(projectRoot, host, config) {
3824
+ const projectKey = projectLookupKey(projectRoot, host);
3825
+ const key = workerKeysByProject.get(projectKey);
3826
+ const worker = key ? workers.get(key) : void 0;
3827
+ if (!worker) return;
3828
+ configureBackgroundWorker(projectRoot, host, config, worker.getHooksForConfig(config), {
3829
+ stopPreviousAutoIndex: false,
3830
+ restartAutoIndex: true
3831
+ });
3832
+ }
3833
+ function requestBackgroundWorkerRefresh(projectRoot, host, allowDisabledAutoIndex = false) {
3834
+ const key = workerKeysByProject.get(projectLookupKey(projectRoot, host));
3835
+ workers.get(key ?? "")?.requestRefresh(allowDisabledAutoIndex);
3836
+ }
3837
+ function isBackgroundWorkerManaged(projectRoot, host) {
3838
+ const key = workerKeysByProject.get(projectLookupKey(projectRoot, host));
3839
+ return key !== void 0 && workers.has(key);
3840
+ }
3841
+ function isBackgroundWorkerLeader(projectRoot, host) {
3842
+ const key = workerKeysByProject.get(projectLookupKey(projectRoot, host));
3843
+ return key !== void 0 && workers.get(key)?.isLeader() === true;
3844
+ }
3845
+ async function stopBackgroundWorker(projectRoot, host) {
3846
+ const projectKey = projectLookupKey(projectRoot, host);
3847
+ const key = workerKeysByProject.get(projectKey);
3848
+ const worker = key ? workers.get(key) : void 0;
3849
+ if (!worker) return;
3850
+ await worker.stop();
3851
+ }
3852
+
2974
3853
  // src/utils/files.ts
2975
3854
  var import_ignore = __toESM(require_ignore(), 1);
2976
- import { existsSync as existsSync6, readFileSync as readFileSync5, promises as fsPromises } from "fs";
2977
- import * as path10 from "path";
3855
+ import { existsSync as existsSync7, readFileSync as readFileSync6, promises as fsPromises } from "fs";
3856
+ import * as path11 from "path";
2978
3857
  var PROJECT_MARKERS = [
2979
3858
  ".git",
2980
3859
  "package.json",
@@ -2992,7 +3871,7 @@ var PROJECT_MARKERS = [
2992
3871
  ];
2993
3872
  function hasProjectMarker(projectRoot) {
2994
3873
  for (const marker of PROJECT_MARKERS) {
2995
- if (existsSync6(path10.join(projectRoot, marker))) {
3874
+ if (existsSync7(path11.join(projectRoot, marker))) {
2996
3875
  return true;
2997
3876
  }
2998
3877
  }
@@ -3019,13 +3898,40 @@ function createIgnoreFilter(projectRoot) {
3019
3898
  "**/*build*/**"
3020
3899
  ];
3021
3900
  ig.add(defaultIgnores);
3022
- const gitignorePath = path10.join(projectRoot, ".gitignore");
3023
- if (existsSync6(gitignorePath)) {
3024
- const gitignoreContent = readFileSync5(gitignorePath, "utf-8");
3901
+ const gitignorePath = path11.join(projectRoot, ".gitignore");
3902
+ if (existsSync7(gitignorePath)) {
3903
+ const gitignoreContent = readFileSync6(gitignorePath, "utf-8");
3025
3904
  ig.add(gitignoreContent);
3026
3905
  }
3027
3906
  return ig;
3028
3907
  }
3908
+ function toPosixRelativePath(relativePath) {
3909
+ return relativePath.split(path11.sep).join("/");
3910
+ }
3911
+ function matchesAnyGlob(filePath, patterns) {
3912
+ const normalized = toPosixRelativePath(filePath);
3913
+ return patterns.some((pattern) => matchGlob(normalized, pattern));
3914
+ }
3915
+ function isExcludedByPatterns(relativePath, excludePatterns) {
3916
+ return matchesAnyGlob(relativePath, excludePatterns);
3917
+ }
3918
+ function isExcludedDirectory(relativePath, excludePatterns) {
3919
+ const normalized = toPosixRelativePath(relativePath);
3920
+ if (matchesAnyGlob(normalized, excludePatterns)) {
3921
+ return true;
3922
+ }
3923
+ for (const pattern of excludePatterns) {
3924
+ const posixPattern = toPosixRelativePath(pattern).replace(/\/+$/, "");
3925
+ if (!posixPattern.endsWith("/**")) {
3926
+ continue;
3927
+ }
3928
+ const directoryPattern = posixPattern.slice(0, -3);
3929
+ if (directoryPattern && matchesAnyGlob(normalized, [directoryPattern])) {
3930
+ return true;
3931
+ }
3932
+ }
3933
+ return false;
3934
+ }
3029
3935
  function matchGlob(filePath, pattern) {
3030
3936
  if (pattern.startsWith("**/")) {
3031
3937
  const withoutPrefix = pattern.slice(3);
@@ -3046,8 +3952,8 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
3046
3952
  const filesInDir = [];
3047
3953
  const subdirs = [];
3048
3954
  for (const entry of entries) {
3049
- const fullPath = path10.join(dir, entry.name);
3050
- const relativePath = path10.relative(projectRoot, fullPath);
3955
+ const fullPath = path11.join(dir, entry.name);
3956
+ const relativePath = toPosixRelativePath(path11.relative(projectRoot, fullPath));
3051
3957
  if (isHiddenPathSegment(entry.name)) {
3052
3958
  if (entry.isDirectory()) {
3053
3959
  skipped.push({ path: relativePath, reason: "excluded" });
@@ -3065,6 +3971,10 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
3065
3971
  continue;
3066
3972
  }
3067
3973
  if (entry.isDirectory()) {
3974
+ if (isExcludedDirectory(relativePath, excludePatterns)) {
3975
+ skipped.push({ path: relativePath, reason: "excluded" });
3976
+ continue;
3977
+ }
3068
3978
  subdirs.push({ fullPath, relativePath });
3069
3979
  } else if (entry.isFile()) {
3070
3980
  const stat2 = await fsPromises.stat(fullPath);
@@ -3072,20 +3982,11 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
3072
3982
  skipped.push({ path: relativePath, reason: "too_large" });
3073
3983
  continue;
3074
3984
  }
3075
- for (const pattern of excludePatterns) {
3076
- if (matchGlob(relativePath, pattern)) {
3077
- skipped.push({ path: relativePath, reason: "excluded" });
3078
- continue;
3079
- }
3080
- }
3081
- let matched = false;
3082
- for (const pattern of includePatterns) {
3083
- if (matchGlob(relativePath, pattern)) {
3084
- matched = true;
3085
- break;
3086
- }
3985
+ if (isExcludedByPatterns(relativePath, excludePatterns)) {
3986
+ skipped.push({ path: relativePath, reason: "excluded" });
3987
+ continue;
3087
3988
  }
3088
- if (matched) {
3989
+ if (matchesAnyGlob(relativePath, includePatterns)) {
3089
3990
  filesInDir.push({ path: fullPath, size: stat2.size });
3090
3991
  }
3091
3992
  }
@@ -3096,7 +3997,7 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
3096
3997
  yield f;
3097
3998
  }
3098
3999
  for (let i = options.maxFilesPerDirectory; i < filesInDir.length; i++) {
3099
- skipped.push({ path: path10.relative(projectRoot, filesInDir[i].path), reason: "excluded" });
4000
+ skipped.push({ path: toPosixRelativePath(path11.relative(projectRoot, filesInDir[i].path)), reason: "excluded" });
3100
4001
  }
3101
4002
  const canRecurse = options.maxDepth === -1 || currentDepth < options.maxDepth;
3102
4003
  if (canRecurse) {
@@ -3136,8 +4037,8 @@ async function collectFiles(projectRoot, includePatterns, excludePatterns, maxFi
3136
4037
  if (additionalRoots && additionalRoots.length > 0) {
3137
4038
  const normalizedRoots = /* @__PURE__ */ new Set();
3138
4039
  for (const kbRoot of additionalRoots) {
3139
- const resolved = path10.normalize(
3140
- path10.isAbsolute(kbRoot) ? kbRoot : path10.resolve(projectRoot, kbRoot)
4040
+ const resolved = path11.normalize(
4041
+ path11.isAbsolute(kbRoot) ? kbRoot : path11.resolve(projectRoot, kbRoot)
3141
4042
  );
3142
4043
  normalizedRoots.add(resolved);
3143
4044
  }
@@ -3178,7 +4079,7 @@ function getErrorMessage(error) {
3178
4079
  return error instanceof Error ? error.message : String(error);
3179
4080
  }
3180
4081
  function runCommand(file, args, options) {
3181
- return new Promise((resolve19, reject) => {
4082
+ return new Promise((resolve20, reject) => {
3182
4083
  childProcess.execFile(
3183
4084
  file,
3184
4085
  args,
@@ -3188,7 +4089,7 @@ function runCommand(file, args, options) {
3188
4089
  reject(error);
3189
4090
  return;
3190
4091
  }
3191
- resolve19(stdout);
4092
+ resolve20(stdout);
3192
4093
  }
3193
4094
  );
3194
4095
  });
@@ -3280,29 +4181,29 @@ var AutoIndexCancelledError = class extends Error {
3280
4181
  function now() {
3281
4182
  return (/* @__PURE__ */ new Date()).toISOString();
3282
4183
  }
3283
- function canonicalizePath(targetPath) {
3284
- const resolved = path11.resolve(targetPath);
3285
- if (existsSync7(resolved)) {
4184
+ function canonicalizePath2(targetPath) {
4185
+ const resolved = path12.resolve(targetPath);
4186
+ if (existsSync8(resolved)) {
3286
4187
  try {
3287
- return realpathSync3.native(resolved);
4188
+ return realpathSync4.native(resolved);
3288
4189
  } catch {
3289
4190
  return resolved;
3290
4191
  }
3291
4192
  }
3292
- const parent = path11.dirname(resolved);
4193
+ const parent = path12.dirname(resolved);
3293
4194
  if (parent === resolved) return resolved;
3294
- return path11.join(canonicalizePath(parent), path11.basename(resolved));
4195
+ return path12.join(canonicalizePath2(parent), path12.basename(resolved));
3295
4196
  }
3296
4197
  function isHomeDirectory(projectRoot) {
3297
- return canonicalizePath(projectRoot) === canonicalizePath(os3.homedir());
4198
+ return canonicalizePath2(projectRoot) === canonicalizePath2(os4.homedir());
3298
4199
  }
3299
- function projectLookupKey(projectRoot, host) {
3300
- return `${host}::${canonicalizePath(projectRoot)}`;
4200
+ function projectLookupKey2(projectRoot, host) {
4201
+ return `${host}::${canonicalizePath2(projectRoot)}`;
3301
4202
  }
3302
4203
  function coordinatorKey(projectRoot, config, host) {
3303
- const canonicalProjectRoot = canonicalizePath(projectRoot);
4204
+ const canonicalProjectRoot = canonicalizePath2(projectRoot);
3304
4205
  const indexPath = resolveProjectIndexPath(projectRoot, config.scope, host);
3305
- return `${canonicalizePath(indexPath)}::${canonicalProjectRoot}`;
4206
+ return `${canonicalizePath2(indexPath)}::${canonicalProjectRoot}`;
3306
4207
  }
3307
4208
  function getProjectSafety(projectRoot, config) {
3308
4209
  if (isHomeDirectory(projectRoot)) {
@@ -3333,10 +4234,10 @@ function safeFailureMessage(error) {
3333
4234
  }
3334
4235
  function cancellableDelay(delayMs, signal) {
3335
4236
  if (signal.aborted) return Promise.reject(new AutoIndexCancelledError());
3336
- return new Promise((resolve19, reject) => {
4237
+ return new Promise((resolve20, reject) => {
3337
4238
  const timer = setTimeout(() => {
3338
4239
  signal.removeEventListener("abort", onAbort);
3339
- resolve19();
4240
+ resolve20();
3340
4241
  }, delayMs);
3341
4242
  timer.unref?.();
3342
4243
  const onAbort = () => {
@@ -3348,18 +4249,44 @@ function cancellableDelay(delayMs, signal) {
3348
4249
  }
3349
4250
  function withTimeout(promise, timeoutMs) {
3350
4251
  if (timeoutMs <= 0) return Promise.resolve(void 0);
3351
- return new Promise((resolve19) => {
3352
- const timer = setTimeout(() => resolve19(void 0), timeoutMs);
4252
+ return new Promise((resolve20) => {
4253
+ const timer = setTimeout(() => resolve20(void 0), timeoutMs);
3353
4254
  timer.unref?.();
3354
4255
  void promise.then((value) => {
3355
4256
  clearTimeout(timer);
3356
- resolve19(value);
4257
+ resolve20(value);
3357
4258
  }, () => {
3358
4259
  clearTimeout(timer);
3359
- resolve19(void 0);
4260
+ resolve20(void 0);
3360
4261
  });
3361
4262
  });
3362
4263
  }
4264
+ function settlesWithin(promise, timeoutMs) {
4265
+ if (timeoutMs <= 0) return Promise.resolve(false);
4266
+ return new Promise((resolve20) => {
4267
+ let settled = false;
4268
+ const timer = setTimeout(() => {
4269
+ if (settled) return;
4270
+ settled = true;
4271
+ resolve20(false);
4272
+ }, timeoutMs);
4273
+ timer.unref?.();
4274
+ void promise.then(
4275
+ () => {
4276
+ if (settled) return;
4277
+ settled = true;
4278
+ clearTimeout(timer);
4279
+ resolve20(true);
4280
+ },
4281
+ () => {
4282
+ if (settled) return;
4283
+ settled = true;
4284
+ clearTimeout(timer);
4285
+ resolve20(true);
4286
+ }
4287
+ );
4288
+ });
4289
+ }
3363
4290
  function requestPriority(request) {
3364
4291
  if (request.force) return 4;
3365
4292
  if (request.source === "manual") return 3;
@@ -3370,6 +4297,7 @@ function mergeRequests(current, next) {
3370
4297
  if (!current) return next;
3371
4298
  const preferred = requestPriority(next) > requestPriority(current) ? next : current;
3372
4299
  return {
4300
+ allowDisabledAutoIndex: current.allowDisabledAutoIndex || next.allowDisabledAutoIndex,
3373
4301
  checkFreshness: current.checkFreshness && next.checkFreshness,
3374
4302
  force: current.force || next.force,
3375
4303
  onProgress: next.onProgress ?? current.onProgress,
@@ -3431,11 +4359,11 @@ var AutoIndexCoordinator = class {
3431
4359
  progress: this.status.progress ? { ...this.status.progress } : void 0
3432
4360
  };
3433
4361
  }
3434
- start(source) {
4362
+ start(source, allowDisabledAutoIndex = false) {
3435
4363
  this.refreshSafety();
3436
- if (!this.registration.config.indexing.autoIndex || !this.registration.safeToRun) return null;
4364
+ if (!this.registration.config.indexing.autoIndex && !allowDisabledAutoIndex || !this.registration.safeToRun) return null;
3437
4365
  if (this.status.state === "failed") return this.inFlight;
3438
- return this.request({ checkFreshness: true, force: false, source });
4366
+ return this.request({ allowDisabledAutoIndex, checkFreshness: true, force: false, source });
3439
4367
  }
3440
4368
  request(request) {
3441
4369
  if (this.stopped) {
@@ -3510,13 +4438,15 @@ var AutoIndexCoordinator = class {
3510
4438
  retryAttempt: void 0
3511
4439
  });
3512
4440
  const inFlight = this.inFlight;
3513
- if (inFlight) {
3514
- if (waitForCompletion) {
3515
- await inFlight;
3516
- } else {
3517
- await withTimeout(inFlight, SHUTDOWN_WAIT_MS);
3518
- }
4441
+ const completion = inFlight ? inFlight.then(() => void 0, () => void 0) : Promise.resolve();
4442
+ if (!inFlight) {
4443
+ return { completed: true, completion };
3519
4444
  }
4445
+ if (waitForCompletion) {
4446
+ await completion;
4447
+ return { completed: true, completion };
4448
+ }
4449
+ return { completed: await settlesWithin(completion, SHUTDOWN_WAIT_MS), completion };
3520
4450
  }
3521
4451
  startRequest(request) {
3522
4452
  if (this.stopped || !this.canRun(request)) {
@@ -3705,7 +4635,7 @@ var AutoIndexCoordinator = class {
3705
4635
  if (request.source === "manual" || request.source === "watcher") {
3706
4636
  return true;
3707
4637
  }
3708
- return this.registration.safeToRun && this.registration.config.indexing.autoIndex;
4638
+ return this.registration.safeToRun && (this.registration.config.indexing.autoIndex || request.allowDisabledAutoIndex === true);
3709
4639
  }
3710
4640
  shouldDeferForBattery(request) {
3711
4641
  return this.registration.backgroundIndexingPolicy !== null && (request.source === "startup" || request.source === "watcher");
@@ -3738,17 +4668,17 @@ var AutoIndexCoordinator = class {
3738
4668
  }
3739
4669
  }
3740
4670
  waitForBatteryRetry(delayMs) {
3741
- return new Promise((resolve19) => {
4671
+ return new Promise((resolve20) => {
3742
4672
  const timer = setTimeout(() => {
3743
4673
  if (this.batteryRetryTimer === timer) {
3744
4674
  this.batteryRetryTimer = null;
3745
4675
  this.resolveBatteryRetry = null;
3746
4676
  }
3747
- resolve19();
4677
+ resolve20();
3748
4678
  }, delayMs);
3749
4679
  timer.unref?.();
3750
4680
  this.batteryRetryTimer = timer;
3751
- this.resolveBatteryRetry = resolve19;
4681
+ this.resolveBatteryRetry = resolve20;
3752
4682
  });
3753
4683
  }
3754
4684
  cancelBatteryRetry() {
@@ -3756,9 +4686,9 @@ var AutoIndexCoordinator = class {
3756
4686
  clearTimeout(this.batteryRetryTimer);
3757
4687
  this.batteryRetryTimer = null;
3758
4688
  }
3759
- const resolve19 = this.resolveBatteryRetry;
4689
+ const resolve20 = this.resolveBatteryRetry;
3760
4690
  this.resolveBatteryRetry = null;
3761
- resolve19?.();
4691
+ resolve20?.();
3762
4692
  }
3763
4693
  finishBatteryCheck(batteryCheck) {
3764
4694
  if (this.batteryCheck !== batteryCheck) return;
@@ -3771,12 +4701,25 @@ var AutoIndexCoordinator = class {
3771
4701
  }
3772
4702
  };
3773
4703
  function getCoordinator(projectRoot, host) {
3774
- const key = coordinatorKeysByProject.get(projectLookupKey(projectRoot, host));
4704
+ const key = coordinatorKeysByProject.get(projectLookupKey2(projectRoot, host));
3775
4705
  return key ? coordinators.get(key) ?? null : null;
3776
4706
  }
3777
- function configureAutoIndex(projectRoot, host, config, getIndexer) {
3778
- const projectKey = projectLookupKey(projectRoot, host);
4707
+ function synchronizeBackgroundWorker(projectRoot, host, config, safeToRun) {
4708
+ if (safeToRun) {
4709
+ updateBackgroundWorkerConfig(projectRoot, host, config);
4710
+ return;
4711
+ }
4712
+ void stopBackgroundWorker(projectRoot, host).catch((error) => {
4713
+ console.error("[codebase-index] Failed to stop background worker after project safety changed:", error);
4714
+ });
4715
+ }
4716
+ function configureAutoIndex(projectRoot, host, config, getIndexer, options = {}) {
4717
+ const projectKey = projectLookupKey2(projectRoot, host);
3779
4718
  const safety = getProjectSafety(projectRoot, config);
4719
+ const synchronizeWorker = options.synchronizeBackgroundWorker ?? true;
4720
+ if (options.preserveManagedWorker === true && isBackgroundWorkerManaged(projectRoot, host)) {
4721
+ return;
4722
+ }
3780
4723
  const registration = {
3781
4724
  backgroundIndexingPolicy: createBackgroundIndexingPolicy(
3782
4725
  config.indexing.pauseBackgroundIndexingOnBattery
@@ -3794,6 +4737,9 @@ function configureAutoIndex(projectRoot, host, config, getIndexer) {
3794
4737
  const stopPrevious = previousCoordinator?.stop(true) ?? Promise.resolve();
3795
4738
  const activation = Promise.all([previousBarrier, stopPrevious]).then(() => void 0);
3796
4739
  coordinatorReplacementBarriers.set(projectKey, activation);
4740
+ if (synchronizeWorker) {
4741
+ synchronizeBackgroundWorker(projectRoot, host, config, safety.safeToRun);
4742
+ }
3797
4743
  coordinators.delete(previousKey);
3798
4744
  const coordinator2 = new AutoIndexCoordinator(registration);
3799
4745
  coordinator2.activateAfter(activation);
@@ -3809,6 +4755,9 @@ function configureAutoIndex(projectRoot, host, config, getIndexer) {
3809
4755
  coordinator.update(registration);
3810
4756
  }
3811
4757
  coordinatorKeysByProject.set(projectKey, key);
4758
+ if (synchronizeWorker) {
4759
+ synchronizeBackgroundWorker(projectRoot, host, config, safety.safeToRun);
4760
+ }
3812
4761
  }
3813
4762
  function runCoordinatedIndex(projectRoot, host, force, onProgress) {
3814
4763
  return getCoordinator(projectRoot, host)?.request({
@@ -3843,15 +4792,23 @@ async function waitForAutoIndexForRetrieval(projectRoot, host) {
3843
4792
  };
3844
4793
  }
3845
4794
  try {
3846
- if (await hasReadableCurrentIndex(coordinator)) return { ready: true };
4795
+ const readiness = await getSearchReadiness(coordinator);
4796
+ if (readiness.searchable) {
4797
+ return { ready: true };
4798
+ }
4799
+ if (readiness.blocked) return unavailableSnapshotResult(readiness.reason);
3847
4800
  } catch {
3848
4801
  }
3849
- const job = coordinator.start("retrieval") ?? coordinator.currentJob();
4802
+ const job = startRetrievalRefresh(projectRoot, host, coordinator);
3850
4803
  if (job) {
3851
4804
  await withTimeout(job, coordinator.getWaitMs());
4805
+ } else if (isBackgroundWorkerManaged(projectRoot, host)) {
4806
+ await waitForPublishedSnapshot(coordinator, coordinator.getWaitMs());
3852
4807
  }
3853
4808
  try {
3854
- if (await hasReadableCurrentIndex(coordinator)) return { ready: true };
4809
+ const readiness = await getSearchReadiness(coordinator);
4810
+ if (readiness.searchable) return { ready: true };
4811
+ if (readiness.blocked) return unavailableSnapshotResult(readiness.reason);
3855
4812
  } catch {
3856
4813
  }
3857
4814
  const status = coordinator.snapshot();
@@ -3872,18 +4829,45 @@ async function waitForAutoIndexForRetrieval(projectRoot, host) {
3872
4829
  text: `Automatic indexing is ${status.state}. Retry shortly or call index_status for progress. You can also run index_codebase explicitly.`
3873
4830
  };
3874
4831
  }
3875
- async function hasReadableCurrentIndex(coordinator) {
4832
+ async function getSearchReadiness(coordinator) {
3876
4833
  const indexer = coordinator.getIndexer();
3877
4834
  if (indexer.getIndexFreshness) {
3878
4835
  const freshness = await indexer.getIndexFreshness();
3879
- return freshness.readable && freshness.current;
4836
+ const searchable = freshness.readable && freshness.current && freshness.reason === "current";
4837
+ return {
4838
+ blocked: freshness.reason === "unreadable" || freshness.reason === "incompatible" || freshness.reason === "failed-batches" || freshness.reason === "migration-required",
4839
+ reason: freshness.reason,
4840
+ searchable
4841
+ };
4842
+ }
4843
+ const indexed = (await indexer.getStatus()).indexed;
4844
+ return { blocked: false, searchable: indexed };
4845
+ }
4846
+ function unavailableSnapshotResult(reason) {
4847
+ 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.";
4848
+ return {
4849
+ ready: false,
4850
+ text: `${detail} Run index_codebase before retrying retrieval.`
4851
+ };
4852
+ }
4853
+ function startRetrievalRefresh(projectRoot, host, coordinator) {
4854
+ if (isBackgroundWorkerManaged(projectRoot, host)) {
4855
+ requestBackgroundWorkerRefresh(projectRoot, host, true);
4856
+ return isBackgroundWorkerLeader(projectRoot, host) ? coordinator.currentJob() : null;
4857
+ }
4858
+ return coordinator.start("retrieval") ?? coordinator.currentJob();
4859
+ }
4860
+ async function waitForPublishedSnapshot(coordinator, waitMs) {
4861
+ const deadline = Date.now() + waitMs;
4862
+ while (Date.now() < deadline) {
4863
+ if ((await getSearchReadiness(coordinator)).searchable) return;
4864
+ await new Promise((resolve20) => setTimeout(resolve20, Math.min(250, deadline - Date.now())));
3880
4865
  }
3881
- return (await indexer.getStatus()).indexed;
3882
4866
  }
3883
4867
 
3884
4868
  // src/tools/config-state.ts
3885
- import { existsSync as existsSync8, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
3886
- import * as path12 from "path";
4869
+ import { existsSync as existsSync9, mkdirSync as mkdirSync3, writeFileSync as writeFileSync3 } from "fs";
4870
+ import * as path13 from "path";
3887
4871
  function normalizeKnowledgeBasePaths(config, projectRoot) {
3888
4872
  const normalized = { ...config };
3889
4873
  if (Array.isArray(normalized.knowledgeBases)) {
@@ -3904,8 +4888,8 @@ function loadRuntimeConfig(projectRoot, host) {
3904
4888
  }
3905
4889
 
3906
4890
  // src/indexer/index.ts
3907
- import { existsSync as existsSync11, readFileSync as readFileSync8, statSync as statSync4, writeFileSync as writeFileSync3, renameSync as renameSync3, unlinkSync as unlinkSync2, mkdirSync as mkdirSync4, promises as fsPromises3 } from "fs";
3908
- import * as path19 from "path";
4891
+ import { existsSync as existsSync12, readFileSync as readFileSync9, statSync as statSync4, writeFileSync as writeFileSync4, renameSync as renameSync4, unlinkSync as unlinkSync2, mkdirSync as mkdirSync5, promises as fsPromises3 } from "fs";
4892
+ import * as path20 from "path";
3909
4893
  import { performance as performance2 } from "perf_hooks";
3910
4894
  import { execFile as execFile5 } from "child_process";
3911
4895
  import { promisify as promisify4 } from "util";
@@ -3932,7 +4916,7 @@ function pTimeout(promise, options) {
3932
4916
  } = options;
3933
4917
  let timer;
3934
4918
  let abortHandler;
3935
- const wrappedPromise = new Promise((resolve19, reject) => {
4919
+ const wrappedPromise = new Promise((resolve20, reject) => {
3936
4920
  if (typeof milliseconds !== "number" || Math.sign(milliseconds) !== 1) {
3937
4921
  throw new TypeError(`Expected \`milliseconds\` to be a positive number, got \`${milliseconds}\``);
3938
4922
  }
@@ -3946,7 +4930,7 @@ function pTimeout(promise, options) {
3946
4930
  };
3947
4931
  signal.addEventListener("abort", abortHandler, { once: true });
3948
4932
  }
3949
- promise.then(resolve19, reject);
4933
+ promise.then(resolve20, reject);
3950
4934
  if (milliseconds === Number.POSITIVE_INFINITY) {
3951
4935
  return;
3952
4936
  }
@@ -3954,7 +4938,7 @@ function pTimeout(promise, options) {
3954
4938
  timer = customTimers.setTimeout.call(void 0, () => {
3955
4939
  if (fallback) {
3956
4940
  try {
3957
- resolve19(fallback());
4941
+ resolve20(fallback());
3958
4942
  } catch (error) {
3959
4943
  reject(error);
3960
4944
  }
@@ -3964,7 +4948,7 @@ function pTimeout(promise, options) {
3964
4948
  promise.cancel();
3965
4949
  }
3966
4950
  if (message === false) {
3967
- resolve19();
4951
+ resolve20();
3968
4952
  } else if (message instanceof Error) {
3969
4953
  reject(message);
3970
4954
  } else {
@@ -4366,7 +5350,7 @@ var PQueue = class extends import_index.default {
4366
5350
  // Assign unique ID if not provided
4367
5351
  id: options.id ?? (this.#idAssigner++).toString()
4368
5352
  };
4369
- return new Promise((resolve19, reject) => {
5353
+ return new Promise((resolve20, reject) => {
4370
5354
  const taskSymbol = /* @__PURE__ */ Symbol(`task-${options.id}`);
4371
5355
  let cleanupQueueAbortHandler = () => void 0;
4372
5356
  const run = async () => {
@@ -4406,7 +5390,7 @@ var PQueue = class extends import_index.default {
4406
5390
  })]);
4407
5391
  }
4408
5392
  const result = await operation;
4409
- resolve19(result);
5393
+ resolve20(result);
4410
5394
  this.emit("completed", result);
4411
5395
  } catch (error) {
4412
5396
  reject(error);
@@ -4594,13 +5578,13 @@ var PQueue = class extends import_index.default {
4594
5578
  });
4595
5579
  }
4596
5580
  async #onEvent(event, filter) {
4597
- return new Promise((resolve19) => {
5581
+ return new Promise((resolve20) => {
4598
5582
  const listener = () => {
4599
5583
  if (filter && !filter()) {
4600
5584
  return;
4601
5585
  }
4602
5586
  this.off(event, listener);
4603
- resolve19();
5587
+ resolve20();
4604
5588
  };
4605
5589
  this.on(event, listener);
4606
5590
  });
@@ -4886,7 +5870,7 @@ async function onAttemptFailure({ error, attemptNumber, retriesConsumed, startTi
4886
5870
  const finalDelay = Math.min(delayTime, remainingTime);
4887
5871
  options.signal?.throwIfAborted();
4888
5872
  if (finalDelay > 0) {
4889
- await new Promise((resolve19, reject) => {
5873
+ await new Promise((resolve20, reject) => {
4890
5874
  const onAbort = () => {
4891
5875
  clearTimeout(timeoutToken);
4892
5876
  options.signal?.removeEventListener("abort", onAbort);
@@ -4894,7 +5878,7 @@ async function onAttemptFailure({ error, attemptNumber, retriesConsumed, startTi
4894
5878
  };
4895
5879
  const timeoutToken = setTimeout(() => {
4896
5880
  options.signal?.removeEventListener("abort", onAbort);
4897
- resolve19();
5881
+ resolve20();
4898
5882
  }, finalDelay);
4899
5883
  if (options.unref) {
4900
5884
  timeoutToken.unref?.();
@@ -4955,17 +5939,17 @@ async function pRetry(input, options = {}) {
4955
5939
  }
4956
5940
 
4957
5941
  // src/embeddings/detector.ts
4958
- import { existsSync as existsSync9, readFileSync as readFileSync6 } from "fs";
4959
- import * as path13 from "path";
4960
- import * as os4 from "os";
5942
+ import { existsSync as existsSync10, readFileSync as readFileSync7 } from "fs";
5943
+ import * as path14 from "path";
5944
+ import * as os5 from "os";
4961
5945
  function getOpenCodeAuthPath() {
4962
- return path13.join(os4.homedir(), ".local", "share", "opencode", "auth.json");
5946
+ return path14.join(os5.homedir(), ".local", "share", "opencode", "auth.json");
4963
5947
  }
4964
5948
  function loadOpenCodeAuth() {
4965
5949
  const authPath = getOpenCodeAuthPath();
4966
5950
  try {
4967
- if (existsSync9(authPath)) {
4968
- return JSON.parse(readFileSync6(authPath, "utf-8"));
5951
+ if (existsSync10(authPath)) {
5952
+ return JSON.parse(readFileSync7(authPath, "utf-8"));
4969
5953
  }
4970
5954
  } catch {
4971
5955
  }
@@ -5256,17 +6240,17 @@ function validateExternalUrl(urlString) {
5256
6240
  if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
5257
6241
  return { valid: false, reason: `Blocked protocol: ${parsed.protocol}` };
5258
6242
  }
5259
- const hostname2 = parsed.hostname.toLowerCase();
5260
- if (BLOCKED_HOSTNAMES.has(hostname2)) {
5261
- return { valid: false, reason: `Blocked: cloud metadata service (${hostname2})` };
6243
+ const hostname3 = parsed.hostname.toLowerCase();
6244
+ if (BLOCKED_HOSTNAMES.has(hostname3)) {
6245
+ return { valid: false, reason: `Blocked: cloud metadata service (${hostname3})` };
5262
6246
  }
5263
6247
  for (const pattern of BLOCKED_METADATA_IPS) {
5264
- if (pattern.test(hostname2)) {
5265
- return { valid: false, reason: `Blocked: cloud metadata IP (${hostname2})` };
6248
+ if (pattern.test(hostname3)) {
6249
+ return { valid: false, reason: `Blocked: cloud metadata IP (${hostname3})` };
5266
6250
  }
5267
6251
  }
5268
- if (/^169\.254\./.test(hostname2)) {
5269
- return { valid: false, reason: `Blocked: link-local address (${hostname2})` };
6252
+ if (/^169\.254\./.test(hostname3)) {
6253
+ return { valid: false, reason: `Blocked: link-local address (${hostname3})` };
5270
6254
  }
5271
6255
  return { valid: true };
5272
6256
  }
@@ -6358,8 +7342,8 @@ function extractParamNames(params) {
6358
7342
  }
6359
7343
 
6360
7344
  // src/native/binding.ts
6361
- import * as os5 from "os";
6362
- import * as path14 from "path";
7345
+ import * as os6 from "os";
7346
+ import * as path15 from "path";
6363
7347
  import * as module from "module";
6364
7348
  import { fileURLToPath } from "url";
6365
7349
 
@@ -6395,7 +7379,7 @@ var MCP_BINARY_CURRENT_NAME = CURRENT_PRODUCT.mcpBinary;
6395
7379
  var STABLE_NATIVE_BINARY_NAME = IDENTITY_CATALOG.native.binaryName;
6396
7380
 
6397
7381
  // src/native/binding.ts
6398
- function getNativeBindingFilename(platform2 = os5.platform(), arch2 = os5.arch()) {
7382
+ function getNativeBindingFilename(platform2 = os6.platform(), arch2 = os6.arch()) {
6399
7383
  if (platform2 === "darwin" && arch2 === "arm64") {
6400
7384
  return `${STABLE_NATIVE_BINARY_NAME}.darwin-arm64.node`;
6401
7385
  }
@@ -6413,25 +7397,25 @@ function getNativeBindingFilename(platform2 = os5.platform(), arch2 = os5.arch()
6413
7397
  }
6414
7398
  throw new Error(`Unsupported platform: ${platform2}-${arch2}`);
6415
7399
  }
6416
- function resolveNativeBindingPath(packageRoot, platform2 = os5.platform(), arch2 = os5.arch()) {
6417
- return path14.join(packageRoot, "native", getNativeBindingFilename(platform2, arch2));
7400
+ function resolveNativeBindingPath(packageRoot, platform2 = os6.platform(), arch2 = os6.arch()) {
7401
+ return path15.join(packageRoot, "native", getNativeBindingFilename(platform2, arch2));
6418
7402
  }
6419
7403
  function getNativeBinding() {
6420
7404
  let currentDir;
6421
7405
  let requireTarget;
6422
7406
  if (typeof import.meta !== "undefined" && import.meta.url) {
6423
- currentDir = path14.dirname(fileURLToPath(import.meta.url));
7407
+ currentDir = path15.dirname(fileURLToPath(import.meta.url));
6424
7408
  requireTarget = import.meta.url;
6425
7409
  } else if (typeof __dirname !== "undefined") {
6426
7410
  currentDir = __dirname;
6427
7411
  requireTarget = __filename;
6428
7412
  } else {
6429
7413
  currentDir = process.cwd();
6430
- requireTarget = path14.join(currentDir, "index.js");
7414
+ requireTarget = path15.join(currentDir, "index.js");
6431
7415
  }
6432
7416
  const normalizedDir = currentDir.replace(/\\/g, "/");
6433
- const isDevMode = normalizedDir.includes("/src/native") || currentDir.includes(path14.join("src", "native"));
6434
- const packageRoot = isDevMode ? path14.resolve(currentDir, "../..") : path14.resolve(currentDir, "..");
7417
+ const isDevMode = normalizedDir.includes("/src/native") || currentDir.includes(path15.join("src", "native"));
7418
+ const packageRoot = isDevMode ? path15.resolve(currentDir, "../..") : path15.resolve(currentDir, "..");
6435
7419
  const nativePath = resolveNativeBindingPath(packageRoot);
6436
7420
  const require2 = module.createRequire(requireTarget);
6437
7421
  return require2(nativePath);
@@ -7015,8 +7999,8 @@ var Database = class _Database {
7015
7999
 
7016
8000
  // src/git/branch-materialization.ts
7017
8001
  import { promises as fsPromises2 } from "fs";
7018
- import * as os6 from "os";
7019
- import * as path15 from "path";
8002
+ import * as os7 from "os";
8003
+ import * as path16 from "path";
7020
8004
 
7021
8005
  // src/git/branch-resolution.ts
7022
8006
  import { execFile as execFile2 } from "child_process";
@@ -7335,13 +8319,13 @@ async function isWorktreeRegistered(projectRoot, worktreePath) {
7335
8319
  return false;
7336
8320
  }
7337
8321
  function isPathWithinRoot(filePath, rootPath) {
7338
- const relative12 = path15.relative(path15.resolve(rootPath), path15.resolve(filePath));
7339
- return relative12 === "" || !relative12.startsWith(`..${path15.sep}`) && relative12 !== ".." && !path15.isAbsolute(relative12);
8322
+ const relative12 = path16.relative(path16.resolve(rootPath), path16.resolve(filePath));
8323
+ return relative12 === "" || !relative12.startsWith(`..${path16.sep}`) && relative12 !== ".." && !path16.isAbsolute(relative12);
7340
8324
  }
7341
8325
  async function pruneExactMissingWorktreeRegistration(projectRoot, worktreePath) {
7342
8326
  if (await pathExists(worktreePath)) return false;
7343
8327
  const commonDir = await runGit(projectRoot, ["rev-parse", "--path-format=absolute", "--git-common-dir"]);
7344
- const registrationsRoot = path15.join(commonDir, "worktrees");
8328
+ const registrationsRoot = path16.join(commonDir, "worktrees");
7345
8329
  let entries;
7346
8330
  try {
7347
8331
  entries = await fsPromises2.readdir(registrationsRoot, { withFileTypes: true });
@@ -7352,16 +8336,16 @@ async function pruneExactMissingWorktreeRegistration(projectRoot, worktreePath)
7352
8336
  const target = canonicalizePathForComparison(worktreePath);
7353
8337
  for (const entry of entries) {
7354
8338
  if (!entry.isDirectory()) continue;
7355
- const registrationPath = path15.join(registrationsRoot, entry.name);
8339
+ const registrationPath = path16.join(registrationsRoot, entry.name);
7356
8340
  if (!isPathWithinRoot(registrationPath, registrationsRoot)) continue;
7357
8341
  let gitdirPath;
7358
8342
  try {
7359
- gitdirPath = (await fsPromises2.readFile(path15.join(registrationPath, "gitdir"), "utf8")).trim();
8343
+ gitdirPath = (await fsPromises2.readFile(path16.join(registrationPath, "gitdir"), "utf8")).trim();
7360
8344
  } catch {
7361
8345
  continue;
7362
8346
  }
7363
- const resolvedGitdirPath = path15.isAbsolute(gitdirPath) ? gitdirPath : path15.resolve(registrationPath, gitdirPath);
7364
- if (canonicalizePathForComparison(path15.dirname(resolvedGitdirPath)) !== target) continue;
8347
+ const resolvedGitdirPath = path16.isAbsolute(gitdirPath) ? gitdirPath : path16.resolve(registrationPath, gitdirPath);
8348
+ if (canonicalizePathForComparison(path16.dirname(resolvedGitdirPath)) !== target) continue;
7365
8349
  await fsPromises2.rm(registrationPath, { recursive: true, force: true });
7366
8350
  return true;
7367
8351
  }
@@ -7379,7 +8363,7 @@ async function removeWorktree(projectRoot, worktreePath) {
7379
8363
  registered = await isWorktreeRegistered(projectRoot, worktreePath);
7380
8364
  } catch (error) {
7381
8365
  errors.push(asError(error));
7382
- throw new AggregateError(errors, `Could not verify temporary worktree deregistration; preserved ${path15.dirname(worktreePath)}`);
8366
+ throw new AggregateError(errors, `Could not verify temporary worktree deregistration; preserved ${path16.dirname(worktreePath)}`);
7383
8367
  }
7384
8368
  if (registered) {
7385
8369
  try {
@@ -7395,7 +8379,7 @@ async function removeWorktree(projectRoot, worktreePath) {
7395
8379
  registered = await isWorktreeRegistered(projectRoot, worktreePath);
7396
8380
  } catch (error) {
7397
8381
  errors.push(asError(error));
7398
- throw new AggregateError(errors, `Could not verify temporary worktree deregistration; preserved ${path15.dirname(worktreePath)}`);
8382
+ throw new AggregateError(errors, `Could not verify temporary worktree deregistration; preserved ${path16.dirname(worktreePath)}`);
7399
8383
  }
7400
8384
  }
7401
8385
  if (registered && !await pathExists(worktreePath)) {
@@ -7408,13 +8392,13 @@ async function removeWorktree(projectRoot, worktreePath) {
7408
8392
  }
7409
8393
  if (registered) {
7410
8394
  errors.push(new Error(`Temporary worktree remains registered: ${worktreePath}`));
7411
- throw new AggregateError(errors, `Failed to deregister temporary worktree; preserved ${path15.dirname(worktreePath)}`);
8395
+ throw new AggregateError(errors, `Failed to deregister temporary worktree; preserved ${path16.dirname(worktreePath)}`);
7412
8396
  }
7413
8397
  try {
7414
- await fsPromises2.rm(path15.dirname(worktreePath), { recursive: true, force: true });
8398
+ await fsPromises2.rm(path16.dirname(worktreePath), { recursive: true, force: true });
7415
8399
  } catch (error) {
7416
8400
  errors.push(asError(error));
7417
- throw new AggregateError(errors, `Deregistered the temporary worktree but could not remove ${path15.dirname(worktreePath)}`);
8401
+ throw new AggregateError(errors, `Deregistered the temporary worktree but could not remove ${path16.dirname(worktreePath)}`);
7418
8402
  }
7419
8403
  }
7420
8404
  async function cleanupTemporaryWorktree(projectRoot, worktreePath, temporaryRoot) {
@@ -7450,9 +8434,9 @@ async function withMaterializedBranch(request, callback) {
7450
8434
  `Git ref ${JSON.stringify(request.ref ?? request.branch)} is not available locally. For an unfetched branch, pass a remote-qualified name such as origin/feature.`
7451
8435
  );
7452
8436
  }
7453
- const temporaryRoot = await fsPromises2.mkdtemp(path15.join(os6.tmpdir(), "codebase-index-branch-"));
7454
- const worktreePath = path15.join(temporaryRoot, "worktree");
7455
- const hooksPath = path15.join(temporaryRoot, "hooks");
8437
+ const temporaryRoot = await fsPromises2.mkdtemp(path16.join(os7.tmpdir(), "codebase-index-branch-"));
8438
+ const worktreePath = path16.join(temporaryRoot, "worktree");
8439
+ const hooksPath = path16.join(temporaryRoot, "hooks");
7456
8440
  await fsPromises2.mkdir(hooksPath);
7457
8441
  const info = {
7458
8442
  branch: request.branch,
@@ -7503,8 +8487,8 @@ async function withMaterializedBranch(request, callback) {
7503
8487
 
7504
8488
  // src/tools/changed-files.ts
7505
8489
  import { execFile as execFile3 } from "child_process";
7506
- import { realpathSync as realpathSync4 } from "fs";
7507
- import * as path16 from "path";
8490
+ import { realpathSync as realpathSync5 } from "fs";
8491
+ import * as path17 from "path";
7508
8492
  import { promisify as promisify2 } from "util";
7509
8493
  var execFileAsync2 = promisify2(execFile3);
7510
8494
  var GH_PR_VIEW_FIELDS = [
@@ -7646,9 +8630,9 @@ function getHeadRepositoryIdentity(data, host) {
7646
8630
  return `${host}/${owner.toLowerCase()}/${repository.replace(/\.git$/i, "").toLowerCase()}`;
7647
8631
  }
7648
8632
  function getLocalRepositoryIdentity(projectRoot) {
7649
- let canonicalRoot = path16.resolve(projectRoot);
8633
+ let canonicalRoot = path17.resolve(projectRoot);
7650
8634
  try {
7651
- canonicalRoot = realpathSync4.native(canonicalRoot);
8635
+ canonicalRoot = realpathSync5.native(canonicalRoot);
7652
8636
  } catch {
7653
8637
  }
7654
8638
  return `local:${canonicalRoot}`;
@@ -7707,17 +8691,17 @@ async function getMergeBase(projectRoot, baseCommit, headCommit) {
7707
8691
  return commit;
7708
8692
  }
7709
8693
  function normalizeFiles(rawFiles, projectRoot) {
7710
- const root = path16.resolve(projectRoot);
8694
+ const root = path17.resolve(projectRoot);
7711
8695
  const seen = /* @__PURE__ */ new Set();
7712
8696
  const result = [];
7713
8697
  for (const raw of rawFiles) {
7714
8698
  if (raw.length === 0) continue;
7715
- const absolute = path16.resolve(root, raw);
7716
- const relative12 = path16.relative(root, absolute);
7717
- if (path16.isAbsolute(raw) || relative12 === ".." || relative12.startsWith(`..${path16.sep}`) || path16.isAbsolute(relative12)) {
8699
+ const absolute = path17.resolve(root, raw);
8700
+ const relative12 = path17.relative(root, absolute);
8701
+ if (path17.isAbsolute(raw) || relative12 === ".." || relative12.startsWith(`..${path17.sep}`) || path17.isAbsolute(relative12)) {
7718
8702
  throw new Error(`Changed file escapes the project root: ${JSON.stringify(raw)}`);
7719
8703
  }
7720
- const cleaned = relative12.startsWith(`.${path16.sep}`) ? relative12.slice(2) : relative12;
8704
+ const cleaned = relative12.startsWith(`.${path17.sep}`) ? relative12.slice(2) : relative12;
7721
8705
  if (!seen.has(cleaned)) {
7722
8706
  seen.add(cleaned);
7723
8707
  result.push(cleaned);
@@ -7728,7 +8712,7 @@ function normalizeFiles(rawFiles, projectRoot) {
7728
8712
 
7729
8713
  // src/indexer/git-blame.ts
7730
8714
  import { execFile as execFile4 } from "child_process";
7731
- import * as path17 from "path";
8715
+ import * as path18 from "path";
7732
8716
  import { promisify as promisify3 } from "util";
7733
8717
  var execFileAsync3 = promisify3(execFile4);
7734
8718
  function parseGitBlamePorcelain(output) {
@@ -7766,7 +8750,7 @@ function parseGitBlamePorcelain(output) {
7766
8750
  return Array.from(commits.values()).filter((commit) => commit.lines > 0).sort((a, b) => b.lines - a.lines || b.committedAt - a.committedAt)[0];
7767
8751
  }
7768
8752
  async function getChunkGitBlame(projectRoot, filePath, startLine, endLine) {
7769
- const relativePath = path17.relative(projectRoot, filePath);
8753
+ const relativePath = path18.relative(projectRoot, filePath);
7770
8754
  try {
7771
8755
  const { stdout } = await execFileAsync3(
7772
8756
  "git",
@@ -8345,8 +9329,8 @@ function pathSegmentsForAffinityMatch(filePath) {
8345
9329
  if (segments.length === 0) {
8346
9330
  return [];
8347
9331
  }
8348
- const basename6 = segments[segments.length - 1] ?? "";
8349
- const basenameWithoutExt = basename6.replace(/\.[^/.]+$/u, "");
9332
+ const basename7 = segments[segments.length - 1] ?? "";
9333
+ const basenameWithoutExt = basename7.replace(/\.[^/.]+$/u, "");
8350
9334
  const normalizedSegments = segments.map((segment) => segment.toLowerCase());
8351
9335
  return Array.from(/* @__PURE__ */ new Set([
8352
9336
  ...normalizedSegments,
@@ -8655,8 +9639,8 @@ function hasAllEmbeddingParts(parts, expectedPartCount) {
8655
9639
 
8656
9640
  // src/indexer/failed-state-persistence.ts
8657
9641
  import * as fs2 from "fs";
8658
- import { createHash, randomBytes as randomBytes3 } from "crypto";
8659
- import * as path18 from "path";
9642
+ import { createHash as createHash2, randomBytes as randomBytes3 } from "crypto";
9643
+ import * as path19 from "path";
8660
9644
  import { StringDecoder } from "string_decoder";
8661
9645
  var CURRENT_FAILED_BATCH_VERSION = 1;
8662
9646
  var DEFAULT_MALFORMED_LINE_ACTION = "skip";
@@ -8674,7 +9658,7 @@ function* readFailedBatchRecords(filePath, options = {}) {
8674
9658
  function createFailedBatchWriter(targetPath) {
8675
9659
  const temporaryPath = createTemporaryPath(targetPath);
8676
9660
  let finalized = false;
8677
- fs2.mkdirSync(path18.dirname(targetPath), { recursive: true });
9661
+ fs2.mkdirSync(path19.dirname(targetPath), { recursive: true });
8678
9662
  fs2.closeSync(fs2.openSync(temporaryPath, "w"));
8679
9663
  const write = (record) => {
8680
9664
  if (finalized) {
@@ -8693,7 +9677,7 @@ function createFailedBatchWriter(targetPath) {
8693
9677
  if (lines.length === 0) {
8694
9678
  return;
8695
9679
  }
8696
- fs2.mkdirSync(path18.dirname(targetPath), { recursive: true });
9680
+ fs2.mkdirSync(path19.dirname(targetPath), { recursive: true });
8697
9681
  fs2.appendFileSync(temporaryPath, `${lines.join("\n")}
8698
9682
  `, "utf-8");
8699
9683
  };
@@ -8701,7 +9685,7 @@ function createFailedBatchWriter(targetPath) {
8701
9685
  if (finalized) {
8702
9686
  return;
8703
9687
  }
8704
- fs2.mkdirSync(path18.dirname(targetPath), { recursive: true });
9688
+ fs2.mkdirSync(path19.dirname(targetPath), { recursive: true });
8705
9689
  fs2.renameSync(temporaryPath, targetPath);
8706
9690
  finalized = true;
8707
9691
  };
@@ -8847,10 +9831,10 @@ function stripLeadingBomAndWhitespace(value) {
8847
9831
  return result;
8848
9832
  }
8849
9833
  function createTemporaryPath(targetPath) {
8850
- const randomId = createHash("sha1").update(`${Date.now()}:${randomBytes3(8).toString("hex")}`).digest("hex");
8851
- const targetDir = path18.dirname(targetPath);
8852
- const baseName = path18.basename(targetPath);
8853
- return path18.join(targetDir, `.${baseName}.${randomId}.tmp`);
9834
+ const randomId = createHash2("sha1").update(`${Date.now()}:${randomBytes3(8).toString("hex")}`).digest("hex");
9835
+ const targetDir = path19.dirname(targetPath);
9836
+ const baseName = path19.basename(targetPath);
9837
+ return path19.join(targetDir, `.${baseName}.${randomId}.tmp`);
8854
9838
  }
8855
9839
  function handleMalformedLine(filePath, lineNumber, line, error, options) {
8856
9840
  const action = options.malformedLineAction ?? DEFAULT_MALFORMED_LINE_ACTION;
@@ -9096,9 +10080,9 @@ var SWIFT_PARSER_VERSION = "1";
9096
10080
  var METAL_PARSER_VERSION = "1";
9097
10081
  var SYMBOL_EXTRACTOR_VERSION = "1";
9098
10082
  function isPathWithinRoot2(filePath, rootPath) {
9099
- const normalizedFilePath = path19.resolve(filePath);
9100
- const normalizedRoot = path19.resolve(rootPath);
9101
- return normalizedFilePath === normalizedRoot || normalizedFilePath.startsWith(`${normalizedRoot}${path19.sep}`);
10083
+ const normalizedFilePath = path20.resolve(filePath);
10084
+ const normalizedRoot = path20.resolve(rootPath);
10085
+ return normalizedFilePath === normalizedRoot || normalizedFilePath.startsWith(`${normalizedRoot}${path20.sep}`);
9102
10086
  }
9103
10087
  function promoteIdentifierMatches(query, combined, semanticCandidates, keywordCandidates, database, branchChunkIds, prioritizeSourcePaths = classifyQueryIntentRaw(query) === "source") {
9104
10088
  if (combined.length === 0) {
@@ -9429,10 +10413,10 @@ function matchesHardSearchFilters(candidate, options, projectRoot) {
9429
10413
  }
9430
10414
  if (options?.directory) {
9431
10415
  const candidatePath = canonicalizePathForComparison(
9432
- path19.resolve(projectRoot, candidate.metadata.filePath.replace(/\\/g, path19.sep))
10416
+ path20.resolve(projectRoot, candidate.metadata.filePath.replace(/\\/g, path20.sep))
9433
10417
  );
9434
10418
  const directoryPath = canonicalizePathForComparison(
9435
- path19.resolve(projectRoot, options.directory.trim().replace(/\\/g, path19.sep))
10419
+ path20.resolve(projectRoot, options.directory.trim().replace(/\\/g, path20.sep))
9436
10420
  );
9437
10421
  if (!isPathWithinRoot2(candidatePath, directoryPath)) return false;
9438
10422
  }
@@ -9545,26 +10529,37 @@ var Indexer = class _Indexer {
9545
10529
  return this.indexPathOverride ?? resolveProjectIndexPath(this.projectRoot, this.config.scope, this.host);
9546
10530
  }
9547
10531
  toCanonicalFilePath(filePath) {
9548
- if (!path19.isAbsolute(filePath)) {
10532
+ if (!path20.isAbsolute(filePath)) {
9549
10533
  return this.resolveStoredFilePath(filePath, this.projectRoot);
9550
10534
  }
9551
- if (path19.resolve(this.materializedProjectRoot) === path19.resolve(this.projectRoot) || !isPathWithinRoot2(filePath, this.materializedProjectRoot)) {
10535
+ if (path20.resolve(this.materializedProjectRoot) === path20.resolve(this.projectRoot) || !isPathWithinRoot2(filePath, this.materializedProjectRoot)) {
9552
10536
  return filePath;
9553
10537
  }
9554
- return path19.resolve(this.projectRoot, path19.relative(this.materializedProjectRoot, filePath));
10538
+ return path20.resolve(this.projectRoot, path20.relative(this.materializedProjectRoot, filePath));
9555
10539
  }
9556
10540
  toStoredFilePath(filePath) {
9557
10541
  const canonicalFilePath = this.toCanonicalFilePath(filePath);
9558
10542
  if (this.config.scope !== "project" || !isPathWithinRoot2(canonicalFilePath, this.projectRoot)) {
9559
10543
  return canonicalFilePath;
9560
10544
  }
9561
- return path19.relative(this.projectRoot, canonicalFilePath).split(path19.sep).join("/");
10545
+ return path20.relative(this.projectRoot, canonicalFilePath).split(path20.sep).join("/");
10546
+ }
10547
+ isStoredPathExcluded(storedPath) {
10548
+ let matchPath = storedPath.split(path20.sep).join("/");
10549
+ if (path20.isAbsolute(storedPath)) {
10550
+ const relativePath = path20.relative(this.projectRoot, storedPath).split(path20.sep).join("/");
10551
+ if (relativePath.startsWith("..") || path20.isAbsolute(relativePath)) {
10552
+ return false;
10553
+ }
10554
+ matchPath = relativePath;
10555
+ }
10556
+ return isExcludedByPatterns(matchPath, this.config.exclude);
9562
10557
  }
9563
10558
  resolveStoredFilePath(filePath, rootPath = this.projectRoot) {
9564
- if (path19.isAbsolute(filePath)) {
10559
+ if (path20.isAbsolute(filePath)) {
9565
10560
  return filePath;
9566
10561
  }
9567
- const resolvedPath = path19.resolve(rootPath, ...filePath.split("/"));
10562
+ const resolvedPath = path20.resolve(rootPath, ...filePath.split("/"));
9568
10563
  if (!isPathWithinRoot2(resolvedPath, rootPath)) {
9569
10564
  throw new Error(`Stored project path escapes project root: ${JSON.stringify(filePath)}`);
9570
10565
  }
@@ -9588,7 +10583,7 @@ var Indexer = class _Indexer {
9588
10583
  }
9589
10584
  toMaterializedFilePath(filePath) {
9590
10585
  const storedFilePath = this.toStoredFilePath(filePath);
9591
- if (path19.isAbsolute(storedFilePath)) {
10586
+ if (path20.isAbsolute(storedFilePath)) {
9592
10587
  return storedFilePath;
9593
10588
  }
9594
10589
  return this.resolveStoredFilePath(storedFilePath, this.materializedProjectRoot);
@@ -9605,10 +10600,10 @@ var Indexer = class _Indexer {
9605
10600
  }
9606
10601
  getRuntimeArtifactPath(fileName) {
9607
10602
  const namespace = this.getRuntimeArtifactNamespace();
9608
- if (!namespace) return path19.join(this.indexPath, fileName);
9609
- const extension = path19.extname(fileName);
10603
+ if (!namespace) return path20.join(this.indexPath, fileName);
10604
+ const extension = path20.extname(fileName);
9610
10605
  const baseName = fileName.slice(0, fileName.length - extension.length);
9611
- return path19.join(this.indexPath, `${baseName}.${namespace}${extension}`);
10606
+ return path20.join(this.indexPath, `${baseName}.${namespace}${extension}`);
9612
10607
  }
9613
10608
  refreshRuntimeArtifactPaths() {
9614
10609
  this.fileHashCachePath = this.getRuntimeArtifactPath("file-hashes.json");
@@ -9621,14 +10616,14 @@ var Indexer = class _Indexer {
9621
10616
  getMaterializedKnowledgeBases() {
9622
10617
  const canonicalProjectRoot = this.getCanonicalPath(this.projectRoot);
9623
10618
  return this.config.knowledgeBases.map((knowledgeBase) => {
9624
- const configuredPath = path19.isAbsolute(knowledgeBase) ? knowledgeBase : path19.resolve(this.projectRoot, knowledgeBase);
10619
+ const configuredPath = path20.isAbsolute(knowledgeBase) ? knowledgeBase : path20.resolve(this.projectRoot, knowledgeBase);
9625
10620
  const canonicalPath = this.getCanonicalPath(configuredPath);
9626
10621
  if (!isPathWithinRoot2(canonicalPath, canonicalProjectRoot)) {
9627
10622
  return canonicalPath;
9628
10623
  }
9629
- return path19.resolve(
10624
+ return path20.resolve(
9630
10625
  this.materializedProjectRoot,
9631
- path19.relative(canonicalProjectRoot, canonicalPath)
10626
+ path20.relative(canonicalProjectRoot, canonicalPath)
9632
10627
  );
9633
10628
  });
9634
10629
  }
@@ -9636,7 +10631,7 @@ var Indexer = class _Indexer {
9636
10631
  try {
9637
10632
  return canonicalizePathForComparison(targetPath);
9638
10633
  } catch {
9639
- return path19.resolve(targetPath);
10634
+ return path20.resolve(targetPath);
9640
10635
  }
9641
10636
  }
9642
10637
  getProjectIdentityHash(projectRoot) {
@@ -9717,7 +10712,7 @@ var Indexer = class _Indexer {
9717
10712
  } catch (error) {
9718
10713
  releaseError = error;
9719
10714
  this.writerArtifactFingerprint = null;
9720
- if (!existsSync11(lease.lockPath) && this.activeIndexLease?.owner.token === lease.owner.token) {
10715
+ if (!existsSync12(lease.lockPath) && this.activeIndexLease?.owner.token === lease.owner.token) {
9721
10716
  this.activeIndexLease = null;
9722
10717
  }
9723
10718
  }
@@ -9735,12 +10730,12 @@ var Indexer = class _Indexer {
9735
10730
  return this.activeIndexLease;
9736
10731
  }
9737
10732
  loadFileHashCache() {
9738
- if (!existsSync11(this.fileHashCachePath)) {
10733
+ if (!existsSync12(this.fileHashCachePath)) {
9739
10734
  this.fileHashCache = /* @__PURE__ */ new Map();
9740
10735
  return;
9741
10736
  }
9742
10737
  try {
9743
- const data = readFileSync8(this.fileHashCachePath, "utf-8");
10738
+ const data = readFileSync9(this.fileHashCachePath, "utf-8");
9744
10739
  const parsed = JSON.parse(data);
9745
10740
  this.fileHashCache = new Map(Object.entries(parsed));
9746
10741
  } catch (error) {
@@ -9762,24 +10757,24 @@ var Indexer = class _Indexer {
9762
10757
  atomicWriteSync(targetPath, data) {
9763
10758
  const lease = this.requireActiveLease();
9764
10759
  const tempPath = createLeaseTemporaryPath(targetPath, lease.owner, "tmp");
9765
- mkdirSync4(path19.dirname(targetPath), { recursive: true });
10760
+ mkdirSync5(path20.dirname(targetPath), { recursive: true });
9766
10761
  try {
9767
- writeFileSync3(tempPath, data);
9768
- renameSync3(tempPath, targetPath);
10762
+ writeFileSync4(tempPath, data);
10763
+ renameSync4(tempPath, targetPath);
9769
10764
  } finally {
9770
10765
  removeLeaseTemporaryPath(tempPath);
9771
10766
  }
9772
10767
  }
9773
10768
  saveInvertedIndex(invertedIndex) {
9774
10769
  this.atomicWriteSync(
9775
- path19.join(this.indexPath, "inverted-index.json"),
10770
+ path20.join(this.indexPath, "inverted-index.json"),
9776
10771
  invertedIndex.serialize()
9777
10772
  );
9778
10773
  }
9779
10774
  getScopedRoots(projectRoot = this.projectRoot) {
9780
10775
  const roots = /* @__PURE__ */ new Set([this.getCanonicalPath(projectRoot)]);
9781
10776
  for (const kbRoot of this.config.knowledgeBases) {
9782
- roots.add(this.getCanonicalPath(path19.resolve(projectRoot, kbRoot)));
10777
+ roots.add(this.getCanonicalPath(path20.resolve(projectRoot, kbRoot)));
9783
10778
  }
9784
10779
  return Array.from(roots);
9785
10780
  }
@@ -10196,7 +11191,7 @@ var Indexer = class _Indexer {
10196
11191
  return configuredProviderInfo !== null && recovery.embeddingProvider === configuredProviderInfo.provider && recovery.embeddingModel === configuredProviderInfo.modelInfo.model && recovery.embeddingDimensions === configuredProviderInfo.modelInfo.dimensions && recovery.embeddingStrategyVersion === EMBEDDING_STRATEGY_VERSION;
10197
11192
  }
10198
11193
  hasUnknownLegacyForceIndexClear(owner) {
10199
- return owner.operation === "force-index" && owner.clearRecovery === void 0 && owner.recoveryProtocolVersion !== 1 && existsSync11(path19.join(this.indexPath, "force-index-phase"));
11194
+ return owner.operation === "force-index" && owner.clearRecovery === void 0 && owner.recoveryProtocolVersion !== 1 && existsSync12(path20.join(this.indexPath, "force-index-phase"));
10200
11195
  }
10201
11196
  async recoverFromInterruptedIndexingUnlocked(owners) {
10202
11197
  for (const owner of owners) {
@@ -10382,7 +11377,7 @@ var Indexer = class _Indexer {
10382
11377
  }
10383
11378
  }
10384
11379
  clearFailedBatchState() {
10385
- if (existsSync11(this.failedBatchesPath)) {
11380
+ if (existsSync12(this.failedBatchesPath)) {
10386
11381
  try {
10387
11382
  unlinkSync2(this.failedBatchesPath);
10388
11383
  } catch {
@@ -10584,7 +11579,7 @@ var Indexer = class _Indexer {
10584
11579
  await options.queue.onSizeLessThan(Math.max(1, options.providerRateLimits.concurrency));
10585
11580
  const task = options.queue.add(async () => {
10586
11581
  if (options.rateLimitState.backoffMs > 0) {
10587
- await new Promise((resolve19) => setTimeout(resolve19, options.rateLimitState.backoffMs));
11582
+ await new Promise((resolve20) => setTimeout(resolve20, options.rateLimitState.backoffMs));
10588
11583
  }
10589
11584
  try {
10590
11585
  const embeddingResult = await pRetry(
@@ -11003,12 +11998,12 @@ var Indexer = class _Indexer {
11003
11998
  }
11004
11999
  }
11005
12000
  captureReaderArtifactFingerprint() {
11006
- const storePath = path19.join(this.indexPath, "vectors");
12001
+ const storePath = path20.join(this.indexPath, "vectors");
11007
12002
  return {
11008
12003
  vectors: `${this.getReaderFileFingerprint(storePath)}|${this.getReaderFileFingerprint(`${storePath}.meta.json`)}`,
11009
- keyword: this.getReaderFileFingerprint(path19.join(this.indexPath, "inverted-index.json")),
11010
- database: this.getReaderFileFingerprint(path19.join(this.indexPath, "codebase.db")),
11011
- databaseIdentity: this.getReaderFileFingerprint(path19.join(this.indexPath, "codebase.db"), true)
12004
+ keyword: this.getReaderFileFingerprint(path20.join(this.indexPath, "inverted-index.json")),
12005
+ database: this.getReaderFileFingerprint(path20.join(this.indexPath, "codebase.db")),
12006
+ databaseIdentity: this.getReaderFileFingerprint(path20.join(this.indexPath, "codebase.db"), true)
11012
12007
  };
11013
12008
  }
11014
12009
  refreshReaderArtifacts() {
@@ -11033,13 +12028,13 @@ var Indexer = class _Indexer {
11033
12028
  issues.set(component, this.createReadIssue(component, message));
11034
12029
  this.readerArtifactRetryAfter.set(component, Date.now() + READER_ARTIFACT_RETRY_INTERVAL_MS);
11035
12030
  };
11036
- const storePath = path19.join(this.indexPath, "vectors");
12031
+ const storePath = path20.join(this.indexPath, "vectors");
11037
12032
  const vectorMetadataPath = `${storePath}.meta.json`;
11038
- const invertedIndexPath = path19.join(this.indexPath, "inverted-index.json");
11039
- const dbPath = path19.join(this.indexPath, "codebase.db");
12033
+ const invertedIndexPath = path20.join(this.indexPath, "inverted-index.json");
12034
+ const dbPath = path20.join(this.indexPath, "codebase.db");
11040
12035
  if (vectorsChanged || retryDue("vectors")) {
11041
- const vectorStoreExists = existsSync11(storePath);
11042
- const vectorMetadataExists = existsSync11(vectorMetadataPath);
12036
+ const vectorStoreExists = existsSync12(storePath);
12037
+ const vectorMetadataExists = existsSync12(vectorMetadataPath);
11043
12038
  if (vectorStoreExists && vectorMetadataExists) {
11044
12039
  try {
11045
12040
  const store = new VectorStore(storePath, this.configuredProviderInfo.modelInfo.dimensions);
@@ -11054,8 +12049,8 @@ var Indexer = class _Indexer {
11054
12049
  setIssue("vectors", this.getVectorReadIssueMessage());
11055
12050
  }
11056
12051
  }
11057
- if (keywordChanged || retryDue("keyword") || !existsSync11(invertedIndexPath) && (this.store?.count() ?? 0) > 0) {
11058
- if (existsSync11(invertedIndexPath)) {
12052
+ if (keywordChanged || retryDue("keyword") || !existsSync12(invertedIndexPath) && (this.store?.count() ?? 0) > 0) {
12053
+ if (existsSync12(invertedIndexPath)) {
11059
12054
  try {
11060
12055
  const invertedIndex = new InvertedIndex(invertedIndexPath);
11061
12056
  invertedIndex.load();
@@ -11070,7 +12065,7 @@ var Indexer = class _Indexer {
11070
12065
  }
11071
12066
  }
11072
12067
  if (databaseReplaced || databaseChanged && issues.has("database") || retryDue("database")) {
11073
- if (existsSync11(dbPath)) {
12068
+ if (existsSync12(dbPath)) {
11074
12069
  try {
11075
12070
  const database = Database.openReadOnly(dbPath);
11076
12071
  if (this.database) {
@@ -11152,11 +12147,11 @@ var Indexer = class _Indexer {
11152
12147
  });
11153
12148
  this.provider = createEmbeddingProvider(this.configuredProviderInfo);
11154
12149
  const dimensions = this.configuredProviderInfo.modelInfo.dimensions;
11155
- const storePath = path19.join(this.indexPath, "vectors");
12150
+ const storePath = path20.join(this.indexPath, "vectors");
11156
12151
  const vectorMetadataPath = `${storePath}.meta.json`;
11157
- const invertedIndexPath = path19.join(this.indexPath, "inverted-index.json");
11158
- const dbPath = path19.join(this.indexPath, "codebase.db");
11159
- let dbIsNew = !existsSync11(dbPath);
12152
+ const invertedIndexPath = path20.join(this.indexPath, "inverted-index.json");
12153
+ const dbPath = path20.join(this.indexPath, "codebase.db");
12154
+ let dbIsNew = !existsSync12(dbPath);
11160
12155
  const readerArtifactFingerprint = mode === "reader" ? this.captureReaderArtifactFingerprint() : null;
11161
12156
  if (mode === "writer") {
11162
12157
  await fsPromises3.mkdir(this.indexPath, { recursive: true });
@@ -11188,14 +12183,14 @@ var Indexer = class _Indexer {
11188
12183
  }
11189
12184
  }
11190
12185
  this.store = new VectorStore(storePath, dimensions);
11191
- if (existsSync11(storePath) || existsSync11(vectorMetadataPath)) {
12186
+ if (existsSync12(storePath) || existsSync12(vectorMetadataPath)) {
11192
12187
  this.store.load();
11193
12188
  }
11194
12189
  this.invertedIndex = new InvertedIndex(invertedIndexPath);
11195
12190
  try {
11196
12191
  this.invertedIndex.load();
11197
12192
  } catch {
11198
- if (existsSync11(invertedIndexPath)) {
12193
+ if (existsSync12(invertedIndexPath)) {
11199
12194
  await fsPromises3.unlink(invertedIndexPath);
11200
12195
  }
11201
12196
  this.invertedIndex = new InvertedIndex(invertedIndexPath);
@@ -11213,8 +12208,8 @@ var Indexer = class _Indexer {
11213
12208
  }
11214
12209
  } else {
11215
12210
  this.store = new VectorStore(storePath, dimensions);
11216
- const vectorStoreExists = existsSync11(storePath);
11217
- const vectorMetadataExists = existsSync11(vectorMetadataPath);
12211
+ const vectorStoreExists = existsSync12(storePath);
12212
+ const vectorMetadataExists = existsSync12(vectorMetadataPath);
11218
12213
  const vectorReadFailureMessage = this.getVectorReadIssueMessage();
11219
12214
  if (vectorStoreExists !== vectorMetadataExists) {
11220
12215
  this.recordReadIssue("vectors", vectorReadFailureMessage);
@@ -11227,7 +12222,7 @@ var Indexer = class _Indexer {
11227
12222
  }
11228
12223
  }
11229
12224
  this.invertedIndex = new InvertedIndex(invertedIndexPath);
11230
- if (existsSync11(invertedIndexPath)) {
12225
+ if (existsSync12(invertedIndexPath)) {
11231
12226
  try {
11232
12227
  this.invertedIndex.load();
11233
12228
  } catch (error) {
@@ -11241,7 +12236,7 @@ var Indexer = class _Indexer {
11241
12236
  } else if (this.store.count() > 0) {
11242
12237
  this.recordReadIssue("keyword", this.getKeywordReadIssueMessage());
11243
12238
  }
11244
- if (existsSync11(dbPath)) {
12239
+ if (existsSync12(dbPath)) {
11245
12240
  try {
11246
12241
  this.database = Database.openReadOnly(dbPath);
11247
12242
  } catch (error) {
@@ -11333,7 +12328,7 @@ var Indexer = class _Indexer {
11333
12328
  if (await this.tryResetCorruptedIndex("running automatic orphan garbage collection", error)) {
11334
12329
  return {
11335
12330
  resetCorruptedIndex: true,
11336
- warning: this.getCorruptedIndexWarning(path19.join(this.indexPath, "codebase.db"))
12331
+ warning: this.getCorruptedIndexWarning(path20.join(this.indexPath, "codebase.db"))
11337
12332
  };
11338
12333
  }
11339
12334
  throw error;
@@ -11348,7 +12343,7 @@ var Indexer = class _Indexer {
11348
12343
  return;
11349
12344
  }
11350
12345
  const retainedEntries = store.getAllMetadata().filter(({ key }) => !excludedSet.has(key));
11351
- const storeBasePath = path19.join(this.indexPath, "vectors");
12346
+ const storeBasePath = path20.join(this.indexPath, "vectors");
11352
12347
  const storeIndexPath = storeBasePath;
11353
12348
  const storeMetadataPath = `${storeBasePath}.meta.json`;
11354
12349
  const lease = this.requireActiveLease();
@@ -11358,19 +12353,19 @@ var Indexer = class _Indexer {
11358
12353
  let backedUpMetadata = false;
11359
12354
  let rebuiltCount = 0;
11360
12355
  let skippedCount = 0;
11361
- if (existsSync11(backupIndexPath)) {
12356
+ if (existsSync12(backupIndexPath)) {
11362
12357
  unlinkSync2(backupIndexPath);
11363
12358
  }
11364
- if (existsSync11(backupMetadataPath)) {
12359
+ if (existsSync12(backupMetadataPath)) {
11365
12360
  unlinkSync2(backupMetadataPath);
11366
12361
  }
11367
12362
  try {
11368
- if (existsSync11(storeIndexPath)) {
11369
- renameSync3(storeIndexPath, backupIndexPath);
12363
+ if (existsSync12(storeIndexPath)) {
12364
+ renameSync4(storeIndexPath, backupIndexPath);
11370
12365
  backedUpIndex = true;
11371
12366
  }
11372
- if (existsSync11(storeMetadataPath)) {
11373
- renameSync3(storeMetadataPath, backupMetadataPath);
12367
+ if (existsSync12(storeMetadataPath)) {
12368
+ renameSync4(storeMetadataPath, backupMetadataPath);
11374
12369
  backedUpMetadata = true;
11375
12370
  }
11376
12371
  store.clear();
@@ -11390,10 +12385,10 @@ var Indexer = class _Indexer {
11390
12385
  rebuiltCount += 1;
11391
12386
  }
11392
12387
  store.save();
11393
- if (backedUpIndex && existsSync11(backupIndexPath)) {
12388
+ if (backedUpIndex && existsSync12(backupIndexPath)) {
11394
12389
  unlinkSync2(backupIndexPath);
11395
12390
  }
11396
- if (backedUpMetadata && existsSync11(backupMetadataPath)) {
12391
+ if (backedUpMetadata && existsSync12(backupMetadataPath)) {
11397
12392
  unlinkSync2(backupMetadataPath);
11398
12393
  }
11399
12394
  this.logger.gc("info", "Rebuilt vector store to avoid native remove", {
@@ -11406,17 +12401,17 @@ var Indexer = class _Indexer {
11406
12401
  store.clear();
11407
12402
  } catch {
11408
12403
  }
11409
- if (existsSync11(storeIndexPath)) {
12404
+ if (existsSync12(storeIndexPath)) {
11410
12405
  unlinkSync2(storeIndexPath);
11411
12406
  }
11412
- if (existsSync11(storeMetadataPath)) {
12407
+ if (existsSync12(storeMetadataPath)) {
11413
12408
  unlinkSync2(storeMetadataPath);
11414
12409
  }
11415
- if (backedUpIndex && existsSync11(backupIndexPath)) {
11416
- renameSync3(backupIndexPath, storeIndexPath);
12410
+ if (backedUpIndex && existsSync12(backupIndexPath)) {
12411
+ renameSync4(backupIndexPath, storeIndexPath);
11417
12412
  }
11418
- if (backedUpMetadata && existsSync11(backupMetadataPath)) {
11419
- renameSync3(backupMetadataPath, storeMetadataPath);
12413
+ if (backedUpMetadata && existsSync12(backupMetadataPath)) {
12414
+ renameSync4(backupMetadataPath, storeMetadataPath);
11420
12415
  }
11421
12416
  if (backedUpIndex || backedUpMetadata) {
11422
12417
  store.load();
@@ -11431,11 +12426,11 @@ var Indexer = class _Indexer {
11431
12426
  return `Detected a corrupted local SQLite index at ${dbPath} and reset the local index. Run index_codebase to rebuild search data.`;
11432
12427
  }
11433
12428
  async removeProjectRuntimeStateArtifacts() {
11434
- if (!existsSync11(this.indexPath)) return;
12429
+ if (!existsSync12(this.indexPath)) return;
11435
12430
  const names = await fsPromises3.readdir(this.indexPath);
11436
12431
  const runtimeStatePattern = /^(?:file-hashes|failed-batches)(?:\.[a-f0-9]{16})?\.json$/;
11437
12432
  await Promise.all(
11438
- names.filter((name) => runtimeStatePattern.test(name)).map((name) => fsPromises3.rm(path19.join(this.indexPath, name), { force: true }))
12433
+ names.filter((name) => runtimeStatePattern.test(name)).map((name) => fsPromises3.rm(path20.join(this.indexPath, name), { force: true }))
11439
12434
  );
11440
12435
  }
11441
12436
  async resetLocalIndexArtifacts() {
@@ -11451,13 +12446,13 @@ var Indexer = class _Indexer {
11451
12446
  this.readerArtifactRetryAfter.clear();
11452
12447
  this.fileHashCache.clear();
11453
12448
  const resetPaths = [
11454
- path19.join(this.indexPath, "codebase.db"),
11455
- path19.join(this.indexPath, "codebase.db-shm"),
11456
- path19.join(this.indexPath, "codebase.db-wal"),
11457
- path19.join(this.indexPath, "vectors"),
11458
- path19.join(this.indexPath, "vectors.usearch"),
11459
- path19.join(this.indexPath, "vectors.meta.json"),
11460
- path19.join(this.indexPath, "inverted-index.json")
12449
+ path20.join(this.indexPath, "codebase.db"),
12450
+ path20.join(this.indexPath, "codebase.db-shm"),
12451
+ path20.join(this.indexPath, "codebase.db-wal"),
12452
+ path20.join(this.indexPath, "vectors"),
12453
+ path20.join(this.indexPath, "vectors.usearch"),
12454
+ path20.join(this.indexPath, "vectors.meta.json"),
12455
+ path20.join(this.indexPath, "inverted-index.json")
11461
12456
  ];
11462
12457
  await Promise.all(resetPaths.map((targetPath) => fsPromises3.rm(targetPath, { recursive: true, force: true })));
11463
12458
  await this.removeProjectRuntimeStateArtifacts();
@@ -11467,7 +12462,7 @@ var Indexer = class _Indexer {
11467
12462
  if (!isSqliteCorruptionError(error)) {
11468
12463
  return false;
11469
12464
  }
11470
- const dbPath = path19.join(this.indexPath, "codebase.db");
12465
+ const dbPath = path20.join(this.indexPath, "codebase.db");
11471
12466
  const warning = this.getCorruptedIndexWarning(dbPath);
11472
12467
  const errorMessage = getErrorMessage4(error);
11473
12468
  if (this.config.scope === "global") {
@@ -11854,10 +12849,10 @@ var Indexer = class _Indexer {
11854
12849
  const reparseCachedMetalFiles = database.getMetadata(metalParserMetadataKey) !== METAL_PARSER_VERSION;
11855
12850
  const symbolExtractorMetadataKey = this.getSymbolExtractorVersionMetadataKey();
11856
12851
  const refreshCachedSymbols = database.getMetadata(symbolExtractorMetadataKey) !== SYMBOL_EXTRACTOR_VERSION;
11857
- if (reparseCachedSwiftFiles && Array.from(this.fileHashCache.keys()).some((filePath) => path19.extname(filePath).toLowerCase() === ".swift")) {
12852
+ if (reparseCachedSwiftFiles && Array.from(this.fileHashCache.keys()).some((filePath) => path20.extname(filePath).toLowerCase() === ".swift")) {
11858
12853
  this.logger.info("Reindexing cached Swift files for parser support");
11859
12854
  }
11860
- if (reparseCachedMetalFiles && Array.from(this.fileHashCache.keys()).some((filePath) => path19.extname(filePath).toLowerCase() === ".metal")) {
12855
+ if (reparseCachedMetalFiles && Array.from(this.fileHashCache.keys()).some((filePath) => path20.extname(filePath).toLowerCase() === ".metal")) {
11861
12856
  this.logger.info("Reindexing cached Metal files for parser support");
11862
12857
  }
11863
12858
  const includePatterns = [...this.config.include, ...this.config.additionalInclude];
@@ -11901,8 +12896,8 @@ var Indexer = class _Indexer {
11901
12896
  const needsCallGraphRefresh = cachedHashMatches && needsCallGraphResolutionMigration && database.getChunksByFile(storedPath).some(
11902
12897
  (chunk) => chunk.language === "php" || chunk.language === "c" || chunk.language === "cpp"
11903
12898
  );
11904
- const requiresSwiftParserUpgrade = reparseCachedSwiftFiles && path19.extname(storedPath).toLowerCase() === ".swift";
11905
- const requiresMetalParserUpgrade = reparseCachedMetalFiles && path19.extname(storedPath).toLowerCase() === ".metal";
12899
+ const requiresSwiftParserUpgrade = reparseCachedSwiftFiles && path20.extname(storedPath).toLowerCase() === ".swift";
12900
+ const requiresMetalParserUpgrade = reparseCachedMetalFiles && path20.extname(storedPath).toLowerCase() === ".metal";
11906
12901
  const inMigrationScope = forceScopedReembed && scopedRoots !== null && this.isFileInCurrentScope(storedPath, scopedRoots);
11907
12902
  if (cachedHashMatches && !inMigrationScope && !needsCallGraphRefresh && !requiresSwiftParserUpgrade && !requiresMetalParserUpgrade && !refreshCachedSymbols) {
11908
12903
  unchangedFilePaths.add(storedPath);
@@ -11961,7 +12956,7 @@ var Indexer = class _Indexer {
11961
12956
  }
11962
12957
  }
11963
12958
  }
11964
- const shouldRetryFailedPath = (filePath) => filePath !== null && currentFileHashes.has(filePath) && unchangedFilePaths.has(filePath);
12959
+ const shouldRetryFailedPath = (filePath) => filePath !== null && !this.isStoredPathExcluded(filePath) && currentFileHashes.has(filePath) && unchangedFilePaths.has(filePath);
11965
12960
  const failedProcessing = this.prepareFailedBatchProcessing(scopedRoots, shouldRetryFailedPath);
11966
12961
  const maxChunkTokens = getSafeEmbeddingChunkTokenLimit(configuredProviderInfo);
11967
12962
  const providerRateLimits = this.getProviderRateLimits(configuredProviderInfo.provider);
@@ -12065,7 +13060,7 @@ var Indexer = class _Indexer {
12065
13060
  throw new Error(`Parsed file was not present in its source batch: ${parsed.path}`);
12066
13061
  }
12067
13062
  if (parsed.chunks.length === 0) {
12068
- stats.parseFailures.push(path19.isAbsolute(parsed.path) ? path19.relative(this.projectRoot, parsed.path) : parsed.path);
13063
+ stats.parseFailures.push(path20.isAbsolute(parsed.path) ? path20.relative(this.projectRoot, parsed.path) : parsed.path);
12069
13064
  }
12070
13065
  let chunksToProcess = parsed.chunks;
12071
13066
  if (this.config.indexing.fallbackToTextOnMaxChunks && chunksToProcess.length > this.config.indexing.maxChunksPerFile) {
@@ -12400,8 +13395,8 @@ var Indexer = class _Indexer {
12400
13395
  previousBranchSymbolIds,
12401
13396
  Array.from(allSymbolIds)
12402
13397
  );
12403
- const vectorPath = path19.join(this.indexPath, "vectors");
12404
- const shouldFingerprintLegacyPair = !store.hasFingerprint() && existsSync11(vectorPath) && existsSync11(`${vectorPath}.meta.json`);
13398
+ const vectorPath = path20.join(this.indexPath, "vectors");
13399
+ const shouldFingerprintLegacyPair = !store.hasFingerprint() && existsSync12(vectorPath) && existsSync12(`${vectorPath}.meta.json`);
12405
13400
  if (backfilledBlameMetadata || shouldFingerprintLegacyPair || removedStoredChunks) {
12406
13401
  store.save();
12407
13402
  }
@@ -13196,7 +14191,7 @@ var Indexer = class _Indexer {
13196
14191
  const missingChunkKeys = [];
13197
14192
  const chunkKeysByRemovedFile = /* @__PURE__ */ new Map();
13198
14193
  for (const [filePath, chunkKeys] of filePathsToChunkKeys) {
13199
- if (!existsSync11(this.toMaterializedFilePath(filePath))) {
14194
+ if (!existsSync12(this.toMaterializedFilePath(filePath))) {
13200
14195
  chunkKeysByRemovedFile.set(filePath, chunkKeys);
13201
14196
  for (const key of chunkKeys) {
13202
14197
  missingChunkKeys.push(key);
@@ -13259,7 +14254,7 @@ var Indexer = class _Indexer {
13259
14254
  gcOrphanSymbols: 0,
13260
14255
  gcOrphanCallEdges: 0,
13261
14256
  resetCorruptedIndex: true,
13262
- warning: this.getCorruptedIndexWarning(path19.join(this.indexPath, "codebase.db"))
14257
+ warning: this.getCorruptedIndexWarning(path20.join(this.indexPath, "codebase.db"))
13263
14258
  };
13264
14259
  }
13265
14260
  this.logger.recordGc(removedCount, gcOrphanChunks, gcOrphanEmbeddings);
@@ -13289,7 +14284,8 @@ var Indexer = class _Indexer {
13289
14284
  const maxChunkTokens = getSafeEmbeddingChunkTokenLimit(configuredProviderInfo);
13290
14285
  const providerRateLimits = this.getProviderRateLimits(configuredProviderInfo.provider);
13291
14286
  const roots = this.config.scope === "global" ? this.getScopedRoots() : null;
13292
- const failedProcessing = this.prepareFailedBatchProcessing(roots, () => true);
14287
+ const shouldProcessFailedPath = (filePath) => filePath === null || !this.isStoredPathExcluded(filePath);
14288
+ const failedProcessing = this.prepareFailedBatchProcessing(roots, shouldProcessFailedPath);
13293
14289
  if (failedProcessing.latestById.size === 0) {
13294
14290
  this.finalizeFailedBatchWriteState(failedProcessing.state);
13295
14291
  return { succeeded: 0, failed: 0, remaining: 0 };
@@ -13302,7 +14298,7 @@ var Indexer = class _Indexer {
13302
14298
  const retryableChunks = this.iterateLatestFailedChunks(
13303
14299
  failedProcessing.latestById,
13304
14300
  roots,
13305
- () => true,
14301
+ shouldProcessFailedPath,
13306
14302
  maxChunkTokens
13307
14303
  );
13308
14304
  for (const retryBatch of iterateOrderedFileBatches(
@@ -13572,9 +14568,9 @@ var Indexer = class _Indexer {
13572
14568
  this.requireReadableComponents(readIssues, "database");
13573
14569
  let shortest = [];
13574
14570
  for (const branchKey of this.getBranchCatalogKeys()) {
13575
- const path34 = database.findShortestPath(fromName, toName, branchKey, maxDepth);
13576
- if (path34.length > 0 && (shortest.length === 0 || path34.length < shortest.length)) {
13577
- shortest = path34;
14571
+ const path35 = database.findShortestPath(fromName, toName, branchKey, maxDepth);
14572
+ if (path35.length > 0 && (shortest.length === 0 || path35.length < shortest.length)) {
14573
+ shortest = path35;
13578
14574
  }
13579
14575
  }
13580
14576
  return shortest.map((hop) => this.resolveFilePathRecord(hop));
@@ -13622,13 +14618,13 @@ var Indexer = class _Indexer {
13622
14618
  }
13623
14619
  }
13624
14620
  if (!found) continue;
13625
- const path34 = [];
14621
+ const path35 = [];
13626
14622
  let currentSymbolId = toSymbolId;
13627
14623
  while (true) {
13628
14624
  const symbol = symbolsById.get(currentSymbolId);
13629
14625
  if (!symbol) break;
13630
14626
  const parent = parentBySymbolId.get(currentSymbolId);
13631
- path34.push({
14627
+ path35.push({
13632
14628
  symbolId: symbol.id,
13633
14629
  symbolName: symbol.name,
13634
14630
  filePath: symbol.filePath,
@@ -13638,9 +14634,9 @@ var Indexer = class _Indexer {
13638
14634
  if (!parent) break;
13639
14635
  currentSymbolId = parent.parentId;
13640
14636
  }
13641
- path34.reverse();
13642
- if (path34.length > 0 && (shortest.length === 0 || path34.length < shortest.length)) {
13643
- shortest = path34;
14637
+ path35.reverse();
14638
+ if (path35.length > 0 && (shortest.length === 0 || path35.length < shortest.length)) {
14639
+ shortest = path35;
13644
14640
  }
13645
14641
  }
13646
14642
  return shortest.map((hop) => this.resolveFilePathRecord(hop));
@@ -13791,7 +14787,7 @@ var Indexer = class _Indexer {
13791
14787
  );
13792
14788
  }
13793
14789
  }
13794
- const toStoredChangedFiles = (filePaths) => filePaths.map((filePath) => this.toStoredFilePath(path19.resolve(this.projectRoot, filePath)));
14790
+ const toStoredChangedFiles = (filePaths) => filePaths.map((filePath) => this.toStoredFilePath(path20.resolve(this.projectRoot, filePath)));
13795
14791
  const storedChangedFiles = toStoredChangedFiles(changedFiles);
13796
14792
  const directSymbols = database.getSymbolsForFiles(storedChangedFiles, branchKey);
13797
14793
  const directIds = directSymbols.map((s) => s.id);
@@ -13940,12 +14936,12 @@ var Indexer = class _Indexer {
13940
14936
  if (meta.filePath) filePaths.add(meta.filePath);
13941
14937
  }
13942
14938
  const directory = options?.directory?.replace(/\/$/, "");
13943
- const absoluteDirectoryFilter = directory ? path19.resolve(this.projectRoot, directory) : void 0;
14939
+ const absoluteDirectoryFilter = directory ? path20.resolve(this.projectRoot, directory) : void 0;
13944
14940
  for (const filePath of filePaths) {
13945
14941
  if (directory) {
13946
14942
  const absoluteFilePath = this.resolveStoredFilePath(filePath);
13947
14943
  const matchesRelative = filePath === directory || filePath.startsWith(directory + "/");
13948
- const matchesProjectRelative = absoluteDirectoryFilter !== void 0 && (absoluteFilePath === absoluteDirectoryFilter || absoluteFilePath.startsWith(absoluteDirectoryFilter + path19.sep));
14944
+ const matchesProjectRelative = absoluteDirectoryFilter !== void 0 && (absoluteFilePath === absoluteDirectoryFilter || absoluteFilePath.startsWith(absoluteDirectoryFilter + path20.sep));
13949
14945
  if (!matchesRelative && !matchesProjectRelative) {
13950
14946
  continue;
13951
14947
  }
@@ -14034,15 +15030,24 @@ function getOrCreateIndexer(projectRoot, host) {
14034
15030
  }
14035
15031
  const indexer = new Indexer(projectRoot, config, host);
14036
15032
  indexerCache.set(key, indexer);
14037
- configureAutoIndex(projectRoot, host, config, () => getOrCreateIndexer(projectRoot, host));
15033
+ configureAutoIndex(projectRoot, host, config, () => getOrCreateIndexer(projectRoot, host), {
15034
+ preserveManagedWorker: true,
15035
+ synchronizeBackgroundWorker: false
15036
+ });
14038
15037
  return indexer;
14039
15038
  }
14040
- function initializeTools(projectRoot, config, host) {
15039
+ function initializeTools(projectRoot, config, host, options = {}) {
14041
15040
  defaultProjectRoots.set(host, projectRoot);
14042
15041
  const key = getIndexerCacheKey(projectRoot, host);
15042
+ if (options.preserveManagedWorker === true && isBackgroundWorkerManaged(projectRoot, host) && indexerCache.has(key)) {
15043
+ return;
15044
+ }
14043
15045
  configCache.set(key, config);
14044
15046
  indexerCache.set(key, new Indexer(projectRoot, config, host));
14045
- configureAutoIndex(projectRoot, host, config, () => getOrCreateIndexer(projectRoot, host));
15047
+ configureAutoIndex(projectRoot, host, config, () => getOrCreateIndexer(projectRoot, host), {
15048
+ preserveManagedWorker: options.preserveManagedWorker,
15049
+ synchronizeBackgroundWorker: false
15050
+ });
14046
15051
  }
14047
15052
  function getIndexerForProject(projectRoot, host) {
14048
15053
  const root = getProjectRoot(projectRoot, host);
@@ -14072,7 +15077,7 @@ function trimOrUndefined(value) {
14072
15077
  return normalized || void 0;
14073
15078
  }
14074
15079
  function normalizeCallGraphPath(value) {
14075
- let normalized = path20.posix.normalize(value.trim().replaceAll("\\", "/"));
15080
+ let normalized = path21.posix.normalize(value.trim().replaceAll("\\", "/"));
14076
15081
  if (normalized.startsWith("./")) {
14077
15082
  normalized = normalized.slice(2);
14078
15083
  }
@@ -14287,39 +15292,39 @@ async function executeCallGraph(projectRoot, host, args) {
14287
15292
 
14288
15293
  // src/adapters/mcp/cli.ts
14289
15294
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
14290
- import { realpathSync as realpathSync6, writeFileSync as writeFileSync6 } from "fs";
14291
- import * as os8 from "os";
14292
- import * as path32 from "path";
15295
+ import { realpathSync as realpathSync7, writeFileSync as writeFileSync7 } from "fs";
15296
+ import * as os9 from "os";
15297
+ import * as path33 from "path";
14293
15298
  import { fileURLToPath as fileURLToPath2 } from "url";
14294
15299
 
14295
15300
  // src/eval/reports.ts
14296
- import { mkdirSync as mkdirSync5, readFileSync as readFileSync9, writeFileSync as writeFileSync4 } from "fs";
14297
- import * as path21 from "path";
15301
+ import { mkdirSync as mkdirSync6, readFileSync as readFileSync10, writeFileSync as writeFileSync5 } from "fs";
15302
+ import * as path22 from "path";
14298
15303
 
14299
15304
  // src/eval/runner.ts
14300
15305
  import * as crypto2 from "crypto";
14301
- import { existsSync as existsSync14 } from "fs";
14302
- import * as path23 from "path";
15306
+ import { existsSync as existsSync15 } from "fs";
15307
+ import * as path24 from "path";
14303
15308
 
14304
15309
  // src/eval/runner-config.ts
14305
- import { existsSync as existsSync13, mkdirSync as mkdirSync6, readFileSync as readFileSync10, rmSync as rmSync3, writeFileSync as writeFileSync5 } from "fs";
14306
- import * as os7 from "os";
14307
- import * as path22 from "path";
15310
+ import { existsSync as existsSync14, mkdirSync as mkdirSync7, readFileSync as readFileSync11, rmSync as rmSync4, writeFileSync as writeFileSync6 } from "fs";
15311
+ import * as os8 from "os";
15312
+ import * as path23 from "path";
14308
15313
 
14309
15314
  // src/eval/schema.ts
14310
- import { readFileSync as readFileSync11 } from "fs";
15315
+ import { readFileSync as readFileSync12 } from "fs";
14311
15316
 
14312
15317
  // src/eval/cli.ts
14313
- import * as path25 from "path";
15318
+ import * as path26 from "path";
14314
15319
 
14315
15320
  // src/eval/cli-parser.ts
14316
- import * as path24 from "path";
15321
+ import * as path25 from "path";
14317
15322
 
14318
15323
  // src/adapters/mcp/server.ts
14319
15324
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
14320
15325
 
14321
15326
  // src/package-metadata.ts
14322
- import { readFileSync as readFileSync12 } from "fs";
15327
+ import { readFileSync as readFileSync13 } from "fs";
14323
15328
 
14324
15329
  // src/adapters/mcp/register-prompts.ts
14325
15330
  import { z } from "zod";
@@ -14418,26 +15423,26 @@ var MCP_TOOL_NAMES = [
14418
15423
  ];
14419
15424
 
14420
15425
  // src/watcher/file-watcher.ts
14421
- import { existsSync as existsSync15, statSync as statSync6 } from "fs";
14422
- import * as path28 from "path";
15426
+ import { existsSync as existsSync16, statSync as statSync6 } from "fs";
15427
+ import * as path29 from "path";
14423
15428
 
14424
15429
  // src/watcher/native-recursive-watcher.ts
14425
15430
  import { watch } from "fs";
14426
- import * as path26 from "path";
15431
+ import * as path27 from "path";
14427
15432
 
14428
15433
  // src/watcher/snapshot.ts
14429
15434
  import * as fsPromises4 from "fs/promises";
14430
- import * as path27 from "path";
15435
+ import * as path28 from "path";
14431
15436
 
14432
15437
  // src/watcher/git-head-watcher.ts
14433
- import * as path29 from "path";
15438
+ import * as path30 from "path";
14434
15439
 
14435
15440
  // src/tools/visualize/activity.ts
14436
15441
  import { execFileSync } from "child_process";
14437
- import * as path30 from "path";
15442
+ import * as path31 from "path";
14438
15443
 
14439
15444
  // src/tools/visualize/transform.ts
14440
- import * as path31 from "path";
15445
+ import * as path32 from "path";
14441
15446
 
14442
15447
  // src/adapters/mcp/cli.ts
14443
15448
  function parseIndexArgs(argv, cwd) {
@@ -14459,7 +15464,7 @@ function parseIndexArgs(argv, cwd) {
14459
15464
  if (!arg.startsWith("--project=")) {
14460
15465
  i += 1;
14461
15466
  }
14462
- project = path32.resolve(cwd, value);
15467
+ project = path33.resolve(cwd, value);
14463
15468
  continue;
14464
15469
  }
14465
15470
  if (arg === "--config" || arg.startsWith("--config=")) {
@@ -14470,7 +15475,7 @@ function parseIndexArgs(argv, cwd) {
14470
15475
  if (!arg.startsWith("--config=")) {
14471
15476
  i += 1;
14472
15477
  }
14473
- config = path32.resolve(cwd, value);
15478
+ config = path33.resolve(cwd, value);
14474
15479
  continue;
14475
15480
  }
14476
15481
  if (arg === "--host" || arg.startsWith("--host=")) {
@@ -14634,7 +15639,7 @@ function parseCbiCommandArgs(command, args, cwd) {
14634
15639
  if (arg === "--help" || arg === "-h") throw new Error("help-requested");
14635
15640
  if (arg === "--project" || arg.startsWith("--project=")) {
14636
15641
  const parsed = optionValue(args, index, "project");
14637
- project = path33.resolve(cwd, parsed.value);
15642
+ project = path34.resolve(cwd, parsed.value);
14638
15643
  index += parsed.consumed;
14639
15644
  continue;
14640
15645
  }
@@ -14646,7 +15651,7 @@ function parseCbiCommandArgs(command, args, cwd) {
14646
15651
  }
14647
15652
  if (arg === "--config" || arg.startsWith("--config=")) {
14648
15653
  const parsed = optionValue(args, index, "config");
14649
- config = path33.resolve(cwd, parsed.value);
15654
+ config = path34.resolve(cwd, parsed.value);
14650
15655
  index += parsed.consumed;
14651
15656
  continue;
14652
15657
  }
@@ -14659,7 +15664,7 @@ function parseCbiCommandArgs(command, args, cwd) {
14659
15664
  }
14660
15665
  if (command === "graph" && (arg === "--file" || arg.startsWith("--file="))) {
14661
15666
  const parsed = optionValue(args, index, "file");
14662
- filePath = path33.resolve(cwd, parsed.value);
15667
+ filePath = path34.resolve(cwd, parsed.value);
14663
15668
  index += parsed.consumed;
14664
15669
  continue;
14665
15670
  }
@@ -14758,7 +15763,7 @@ async function runCbiCli(argv, cwd, deps = {}) {
14758
15763
  }
14759
15764
  }
14760
15765
  function isCbiEntrypoint(moduleUrl, argvPath) {
14761
- return argvPath !== void 0 && realpathSync7(fileURLToPath3(moduleUrl)) === realpathSync7(argvPath);
15766
+ return argvPath !== void 0 && realpathSync8(fileURLToPath3(moduleUrl)) === realpathSync8(argvPath);
14762
15767
  }
14763
15768
 
14764
15769
  // src/cbi.ts