opencode-codebase-index 0.1.8 → 0.1.11

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/index.cjs CHANGED
@@ -491,7 +491,7 @@ var require_ignore = __commonJS({
491
491
  // path matching.
492
492
  // - check `string` either `MODE_IGNORE` or `MODE_CHECK_IGNORE`
493
493
  // @returns {TestResult} true if a file is ignored
494
- test(path9, checkUnignored, mode) {
494
+ test(path7, checkUnignored, mode) {
495
495
  let ignored = false;
496
496
  let unignored = false;
497
497
  let matchedRule;
@@ -500,7 +500,7 @@ var require_ignore = __commonJS({
500
500
  if (unignored === negative && ignored !== unignored || negative && !ignored && !unignored && !checkUnignored) {
501
501
  return;
502
502
  }
503
- const matched = rule[mode].test(path9);
503
+ const matched = rule[mode].test(path7);
504
504
  if (!matched) {
505
505
  return;
506
506
  }
@@ -521,17 +521,17 @@ var require_ignore = __commonJS({
521
521
  var throwError = (message, Ctor) => {
522
522
  throw new Ctor(message);
523
523
  };
524
- var checkPath = (path9, originalPath, doThrow) => {
525
- if (!isString(path9)) {
524
+ var checkPath = (path7, originalPath, doThrow) => {
525
+ if (!isString(path7)) {
526
526
  return doThrow(
527
527
  `path must be a string, but got \`${originalPath}\``,
528
528
  TypeError
529
529
  );
530
530
  }
531
- if (!path9) {
531
+ if (!path7) {
532
532
  return doThrow(`path must not be empty`, TypeError);
533
533
  }
534
- if (checkPath.isNotRelative(path9)) {
534
+ if (checkPath.isNotRelative(path7)) {
535
535
  const r = "`path.relative()`d";
536
536
  return doThrow(
537
537
  `path should be a ${r} string, but got "${originalPath}"`,
@@ -540,7 +540,7 @@ var require_ignore = __commonJS({
540
540
  }
541
541
  return true;
542
542
  };
543
- var isNotRelative = (path9) => REGEX_TEST_INVALID_PATH.test(path9);
543
+ var isNotRelative = (path7) => REGEX_TEST_INVALID_PATH.test(path7);
544
544
  checkPath.isNotRelative = isNotRelative;
545
545
  checkPath.convert = (p) => p;
546
546
  var Ignore2 = class {
@@ -570,19 +570,19 @@ var require_ignore = __commonJS({
570
570
  }
571
571
  // @returns {TestResult}
572
572
  _test(originalPath, cache, checkUnignored, slices) {
573
- const path9 = originalPath && checkPath.convert(originalPath);
573
+ const path7 = originalPath && checkPath.convert(originalPath);
574
574
  checkPath(
575
- path9,
575
+ path7,
576
576
  originalPath,
577
577
  this._strictPathCheck ? throwError : RETURN_FALSE
578
578
  );
579
- return this._t(path9, cache, checkUnignored, slices);
579
+ return this._t(path7, cache, checkUnignored, slices);
580
580
  }
581
- checkIgnore(path9) {
582
- if (!REGEX_TEST_TRAILING_SLASH.test(path9)) {
583
- return this.test(path9);
581
+ checkIgnore(path7) {
582
+ if (!REGEX_TEST_TRAILING_SLASH.test(path7)) {
583
+ return this.test(path7);
584
584
  }
585
- const slices = path9.split(SLASH2).filter(Boolean);
585
+ const slices = path7.split(SLASH2).filter(Boolean);
586
586
  slices.pop();
587
587
  if (slices.length) {
588
588
  const parent = this._t(
@@ -595,18 +595,18 @@ var require_ignore = __commonJS({
595
595
  return parent;
596
596
  }
597
597
  }
598
- return this._rules.test(path9, false, MODE_CHECK_IGNORE);
598
+ return this._rules.test(path7, false, MODE_CHECK_IGNORE);
599
599
  }
600
- _t(path9, cache, checkUnignored, slices) {
601
- if (path9 in cache) {
602
- return cache[path9];
600
+ _t(path7, cache, checkUnignored, slices) {
601
+ if (path7 in cache) {
602
+ return cache[path7];
603
603
  }
604
604
  if (!slices) {
605
- slices = path9.split(SLASH2).filter(Boolean);
605
+ slices = path7.split(SLASH2).filter(Boolean);
606
606
  }
607
607
  slices.pop();
608
608
  if (!slices.length) {
609
- return cache[path9] = this._rules.test(path9, checkUnignored, MODE_IGNORE);
609
+ return cache[path7] = this._rules.test(path7, checkUnignored, MODE_IGNORE);
610
610
  }
611
611
  const parent = this._t(
612
612
  slices.join(SLASH2) + SLASH2,
@@ -614,29 +614,29 @@ var require_ignore = __commonJS({
614
614
  checkUnignored,
615
615
  slices
616
616
  );
617
- return cache[path9] = parent.ignored ? parent : this._rules.test(path9, checkUnignored, MODE_IGNORE);
617
+ return cache[path7] = parent.ignored ? parent : this._rules.test(path7, checkUnignored, MODE_IGNORE);
618
618
  }
619
- ignores(path9) {
620
- return this._test(path9, this._ignoreCache, false).ignored;
619
+ ignores(path7) {
620
+ return this._test(path7, this._ignoreCache, false).ignored;
621
621
  }
622
622
  createFilter() {
623
- return (path9) => !this.ignores(path9);
623
+ return (path7) => !this.ignores(path7);
624
624
  }
625
625
  filter(paths) {
626
626
  return makeArray(paths).filter(this.createFilter());
627
627
  }
628
628
  // @returns {TestResult}
629
- test(path9) {
630
- return this._test(path9, this._testCache, true);
629
+ test(path7) {
630
+ return this._test(path7, this._testCache, true);
631
631
  }
632
632
  };
633
633
  var factory = (options) => new Ignore2(options);
634
- var isPathValid = (path9) => checkPath(path9 && checkPath.convert(path9), path9, RETURN_FALSE);
634
+ var isPathValid = (path7) => checkPath(path7 && checkPath.convert(path7), path7, RETURN_FALSE);
635
635
  var setupWindows = () => {
636
636
  const makePosix = (str) => /^\\\\\?\\/.test(str) || /["<>|\u0000-\u001F]+/u.test(str) ? str : str.replace(/\\/g, "/");
637
637
  checkPath.convert = makePosix;
638
638
  const REGEX_TEST_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i;
639
- checkPath.isNotRelative = (path9) => REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path9) || isNotRelative(path9);
639
+ checkPath.isNotRelative = (path7) => REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path7) || isNotRelative(path7);
640
640
  };
641
641
  if (
642
642
  // Detect `process` so that it can run in browsers.
@@ -657,8 +657,8 @@ __export(index_exports, {
657
657
  default: () => index_default
658
658
  });
659
659
  module.exports = __toCommonJS(index_exports);
660
- var import_fs6 = require("fs");
661
- var path8 = __toESM(require("path"), 1);
660
+ var import_fs4 = require("fs");
661
+ var path6 = __toESM(require("path"), 1);
662
662
 
663
663
  // src/config/schema.ts
664
664
  var DEFAULT_INCLUDE = [
@@ -693,6 +693,8 @@ function getDefaultIndexingConfig() {
693
693
  autoIndex: false,
694
694
  watchFiles: true,
695
695
  maxFileSize: 1048576,
696
+ maxChunksPerFile: 100,
697
+ semanticOnly: false,
696
698
  retries: 3,
697
699
  retryDelayMs: 1e3
698
700
  };
@@ -726,6 +728,8 @@ function parseConfig(raw) {
726
728
  autoIndex: typeof rawIndexing.autoIndex === "boolean" ? rawIndexing.autoIndex : defaultIndexing.autoIndex,
727
729
  watchFiles: typeof rawIndexing.watchFiles === "boolean" ? rawIndexing.watchFiles : defaultIndexing.watchFiles,
728
730
  maxFileSize: typeof rawIndexing.maxFileSize === "number" ? rawIndexing.maxFileSize : defaultIndexing.maxFileSize,
731
+ maxChunksPerFile: typeof rawIndexing.maxChunksPerFile === "number" ? Math.max(1, rawIndexing.maxChunksPerFile) : defaultIndexing.maxChunksPerFile,
732
+ semanticOnly: typeof rawIndexing.semanticOnly === "boolean" ? rawIndexing.semanticOnly : defaultIndexing.semanticOnly,
729
733
  retries: typeof rawIndexing.retries === "number" ? rawIndexing.retries : defaultIndexing.retries,
730
734
  retryDelayMs: typeof rawIndexing.retryDelayMs === "number" ? rawIndexing.retryDelayMs : defaultIndexing.retryDelayMs
731
735
  };
@@ -807,8 +811,8 @@ function getDefaultModelForProvider(provider) {
807
811
  }
808
812
 
809
813
  // src/indexer/index.ts
810
- var import_fs5 = require("fs");
811
- var path6 = __toESM(require("path"), 1);
814
+ var import_fs3 = require("fs");
815
+ var path4 = __toESM(require("path"), 1);
812
816
 
813
817
  // node_modules/eventemitter3/index.mjs
814
818
  var import_index = __toESM(require_eventemitter3(), 1);
@@ -1879,7 +1883,7 @@ function getGitHubCopilotCredentials() {
1879
1883
  if (!copilotAuth || copilotAuth.type !== "oauth") {
1880
1884
  return null;
1881
1885
  }
1882
- const baseUrl = copilotAuth.enterpriseUrl ? `https://copilot-api.${copilotAuth.enterpriseUrl.replace(/^https?:\/\//, "").replace(/\/$/, "")}` : "https://api.githubcopilot.com";
1886
+ const baseUrl = copilotAuth.enterpriseUrl ? `https://copilot-api.${copilotAuth.enterpriseUrl.replace(/^https?:\/\//, "").replace(/\/$/, "")}` : "https://models.github.ai";
1883
1887
  return {
1884
1888
  provider: "github-copilot",
1885
1889
  baseUrl,
@@ -1954,9 +1958,6 @@ function getProviderDisplayName(provider) {
1954
1958
  }
1955
1959
 
1956
1960
  // src/embeddings/provider.ts
1957
- var import_fs2 = require("fs");
1958
- var path2 = __toESM(require("path"), 1);
1959
- var os2 = __toESM(require("os"), 1);
1960
1961
  function createEmbeddingProvider(credentials, modelInfo) {
1961
1962
  switch (credentials.provider) {
1962
1963
  case "github-copilot":
@@ -1971,56 +1972,16 @@ function createEmbeddingProvider(credentials, modelInfo) {
1971
1972
  throw new Error(`Unsupported embedding provider: ${credentials.provider}`);
1972
1973
  }
1973
1974
  }
1974
- var COPILOT_HEADERS = {
1975
- "User-Agent": "GitHubCopilotChat/0.35.0",
1976
- "Editor-Version": "vscode/1.107.0",
1977
- "Editor-Plugin-Version": "copilot-chat/0.35.0",
1978
- "Copilot-Integration-Id": "vscode-chat",
1979
- "Openai-Intent": "conversation-edits"
1980
- };
1981
1975
  var GitHubCopilotEmbeddingProvider = class {
1982
1976
  constructor(credentials, modelInfo) {
1983
1977
  this.credentials = credentials;
1984
1978
  this.modelInfo = modelInfo;
1985
- this.accessToken = credentials.accessToken || "";
1986
- this.tokenExpires = credentials.tokenExpires || 0;
1987
1979
  }
1988
- accessToken;
1989
- tokenExpires;
1990
- async ensureValidToken() {
1991
- if (this.accessToken && this.tokenExpires > Date.now()) {
1992
- return this.accessToken;
1993
- }
1980
+ getToken() {
1994
1981
  if (!this.credentials.refreshToken) {
1995
- throw new Error("No refresh token available for GitHub Copilot");
1996
- }
1997
- const response = await fetch("https://api.github.com/copilot_internal/v2/token", {
1998
- headers: {
1999
- Accept: "application/json",
2000
- Authorization: `Bearer ${this.credentials.refreshToken}`,
2001
- ...COPILOT_HEADERS
2002
- }
2003
- });
2004
- if (!response.ok) {
2005
- throw new Error(`Token refresh failed: ${response.status}`);
2006
- }
2007
- const tokenData = await response.json();
2008
- this.accessToken = tokenData.token;
2009
- this.tokenExpires = tokenData.expires_at * 1e3 - 5 * 60 * 1e3;
2010
- this.persistToken(tokenData.token, this.tokenExpires);
2011
- return this.accessToken;
2012
- }
2013
- persistToken(token, expires) {
2014
- try {
2015
- const authPath = path2.join(os2.homedir(), ".local", "share", "opencode", "auth.json");
2016
- const authData = JSON.parse((0, import_fs2.readFileSync)(authPath, "utf-8"));
2017
- if (authData["github-copilot"]) {
2018
- authData["github-copilot"].access = token;
2019
- authData["github-copilot"].expires = expires;
2020
- (0, import_fs2.writeFileSync)(authPath, JSON.stringify(authData, null, 2));
2021
- }
2022
- } catch {
1982
+ throw new Error("No OAuth token available for GitHub");
2023
1983
  }
1984
+ return this.credentials.refreshToken;
2024
1985
  }
2025
1986
  async embed(text) {
2026
1987
  const result = await this.embedBatch([text]);
@@ -2030,16 +1991,17 @@ var GitHubCopilotEmbeddingProvider = class {
2030
1991
  };
2031
1992
  }
2032
1993
  async embedBatch(texts) {
2033
- const token = await this.ensureValidToken();
2034
- const response = await fetch(`${this.credentials.baseUrl}/embeddings`, {
1994
+ const token = this.getToken();
1995
+ const response = await fetch(`${this.credentials.baseUrl}/inference/embeddings`, {
2035
1996
  method: "POST",
2036
1997
  headers: {
2037
1998
  Authorization: `Bearer ${token}`,
2038
1999
  "Content-Type": "application/json",
2039
- ...COPILOT_HEADERS
2000
+ Accept: "application/vnd.github+json",
2001
+ "X-GitHub-Api-Version": "2022-11-28"
2040
2002
  },
2041
2003
  body: JSON.stringify({
2042
- model: this.modelInfo.model,
2004
+ model: `openai/${this.modelInfo.model}`,
2043
2005
  input: texts
2044
2006
  })
2045
2007
  });
@@ -2188,8 +2150,8 @@ var OllamaEmbeddingProvider = class {
2188
2150
 
2189
2151
  // src/utils/files.ts
2190
2152
  var import_ignore = __toESM(require_ignore(), 1);
2191
- var import_fs3 = require("fs");
2192
- var path3 = __toESM(require("path"), 1);
2153
+ var import_fs2 = require("fs");
2154
+ var path2 = __toESM(require("path"), 1);
2193
2155
  function createIgnoreFilter(projectRoot) {
2194
2156
  const ig = (0, import_ignore.default)();
2195
2157
  const defaultIgnores = [
@@ -2206,15 +2168,15 @@ function createIgnoreFilter(projectRoot) {
2206
2168
  ".opencode"
2207
2169
  ];
2208
2170
  ig.add(defaultIgnores);
2209
- const gitignorePath = path3.join(projectRoot, ".gitignore");
2210
- if ((0, import_fs3.existsSync)(gitignorePath)) {
2211
- const gitignoreContent = (0, import_fs3.readFileSync)(gitignorePath, "utf-8");
2171
+ const gitignorePath = path2.join(projectRoot, ".gitignore");
2172
+ if ((0, import_fs2.existsSync)(gitignorePath)) {
2173
+ const gitignoreContent = (0, import_fs2.readFileSync)(gitignorePath, "utf-8");
2212
2174
  ig.add(gitignoreContent);
2213
2175
  }
2214
2176
  return ig;
2215
2177
  }
2216
2178
  function shouldIncludeFile(filePath, projectRoot, includePatterns, excludePatterns, ignoreFilter) {
2217
- const relativePath = path3.relative(projectRoot, filePath);
2179
+ const relativePath = path2.relative(projectRoot, filePath);
2218
2180
  if (ignoreFilter.ignores(relativePath)) {
2219
2181
  return false;
2220
2182
  }
@@ -2236,10 +2198,10 @@ function matchGlob(filePath, pattern) {
2236
2198
  return regex.test(filePath);
2237
2199
  }
2238
2200
  async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns, ignoreFilter, maxFileSize, skipped) {
2239
- const entries = await import_fs3.promises.readdir(dir, { withFileTypes: true });
2201
+ const entries = await import_fs2.promises.readdir(dir, { withFileTypes: true });
2240
2202
  for (const entry of entries) {
2241
- const fullPath = path3.join(dir, entry.name);
2242
- const relativePath = path3.relative(projectRoot, fullPath);
2203
+ const fullPath = path2.join(dir, entry.name);
2204
+ const relativePath = path2.relative(projectRoot, fullPath);
2243
2205
  if (ignoreFilter.ignores(relativePath)) {
2244
2206
  if (entry.isFile()) {
2245
2207
  skipped.push({ path: relativePath, reason: "gitignore" });
@@ -2257,7 +2219,7 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
2257
2219
  skipped
2258
2220
  );
2259
2221
  } else if (entry.isFile()) {
2260
- const stat4 = await import_fs3.promises.stat(fullPath);
2222
+ const stat4 = await import_fs2.promises.stat(fullPath);
2261
2223
  if (stat4.size > maxFileSize) {
2262
2224
  skipped.push({ path: relativePath, reason: "too_large" });
2263
2225
  continue;
@@ -2362,13 +2324,13 @@ function padRight(str, length) {
2362
2324
  }
2363
2325
 
2364
2326
  // src/native/index.ts
2365
- var path4 = __toESM(require("path"), 1);
2366
- var os3 = __toESM(require("os"), 1);
2327
+ var path3 = __toESM(require("path"), 1);
2328
+ var os2 = __toESM(require("os"), 1);
2367
2329
  var import_url = require("url");
2368
2330
  var import_meta = {};
2369
2331
  function getNativeBinding() {
2370
- const platform2 = os3.platform();
2371
- const arch2 = os3.arch();
2332
+ const platform2 = os2.platform();
2333
+ const arch2 = os2.arch();
2372
2334
  let bindingName;
2373
2335
  if (platform2 === "darwin" && arch2 === "arm64") {
2374
2336
  bindingName = "codebase-index-native.darwin-arm64.node";
@@ -2385,15 +2347,15 @@ function getNativeBinding() {
2385
2347
  }
2386
2348
  let currentDir;
2387
2349
  if (typeof import_meta !== "undefined" && import_meta.url) {
2388
- currentDir = path4.dirname((0, import_url.fileURLToPath)(import_meta.url));
2350
+ currentDir = path3.dirname((0, import_url.fileURLToPath)(import_meta.url));
2389
2351
  } else if (typeof __dirname !== "undefined") {
2390
2352
  currentDir = __dirname;
2391
2353
  } else {
2392
2354
  currentDir = process.cwd();
2393
2355
  }
2394
2356
  const isDevMode = currentDir.includes("/src/native");
2395
- const packageRoot = isDevMode ? path4.resolve(currentDir, "../..") : path4.resolve(currentDir, "..");
2396
- const nativePath = path4.join(packageRoot, "native", bindingName);
2357
+ const packageRoot = isDevMode ? path3.resolve(currentDir, "../..") : path3.resolve(currentDir, "..");
2358
+ const nativePath = path3.join(packageRoot, "native", bindingName);
2397
2359
  return require(nativePath);
2398
2360
  }
2399
2361
  var native = getNativeBinding();
@@ -2668,139 +2630,39 @@ function generateChunkId(filePath, chunk) {
2668
2630
  function generateChunkHash(chunk) {
2669
2631
  return hashContent(chunk.content);
2670
2632
  }
2671
-
2672
- // src/indexer/inverted-index.ts
2673
- var import_fs4 = require("fs");
2674
- var path5 = __toESM(require("path"), 1);
2675
2633
  var InvertedIndex = class {
2676
- indexPath;
2677
- termToChunks = /* @__PURE__ */ new Map();
2678
- chunkTokens = /* @__PURE__ */ new Map();
2679
- totalTokenCount = 0;
2634
+ inner;
2680
2635
  constructor(indexPath) {
2681
- this.indexPath = path5.join(indexPath, "inverted-index.json");
2636
+ this.inner = new native.InvertedIndex(indexPath);
2682
2637
  }
2683
2638
  load() {
2684
- if (!(0, import_fs4.existsSync)(this.indexPath)) {
2685
- return;
2686
- }
2687
- try {
2688
- const content = (0, import_fs4.readFileSync)(this.indexPath, "utf-8");
2689
- const data = JSON.parse(content);
2690
- for (const [term, chunkIds] of Object.entries(data.termToChunks)) {
2691
- this.termToChunks.set(term, new Set(chunkIds));
2692
- }
2693
- for (const [chunkId, tokens] of Object.entries(data.chunkTokens)) {
2694
- const tokenMap = new Map(Object.entries(tokens).map(([k, v]) => [k, v]));
2695
- this.chunkTokens.set(chunkId, tokenMap);
2696
- for (const count of tokenMap.values()) {
2697
- this.totalTokenCount += count;
2698
- }
2699
- }
2700
- } catch {
2701
- this.termToChunks.clear();
2702
- this.chunkTokens.clear();
2703
- this.totalTokenCount = 0;
2704
- }
2639
+ this.inner.load();
2705
2640
  }
2706
2641
  save() {
2707
- const data = {
2708
- termToChunks: {},
2709
- chunkTokens: {},
2710
- avgDocLength: this.getAvgDocLength()
2711
- };
2712
- for (const [term, chunkIds] of this.termToChunks) {
2713
- data.termToChunks[term] = Array.from(chunkIds);
2714
- }
2715
- for (const [chunkId, tokens] of this.chunkTokens) {
2716
- data.chunkTokens[chunkId] = Object.fromEntries(tokens);
2717
- }
2718
- (0, import_fs4.writeFileSync)(this.indexPath, JSON.stringify(data));
2642
+ this.inner.save();
2719
2643
  }
2720
2644
  addChunk(chunkId, content) {
2721
- const tokens = this.tokenize(content);
2722
- const termFreq = /* @__PURE__ */ new Map();
2723
- for (const token of tokens) {
2724
- termFreq.set(token, (termFreq.get(token) || 0) + 1);
2725
- const chunks = this.termToChunks.get(token) || /* @__PURE__ */ new Set();
2726
- chunks.add(chunkId);
2727
- this.termToChunks.set(token, chunks);
2728
- }
2729
- this.chunkTokens.set(chunkId, termFreq);
2730
- this.totalTokenCount += tokens.length;
2645
+ this.inner.addChunk(chunkId, content);
2731
2646
  }
2732
2647
  removeChunk(chunkId) {
2733
- const tokens = this.chunkTokens.get(chunkId);
2734
- if (!tokens) return;
2735
- for (const [token, count] of tokens) {
2736
- this.totalTokenCount -= count;
2737
- const chunks = this.termToChunks.get(token);
2738
- if (chunks) {
2739
- chunks.delete(chunkId);
2740
- if (chunks.size === 0) {
2741
- this.termToChunks.delete(token);
2742
- }
2743
- }
2744
- }
2745
- this.chunkTokens.delete(chunkId);
2648
+ return this.inner.removeChunk(chunkId);
2746
2649
  }
2747
- search(query) {
2748
- const queryTokens = this.tokenize(query);
2749
- if (queryTokens.length === 0) {
2750
- return /* @__PURE__ */ new Map();
2751
- }
2752
- const candidateChunks = /* @__PURE__ */ new Set();
2753
- for (const token of queryTokens) {
2754
- const chunks = this.termToChunks.get(token);
2755
- if (chunks) {
2756
- for (const chunkId of chunks) {
2757
- candidateChunks.add(chunkId);
2758
- }
2759
- }
2760
- }
2761
- const scores = /* @__PURE__ */ new Map();
2762
- const k1 = 1.2;
2763
- const b = 0.75;
2764
- const N = this.chunkTokens.size;
2765
- const avgDocLength = this.getAvgDocLength();
2766
- for (const chunkId of candidateChunks) {
2767
- const termFreq = this.chunkTokens.get(chunkId);
2768
- if (!termFreq) continue;
2769
- const docLength = Array.from(termFreq.values()).reduce((a, b2) => a + b2, 0);
2770
- let score = 0;
2771
- for (const term of queryTokens) {
2772
- const tf = termFreq.get(term) || 0;
2773
- if (tf === 0) continue;
2774
- const df = this.termToChunks.get(term)?.size || 0;
2775
- const idf = Math.log((N - df + 0.5) / (df + 0.5) + 1);
2776
- const tfNorm = tf * (k1 + 1) / (tf + k1 * (1 - b + b * (docLength / avgDocLength)));
2777
- score += idf * tfNorm;
2778
- }
2779
- scores.set(chunkId, score);
2650
+ search(query, limit) {
2651
+ const results = this.inner.search(query, limit ?? 100);
2652
+ const map = /* @__PURE__ */ new Map();
2653
+ for (const r of results) {
2654
+ map.set(r.chunkId, r.score);
2780
2655
  }
2781
- const maxScore = Math.max(...scores.values(), 1);
2782
- for (const [chunkId, score] of scores) {
2783
- scores.set(chunkId, score / maxScore);
2784
- }
2785
- return scores;
2656
+ return map;
2786
2657
  }
2787
2658
  hasChunk(chunkId) {
2788
- return this.chunkTokens.has(chunkId);
2659
+ return this.inner.hasChunk(chunkId);
2789
2660
  }
2790
2661
  clear() {
2791
- this.termToChunks.clear();
2792
- this.chunkTokens.clear();
2793
- this.totalTokenCount = 0;
2662
+ this.inner.clear();
2794
2663
  }
2795
2664
  getDocumentCount() {
2796
- return this.chunkTokens.size;
2797
- }
2798
- getAvgDocLength() {
2799
- const count = this.chunkTokens.size;
2800
- return count > 0 ? this.totalTokenCount / count : 100;
2801
- }
2802
- tokenize(text) {
2803
- return text.toLowerCase().replace(/[^\w\s]/g, " ").split(/\s+/).filter((t) => t.length > 2);
2665
+ return this.inner.documentCount();
2804
2666
  }
2805
2667
  };
2806
2668
 
@@ -2815,23 +2677,25 @@ var Indexer = class {
2815
2677
  detectedProvider = null;
2816
2678
  fileHashCache = /* @__PURE__ */ new Map();
2817
2679
  fileHashCachePath = "";
2680
+ failedBatchesPath = "";
2818
2681
  constructor(projectRoot, config) {
2819
2682
  this.projectRoot = projectRoot;
2820
2683
  this.config = config;
2821
2684
  this.indexPath = this.getIndexPath();
2822
- this.fileHashCachePath = path6.join(this.indexPath, "file-hashes.json");
2685
+ this.fileHashCachePath = path4.join(this.indexPath, "file-hashes.json");
2686
+ this.failedBatchesPath = path4.join(this.indexPath, "failed-batches.json");
2823
2687
  }
2824
2688
  getIndexPath() {
2825
2689
  if (this.config.scope === "global") {
2826
2690
  const homeDir = process.env.HOME || process.env.USERPROFILE || "";
2827
- return path6.join(homeDir, ".opencode", "global-index");
2691
+ return path4.join(homeDir, ".opencode", "global-index");
2828
2692
  }
2829
- return path6.join(this.projectRoot, ".opencode", "index");
2693
+ return path4.join(this.projectRoot, ".opencode", "index");
2830
2694
  }
2831
2695
  loadFileHashCache() {
2832
2696
  try {
2833
- if ((0, import_fs5.existsSync)(this.fileHashCachePath)) {
2834
- const data = (0, import_fs5.readFileSync)(this.fileHashCachePath, "utf-8");
2697
+ if ((0, import_fs3.existsSync)(this.fileHashCachePath)) {
2698
+ const data = (0, import_fs3.readFileSync)(this.fileHashCachePath, "utf-8");
2835
2699
  const parsed = JSON.parse(data);
2836
2700
  this.fileHashCache = new Map(Object.entries(parsed));
2837
2701
  }
@@ -2844,7 +2708,38 @@ var Indexer = class {
2844
2708
  for (const [k, v] of this.fileHashCache) {
2845
2709
  obj[k] = v;
2846
2710
  }
2847
- (0, import_fs5.writeFileSync)(this.fileHashCachePath, JSON.stringify(obj));
2711
+ (0, import_fs3.writeFileSync)(this.fileHashCachePath, JSON.stringify(obj));
2712
+ }
2713
+ loadFailedBatches() {
2714
+ try {
2715
+ if ((0, import_fs3.existsSync)(this.failedBatchesPath)) {
2716
+ const data = (0, import_fs3.readFileSync)(this.failedBatchesPath, "utf-8");
2717
+ return JSON.parse(data);
2718
+ }
2719
+ } catch {
2720
+ return [];
2721
+ }
2722
+ return [];
2723
+ }
2724
+ saveFailedBatches(batches) {
2725
+ if (batches.length === 0) {
2726
+ if ((0, import_fs3.existsSync)(this.failedBatchesPath)) {
2727
+ import_fs3.promises.unlink(this.failedBatchesPath).catch(() => {
2728
+ });
2729
+ }
2730
+ return;
2731
+ }
2732
+ (0, import_fs3.writeFileSync)(this.failedBatchesPath, JSON.stringify(batches, null, 2));
2733
+ }
2734
+ addFailedBatch(batch, error) {
2735
+ const existing = this.loadFailedBatches();
2736
+ existing.push({
2737
+ chunks: batch,
2738
+ error,
2739
+ attemptCount: 1,
2740
+ lastAttempt: (/* @__PURE__ */ new Date()).toISOString()
2741
+ });
2742
+ this.saveFailedBatches(existing);
2848
2743
  }
2849
2744
  async initialize() {
2850
2745
  this.detectedProvider = await detectEmbeddingProvider(this.config.embeddingProvider);
@@ -2857,15 +2752,16 @@ var Indexer = class {
2857
2752
  this.detectedProvider.credentials,
2858
2753
  this.detectedProvider.modelInfo
2859
2754
  );
2860
- await import_fs5.promises.mkdir(this.indexPath, { recursive: true });
2755
+ await import_fs3.promises.mkdir(this.indexPath, { recursive: true });
2861
2756
  const dimensions = this.detectedProvider.modelInfo.dimensions;
2862
- const storePath = path6.join(this.indexPath, "vectors");
2757
+ const storePath = path4.join(this.indexPath, "vectors");
2863
2758
  this.store = new VectorStore(storePath, dimensions);
2864
- const indexFilePath = path6.join(this.indexPath, "vectors.usearch");
2865
- if ((0, import_fs5.existsSync)(indexFilePath)) {
2759
+ const indexFilePath = path4.join(this.indexPath, "vectors.usearch");
2760
+ if ((0, import_fs3.existsSync)(indexFilePath)) {
2866
2761
  this.store.load();
2867
2762
  }
2868
- this.invertedIndex = new InvertedIndex(this.indexPath);
2763
+ const invertedIndexPath = path4.join(this.indexPath, "inverted-index.json");
2764
+ this.invertedIndex = new InvertedIndex(invertedIndexPath);
2869
2765
  this.invertedIndex.load();
2870
2766
  }
2871
2767
  async ensureInitialized() {
@@ -2929,7 +2825,7 @@ var Indexer = class {
2929
2825
  if (this.fileHashCache.get(f.path) === currentHash) {
2930
2826
  unchangedFilePaths.add(f.path);
2931
2827
  } else {
2932
- const content = await import_fs5.promises.readFile(f.path, "utf-8");
2828
+ const content = await import_fs3.promises.readFile(f.path, "utf-8");
2933
2829
  changedFiles.push({ path: f.path, content, hash: currentHash });
2934
2830
  }
2935
2831
  }
@@ -2964,14 +2860,22 @@ var Indexer = class {
2964
2860
  for (const parsed of parsedFiles) {
2965
2861
  currentFilePaths.add(parsed.path);
2966
2862
  if (parsed.chunks.length === 0) {
2967
- const relativePath = path6.relative(this.projectRoot, parsed.path);
2863
+ const relativePath = path4.relative(this.projectRoot, parsed.path);
2968
2864
  stats.parseFailures.push(relativePath);
2969
2865
  }
2866
+ let fileChunkCount = 0;
2970
2867
  for (const chunk of parsed.chunks) {
2868
+ if (fileChunkCount >= this.config.indexing.maxChunksPerFile) {
2869
+ break;
2870
+ }
2871
+ if (this.config.indexing.semanticOnly && chunk.chunkType === "other") {
2872
+ continue;
2873
+ }
2971
2874
  const id = generateChunkId(parsed.path, chunk);
2972
2875
  const contentHash = generateChunkHash(chunk);
2973
2876
  currentChunkIds.add(id);
2974
2877
  if (existingChunks.get(id) === contentHash) {
2878
+ fileChunkCount++;
2975
2879
  continue;
2976
2880
  }
2977
2881
  const text = createEmbeddingText(chunk, parsed.path);
@@ -2985,6 +2889,7 @@ var Indexer = class {
2985
2889
  hash: contentHash
2986
2890
  };
2987
2891
  pendingChunks.push({ id, text, content: chunk.content, metadata });
2892
+ fileChunkCount++;
2988
2893
  }
2989
2894
  }
2990
2895
  let removedCount = 0;
@@ -3074,6 +2979,7 @@ var Indexer = class {
3074
2979
  });
3075
2980
  } catch (error) {
3076
2981
  stats.failedChunks += batch.length;
2982
+ this.addFailedBatch(batch, String(error));
3077
2983
  console.error(`Failed to embed batch after retries: ${error}`);
3078
2984
  }
3079
2985
  });
@@ -3091,6 +2997,9 @@ var Indexer = class {
3091
2997
  this.fileHashCache = currentFileHashes;
3092
2998
  this.saveFileHashCache();
3093
2999
  stats.durationMs = Date.now() - startTime;
3000
+ if (stats.failedChunks > 0) {
3001
+ stats.failedBatchesPath = this.failedBatchesPath;
3002
+ }
3094
3003
  onProgress?.({
3095
3004
  phase: "complete",
3096
3005
  filesProcessed: files.length,
@@ -3133,7 +3042,7 @@ var Indexer = class {
3133
3042
  let contextEndLine = r.metadata.endLine;
3134
3043
  if (this.config.search.includeContext) {
3135
3044
  try {
3136
- const fileContent = await import_fs5.promises.readFile(
3045
+ const fileContent = await import_fs3.promises.readFile(
3137
3046
  r.metadata.filePath,
3138
3047
  "utf-8"
3139
3048
  );
@@ -3236,7 +3145,7 @@ var Indexer = class {
3236
3145
  const removedFilePaths = [];
3237
3146
  let removedCount = 0;
3238
3147
  for (const [filePath, chunkKeys] of filePathsToChunkKeys) {
3239
- if (!(0, import_fs5.existsSync)(filePath)) {
3148
+ if (!(0, import_fs3.existsSync)(filePath)) {
3240
3149
  for (const key of chunkKeys) {
3241
3150
  store.remove(key);
3242
3151
  invertedIndex.removeChunk(key);
@@ -3251,6 +3160,58 @@ var Indexer = class {
3251
3160
  }
3252
3161
  return { removed: removedCount, filePaths: removedFilePaths };
3253
3162
  }
3163
+ async retryFailedBatches() {
3164
+ const { store, provider, invertedIndex } = await this.ensureInitialized();
3165
+ const failedBatches = this.loadFailedBatches();
3166
+ if (failedBatches.length === 0) {
3167
+ return { succeeded: 0, failed: 0, remaining: 0 };
3168
+ }
3169
+ let succeeded = 0;
3170
+ let failed = 0;
3171
+ const stillFailing = [];
3172
+ for (const batch of failedBatches) {
3173
+ try {
3174
+ const result = await pRetry(
3175
+ async () => {
3176
+ const texts = batch.chunks.map((c) => c.text);
3177
+ return provider.embedBatch(texts);
3178
+ },
3179
+ {
3180
+ retries: this.config.indexing.retries,
3181
+ minTimeout: this.config.indexing.retryDelayMs
3182
+ }
3183
+ );
3184
+ const items = batch.chunks.map((chunk, idx) => ({
3185
+ id: chunk.id,
3186
+ vector: result.embeddings[idx],
3187
+ metadata: chunk.metadata
3188
+ }));
3189
+ store.addBatch(items);
3190
+ for (const chunk of batch.chunks) {
3191
+ invertedIndex.removeChunk(chunk.id);
3192
+ invertedIndex.addChunk(chunk.id, chunk.content);
3193
+ }
3194
+ succeeded += batch.chunks.length;
3195
+ } catch (error) {
3196
+ failed += batch.chunks.length;
3197
+ stillFailing.push({
3198
+ ...batch,
3199
+ attemptCount: batch.attemptCount + 1,
3200
+ lastAttempt: (/* @__PURE__ */ new Date()).toISOString(),
3201
+ error: String(error)
3202
+ });
3203
+ }
3204
+ }
3205
+ this.saveFailedBatches(stillFailing);
3206
+ if (succeeded > 0) {
3207
+ store.save();
3208
+ invertedIndex.save();
3209
+ }
3210
+ return { succeeded, failed, remaining: stillFailing.length };
3211
+ }
3212
+ getFailedBatchesCount() {
3213
+ return this.loadFailedBatches().length;
3214
+ }
3254
3215
  };
3255
3216
 
3256
3217
  // node_modules/chokidar/index.js
@@ -3343,7 +3304,7 @@ var ReaddirpStream = class extends import_node_stream.Readable {
3343
3304
  this._directoryFilter = normalizeFilter(opts.directoryFilter);
3344
3305
  const statMethod = opts.lstat ? import_promises.lstat : import_promises.stat;
3345
3306
  if (wantBigintFsStats) {
3346
- this._stat = (path9) => statMethod(path9, { bigint: true });
3307
+ this._stat = (path7) => statMethod(path7, { bigint: true });
3347
3308
  } else {
3348
3309
  this._stat = statMethod;
3349
3310
  }
@@ -3368,8 +3329,8 @@ var ReaddirpStream = class extends import_node_stream.Readable {
3368
3329
  const par = this.parent;
3369
3330
  const fil = par && par.files;
3370
3331
  if (fil && fil.length > 0) {
3371
- const { path: path9, depth } = par;
3372
- const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path9));
3332
+ const { path: path7, depth } = par;
3333
+ const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path7));
3373
3334
  const awaited = await Promise.all(slice);
3374
3335
  for (const entry of awaited) {
3375
3336
  if (!entry)
@@ -3409,20 +3370,20 @@ var ReaddirpStream = class extends import_node_stream.Readable {
3409
3370
  this.reading = false;
3410
3371
  }
3411
3372
  }
3412
- async _exploreDir(path9, depth) {
3373
+ async _exploreDir(path7, depth) {
3413
3374
  let files;
3414
3375
  try {
3415
- files = await (0, import_promises.readdir)(path9, this._rdOptions);
3376
+ files = await (0, import_promises.readdir)(path7, this._rdOptions);
3416
3377
  } catch (error) {
3417
3378
  this._onError(error);
3418
3379
  }
3419
- return { files, depth, path: path9 };
3380
+ return { files, depth, path: path7 };
3420
3381
  }
3421
- async _formatEntry(dirent, path9) {
3382
+ async _formatEntry(dirent, path7) {
3422
3383
  let entry;
3423
3384
  const basename3 = this._isDirent ? dirent.name : dirent;
3424
3385
  try {
3425
- const fullPath = (0, import_node_path.resolve)((0, import_node_path.join)(path9, basename3));
3386
+ const fullPath = (0, import_node_path.resolve)((0, import_node_path.join)(path7, basename3));
3426
3387
  entry = { path: (0, import_node_path.relative)(this._root, fullPath), fullPath, basename: basename3 };
3427
3388
  entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
3428
3389
  } catch (err) {
@@ -3822,16 +3783,16 @@ var delFromSet = (main, prop, item) => {
3822
3783
  };
3823
3784
  var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
3824
3785
  var FsWatchInstances = /* @__PURE__ */ new Map();
3825
- function createFsWatchInstance(path9, options, listener, errHandler, emitRaw) {
3786
+ function createFsWatchInstance(path7, options, listener, errHandler, emitRaw) {
3826
3787
  const handleEvent = (rawEvent, evPath) => {
3827
- listener(path9);
3828
- emitRaw(rawEvent, evPath, { watchedPath: path9 });
3829
- if (evPath && path9 !== evPath) {
3830
- fsWatchBroadcast(sp.resolve(path9, evPath), KEY_LISTENERS, sp.join(path9, evPath));
3788
+ listener(path7);
3789
+ emitRaw(rawEvent, evPath, { watchedPath: path7 });
3790
+ if (evPath && path7 !== evPath) {
3791
+ fsWatchBroadcast(sp.resolve(path7, evPath), KEY_LISTENERS, sp.join(path7, evPath));
3831
3792
  }
3832
3793
  };
3833
3794
  try {
3834
- return (0, import_node_fs.watch)(path9, {
3795
+ return (0, import_node_fs.watch)(path7, {
3835
3796
  persistent: options.persistent
3836
3797
  }, handleEvent);
3837
3798
  } catch (error) {
@@ -3847,12 +3808,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
3847
3808
  listener(val1, val2, val3);
3848
3809
  });
3849
3810
  };
3850
- var setFsWatchListener = (path9, fullPath, options, handlers) => {
3811
+ var setFsWatchListener = (path7, fullPath, options, handlers) => {
3851
3812
  const { listener, errHandler, rawEmitter } = handlers;
3852
3813
  let cont = FsWatchInstances.get(fullPath);
3853
3814
  let watcher;
3854
3815
  if (!options.persistent) {
3855
- watcher = createFsWatchInstance(path9, options, listener, errHandler, rawEmitter);
3816
+ watcher = createFsWatchInstance(path7, options, listener, errHandler, rawEmitter);
3856
3817
  if (!watcher)
3857
3818
  return;
3858
3819
  return watcher.close.bind(watcher);
@@ -3863,7 +3824,7 @@ var setFsWatchListener = (path9, fullPath, options, handlers) => {
3863
3824
  addAndConvert(cont, KEY_RAW, rawEmitter);
3864
3825
  } else {
3865
3826
  watcher = createFsWatchInstance(
3866
- path9,
3827
+ path7,
3867
3828
  options,
3868
3829
  fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
3869
3830
  errHandler,
@@ -3878,7 +3839,7 @@ var setFsWatchListener = (path9, fullPath, options, handlers) => {
3878
3839
  cont.watcherUnusable = true;
3879
3840
  if (isWindows && error.code === "EPERM") {
3880
3841
  try {
3881
- const fd = await (0, import_promises2.open)(path9, "r");
3842
+ const fd = await (0, import_promises2.open)(path7, "r");
3882
3843
  await fd.close();
3883
3844
  broadcastErr(error);
3884
3845
  } catch (err) {
@@ -3909,7 +3870,7 @@ var setFsWatchListener = (path9, fullPath, options, handlers) => {
3909
3870
  };
3910
3871
  };
3911
3872
  var FsWatchFileInstances = /* @__PURE__ */ new Map();
3912
- var setFsWatchFileListener = (path9, fullPath, options, handlers) => {
3873
+ var setFsWatchFileListener = (path7, fullPath, options, handlers) => {
3913
3874
  const { listener, rawEmitter } = handlers;
3914
3875
  let cont = FsWatchFileInstances.get(fullPath);
3915
3876
  const copts = cont && cont.options;
@@ -3931,7 +3892,7 @@ var setFsWatchFileListener = (path9, fullPath, options, handlers) => {
3931
3892
  });
3932
3893
  const currmtime = curr.mtimeMs;
3933
3894
  if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
3934
- foreach(cont.listeners, (listener2) => listener2(path9, curr));
3895
+ foreach(cont.listeners, (listener2) => listener2(path7, curr));
3935
3896
  }
3936
3897
  })
3937
3898
  };
@@ -3961,13 +3922,13 @@ var NodeFsHandler = class {
3961
3922
  * @param listener on fs change
3962
3923
  * @returns closer for the watcher instance
3963
3924
  */
3964
- _watchWithNodeFs(path9, listener) {
3925
+ _watchWithNodeFs(path7, listener) {
3965
3926
  const opts = this.fsw.options;
3966
- const directory = sp.dirname(path9);
3967
- const basename3 = sp.basename(path9);
3927
+ const directory = sp.dirname(path7);
3928
+ const basename3 = sp.basename(path7);
3968
3929
  const parent = this.fsw._getWatchedDir(directory);
3969
3930
  parent.add(basename3);
3970
- const absolutePath = sp.resolve(path9);
3931
+ const absolutePath = sp.resolve(path7);
3971
3932
  const options = {
3972
3933
  persistent: opts.persistent
3973
3934
  };
@@ -3977,12 +3938,12 @@ var NodeFsHandler = class {
3977
3938
  if (opts.usePolling) {
3978
3939
  const enableBin = opts.interval !== opts.binaryInterval;
3979
3940
  options.interval = enableBin && isBinaryPath(basename3) ? opts.binaryInterval : opts.interval;
3980
- closer = setFsWatchFileListener(path9, absolutePath, options, {
3941
+ closer = setFsWatchFileListener(path7, absolutePath, options, {
3981
3942
  listener,
3982
3943
  rawEmitter: this.fsw._emitRaw
3983
3944
  });
3984
3945
  } else {
3985
- closer = setFsWatchListener(path9, absolutePath, options, {
3946
+ closer = setFsWatchListener(path7, absolutePath, options, {
3986
3947
  listener,
3987
3948
  errHandler: this._boundHandleError,
3988
3949
  rawEmitter: this.fsw._emitRaw
@@ -4004,7 +3965,7 @@ var NodeFsHandler = class {
4004
3965
  let prevStats = stats;
4005
3966
  if (parent.has(basename3))
4006
3967
  return;
4007
- const listener = async (path9, newStats) => {
3968
+ const listener = async (path7, newStats) => {
4008
3969
  if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
4009
3970
  return;
4010
3971
  if (!newStats || newStats.mtimeMs === 0) {
@@ -4018,11 +3979,11 @@ var NodeFsHandler = class {
4018
3979
  this.fsw._emit(EV.CHANGE, file, newStats2);
4019
3980
  }
4020
3981
  if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
4021
- this.fsw._closeFile(path9);
3982
+ this.fsw._closeFile(path7);
4022
3983
  prevStats = newStats2;
4023
3984
  const closer2 = this._watchWithNodeFs(file, listener);
4024
3985
  if (closer2)
4025
- this.fsw._addPathCloser(path9, closer2);
3986
+ this.fsw._addPathCloser(path7, closer2);
4026
3987
  } else {
4027
3988
  prevStats = newStats2;
4028
3989
  }
@@ -4054,7 +4015,7 @@ var NodeFsHandler = class {
4054
4015
  * @param item basename of this item
4055
4016
  * @returns true if no more processing is needed for this entry.
4056
4017
  */
4057
- async _handleSymlink(entry, directory, path9, item) {
4018
+ async _handleSymlink(entry, directory, path7, item) {
4058
4019
  if (this.fsw.closed) {
4059
4020
  return;
4060
4021
  }
@@ -4064,7 +4025,7 @@ var NodeFsHandler = class {
4064
4025
  this.fsw._incrReadyCount();
4065
4026
  let linkPath;
4066
4027
  try {
4067
- linkPath = await (0, import_promises2.realpath)(path9);
4028
+ linkPath = await (0, import_promises2.realpath)(path7);
4068
4029
  } catch (e) {
4069
4030
  this.fsw._emitReady();
4070
4031
  return true;
@@ -4074,12 +4035,12 @@ var NodeFsHandler = class {
4074
4035
  if (dir.has(item)) {
4075
4036
  if (this.fsw._symlinkPaths.get(full) !== linkPath) {
4076
4037
  this.fsw._symlinkPaths.set(full, linkPath);
4077
- this.fsw._emit(EV.CHANGE, path9, entry.stats);
4038
+ this.fsw._emit(EV.CHANGE, path7, entry.stats);
4078
4039
  }
4079
4040
  } else {
4080
4041
  dir.add(item);
4081
4042
  this.fsw._symlinkPaths.set(full, linkPath);
4082
- this.fsw._emit(EV.ADD, path9, entry.stats);
4043
+ this.fsw._emit(EV.ADD, path7, entry.stats);
4083
4044
  }
4084
4045
  this.fsw._emitReady();
4085
4046
  return true;
@@ -4109,9 +4070,9 @@ var NodeFsHandler = class {
4109
4070
  return;
4110
4071
  }
4111
4072
  const item = entry.path;
4112
- let path9 = sp.join(directory, item);
4073
+ let path7 = sp.join(directory, item);
4113
4074
  current.add(item);
4114
- if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path9, item)) {
4075
+ if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path7, item)) {
4115
4076
  return;
4116
4077
  }
4117
4078
  if (this.fsw.closed) {
@@ -4120,8 +4081,8 @@ var NodeFsHandler = class {
4120
4081
  }
4121
4082
  if (item === target || !target && !previous.has(item)) {
4122
4083
  this.fsw._incrReadyCount();
4123
- path9 = sp.join(dir, sp.relative(dir, path9));
4124
- this._addToNodeFs(path9, initialAdd, wh, depth + 1);
4084
+ path7 = sp.join(dir, sp.relative(dir, path7));
4085
+ this._addToNodeFs(path7, initialAdd, wh, depth + 1);
4125
4086
  }
4126
4087
  }).on(EV.ERROR, this._boundHandleError);
4127
4088
  return new Promise((resolve4, reject) => {
@@ -4190,13 +4151,13 @@ var NodeFsHandler = class {
4190
4151
  * @param depth Child path actually targeted for watch
4191
4152
  * @param target Child path actually targeted for watch
4192
4153
  */
4193
- async _addToNodeFs(path9, initialAdd, priorWh, depth, target) {
4154
+ async _addToNodeFs(path7, initialAdd, priorWh, depth, target) {
4194
4155
  const ready = this.fsw._emitReady;
4195
- if (this.fsw._isIgnored(path9) || this.fsw.closed) {
4156
+ if (this.fsw._isIgnored(path7) || this.fsw.closed) {
4196
4157
  ready();
4197
4158
  return false;
4198
4159
  }
4199
- const wh = this.fsw._getWatchHelpers(path9);
4160
+ const wh = this.fsw._getWatchHelpers(path7);
4200
4161
  if (priorWh) {
4201
4162
  wh.filterPath = (entry) => priorWh.filterPath(entry);
4202
4163
  wh.filterDir = (entry) => priorWh.filterDir(entry);
@@ -4212,8 +4173,8 @@ var NodeFsHandler = class {
4212
4173
  const follow = this.fsw.options.followSymlinks;
4213
4174
  let closer;
4214
4175
  if (stats.isDirectory()) {
4215
- const absPath = sp.resolve(path9);
4216
- const targetPath = follow ? await (0, import_promises2.realpath)(path9) : path9;
4176
+ const absPath = sp.resolve(path7);
4177
+ const targetPath = follow ? await (0, import_promises2.realpath)(path7) : path7;
4217
4178
  if (this.fsw.closed)
4218
4179
  return;
4219
4180
  closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
@@ -4223,29 +4184,29 @@ var NodeFsHandler = class {
4223
4184
  this.fsw._symlinkPaths.set(absPath, targetPath);
4224
4185
  }
4225
4186
  } else if (stats.isSymbolicLink()) {
4226
- const targetPath = follow ? await (0, import_promises2.realpath)(path9) : path9;
4187
+ const targetPath = follow ? await (0, import_promises2.realpath)(path7) : path7;
4227
4188
  if (this.fsw.closed)
4228
4189
  return;
4229
4190
  const parent = sp.dirname(wh.watchPath);
4230
4191
  this.fsw._getWatchedDir(parent).add(wh.watchPath);
4231
4192
  this.fsw._emit(EV.ADD, wh.watchPath, stats);
4232
- closer = await this._handleDir(parent, stats, initialAdd, depth, path9, wh, targetPath);
4193
+ closer = await this._handleDir(parent, stats, initialAdd, depth, path7, wh, targetPath);
4233
4194
  if (this.fsw.closed)
4234
4195
  return;
4235
4196
  if (targetPath !== void 0) {
4236
- this.fsw._symlinkPaths.set(sp.resolve(path9), targetPath);
4197
+ this.fsw._symlinkPaths.set(sp.resolve(path7), targetPath);
4237
4198
  }
4238
4199
  } else {
4239
4200
  closer = this._handleFile(wh.watchPath, stats, initialAdd);
4240
4201
  }
4241
4202
  ready();
4242
4203
  if (closer)
4243
- this.fsw._addPathCloser(path9, closer);
4204
+ this.fsw._addPathCloser(path7, closer);
4244
4205
  return false;
4245
4206
  } catch (error) {
4246
4207
  if (this.fsw._handleError(error)) {
4247
4208
  ready();
4248
- return path9;
4209
+ return path7;
4249
4210
  }
4250
4211
  }
4251
4212
  }
@@ -4288,24 +4249,24 @@ function createPattern(matcher) {
4288
4249
  }
4289
4250
  return () => false;
4290
4251
  }
4291
- function normalizePath(path9) {
4292
- if (typeof path9 !== "string")
4252
+ function normalizePath(path7) {
4253
+ if (typeof path7 !== "string")
4293
4254
  throw new Error("string expected");
4294
- path9 = sp2.normalize(path9);
4295
- path9 = path9.replace(/\\/g, "/");
4255
+ path7 = sp2.normalize(path7);
4256
+ path7 = path7.replace(/\\/g, "/");
4296
4257
  let prepend = false;
4297
- if (path9.startsWith("//"))
4258
+ if (path7.startsWith("//"))
4298
4259
  prepend = true;
4299
- path9 = path9.replace(DOUBLE_SLASH_RE, "/");
4260
+ path7 = path7.replace(DOUBLE_SLASH_RE, "/");
4300
4261
  if (prepend)
4301
- path9 = "/" + path9;
4302
- return path9;
4262
+ path7 = "/" + path7;
4263
+ return path7;
4303
4264
  }
4304
4265
  function matchPatterns(patterns, testString, stats) {
4305
- const path9 = normalizePath(testString);
4266
+ const path7 = normalizePath(testString);
4306
4267
  for (let index = 0; index < patterns.length; index++) {
4307
4268
  const pattern = patterns[index];
4308
- if (pattern(path9, stats)) {
4269
+ if (pattern(path7, stats)) {
4309
4270
  return true;
4310
4271
  }
4311
4272
  }
@@ -4343,19 +4304,19 @@ var toUnix = (string) => {
4343
4304
  }
4344
4305
  return str;
4345
4306
  };
4346
- var normalizePathToUnix = (path9) => toUnix(sp2.normalize(toUnix(path9)));
4347
- var normalizeIgnored = (cwd = "") => (path9) => {
4348
- if (typeof path9 === "string") {
4349
- return normalizePathToUnix(sp2.isAbsolute(path9) ? path9 : sp2.join(cwd, path9));
4307
+ var normalizePathToUnix = (path7) => toUnix(sp2.normalize(toUnix(path7)));
4308
+ var normalizeIgnored = (cwd = "") => (path7) => {
4309
+ if (typeof path7 === "string") {
4310
+ return normalizePathToUnix(sp2.isAbsolute(path7) ? path7 : sp2.join(cwd, path7));
4350
4311
  } else {
4351
- return path9;
4312
+ return path7;
4352
4313
  }
4353
4314
  };
4354
- var getAbsolutePath = (path9, cwd) => {
4355
- if (sp2.isAbsolute(path9)) {
4356
- return path9;
4315
+ var getAbsolutePath = (path7, cwd) => {
4316
+ if (sp2.isAbsolute(path7)) {
4317
+ return path7;
4357
4318
  }
4358
- return sp2.join(cwd, path9);
4319
+ return sp2.join(cwd, path7);
4359
4320
  };
4360
4321
  var EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
4361
4322
  var DirEntry = class {
@@ -4420,10 +4381,10 @@ var WatchHelper = class {
4420
4381
  dirParts;
4421
4382
  followSymlinks;
4422
4383
  statMethod;
4423
- constructor(path9, follow, fsw) {
4384
+ constructor(path7, follow, fsw) {
4424
4385
  this.fsw = fsw;
4425
- const watchPath = path9;
4426
- this.path = path9 = path9.replace(REPLACER_RE, "");
4386
+ const watchPath = path7;
4387
+ this.path = path7 = path7.replace(REPLACER_RE, "");
4427
4388
  this.watchPath = watchPath;
4428
4389
  this.fullWatchPath = sp2.resolve(watchPath);
4429
4390
  this.dirParts = [];
@@ -4563,20 +4524,20 @@ var FSWatcher = class extends import_node_events.EventEmitter {
4563
4524
  this._closePromise = void 0;
4564
4525
  let paths = unifyPaths(paths_);
4565
4526
  if (cwd) {
4566
- paths = paths.map((path9) => {
4567
- const absPath = getAbsolutePath(path9, cwd);
4527
+ paths = paths.map((path7) => {
4528
+ const absPath = getAbsolutePath(path7, cwd);
4568
4529
  return absPath;
4569
4530
  });
4570
4531
  }
4571
- paths.forEach((path9) => {
4572
- this._removeIgnoredPath(path9);
4532
+ paths.forEach((path7) => {
4533
+ this._removeIgnoredPath(path7);
4573
4534
  });
4574
4535
  this._userIgnored = void 0;
4575
4536
  if (!this._readyCount)
4576
4537
  this._readyCount = 0;
4577
4538
  this._readyCount += paths.length;
4578
- Promise.all(paths.map(async (path9) => {
4579
- const res = await this._nodeFsHandler._addToNodeFs(path9, !_internal, void 0, 0, _origAdd);
4539
+ Promise.all(paths.map(async (path7) => {
4540
+ const res = await this._nodeFsHandler._addToNodeFs(path7, !_internal, void 0, 0, _origAdd);
4580
4541
  if (res)
4581
4542
  this._emitReady();
4582
4543
  return res;
@@ -4598,17 +4559,17 @@ var FSWatcher = class extends import_node_events.EventEmitter {
4598
4559
  return this;
4599
4560
  const paths = unifyPaths(paths_);
4600
4561
  const { cwd } = this.options;
4601
- paths.forEach((path9) => {
4602
- if (!sp2.isAbsolute(path9) && !this._closers.has(path9)) {
4562
+ paths.forEach((path7) => {
4563
+ if (!sp2.isAbsolute(path7) && !this._closers.has(path7)) {
4603
4564
  if (cwd)
4604
- path9 = sp2.join(cwd, path9);
4605
- path9 = sp2.resolve(path9);
4565
+ path7 = sp2.join(cwd, path7);
4566
+ path7 = sp2.resolve(path7);
4606
4567
  }
4607
- this._closePath(path9);
4608
- this._addIgnoredPath(path9);
4609
- if (this._watched.has(path9)) {
4568
+ this._closePath(path7);
4569
+ this._addIgnoredPath(path7);
4570
+ if (this._watched.has(path7)) {
4610
4571
  this._addIgnoredPath({
4611
- path: path9,
4572
+ path: path7,
4612
4573
  recursive: true
4613
4574
  });
4614
4575
  }
@@ -4672,38 +4633,38 @@ var FSWatcher = class extends import_node_events.EventEmitter {
4672
4633
  * @param stats arguments to be passed with event
4673
4634
  * @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
4674
4635
  */
4675
- async _emit(event, path9, stats) {
4636
+ async _emit(event, path7, stats) {
4676
4637
  if (this.closed)
4677
4638
  return;
4678
4639
  const opts = this.options;
4679
4640
  if (isWindows)
4680
- path9 = sp2.normalize(path9);
4641
+ path7 = sp2.normalize(path7);
4681
4642
  if (opts.cwd)
4682
- path9 = sp2.relative(opts.cwd, path9);
4683
- const args = [path9];
4643
+ path7 = sp2.relative(opts.cwd, path7);
4644
+ const args = [path7];
4684
4645
  if (stats != null)
4685
4646
  args.push(stats);
4686
4647
  const awf = opts.awaitWriteFinish;
4687
4648
  let pw;
4688
- if (awf && (pw = this._pendingWrites.get(path9))) {
4649
+ if (awf && (pw = this._pendingWrites.get(path7))) {
4689
4650
  pw.lastChange = /* @__PURE__ */ new Date();
4690
4651
  return this;
4691
4652
  }
4692
4653
  if (opts.atomic) {
4693
4654
  if (event === EVENTS.UNLINK) {
4694
- this._pendingUnlinks.set(path9, [event, ...args]);
4655
+ this._pendingUnlinks.set(path7, [event, ...args]);
4695
4656
  setTimeout(() => {
4696
- this._pendingUnlinks.forEach((entry, path10) => {
4657
+ this._pendingUnlinks.forEach((entry, path8) => {
4697
4658
  this.emit(...entry);
4698
4659
  this.emit(EVENTS.ALL, ...entry);
4699
- this._pendingUnlinks.delete(path10);
4660
+ this._pendingUnlinks.delete(path8);
4700
4661
  });
4701
4662
  }, typeof opts.atomic === "number" ? opts.atomic : 100);
4702
4663
  return this;
4703
4664
  }
4704
- if (event === EVENTS.ADD && this._pendingUnlinks.has(path9)) {
4665
+ if (event === EVENTS.ADD && this._pendingUnlinks.has(path7)) {
4705
4666
  event = EVENTS.CHANGE;
4706
- this._pendingUnlinks.delete(path9);
4667
+ this._pendingUnlinks.delete(path7);
4707
4668
  }
4708
4669
  }
4709
4670
  if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
@@ -4721,16 +4682,16 @@ var FSWatcher = class extends import_node_events.EventEmitter {
4721
4682
  this.emitWithAll(event, args);
4722
4683
  }
4723
4684
  };
4724
- this._awaitWriteFinish(path9, awf.stabilityThreshold, event, awfEmit);
4685
+ this._awaitWriteFinish(path7, awf.stabilityThreshold, event, awfEmit);
4725
4686
  return this;
4726
4687
  }
4727
4688
  if (event === EVENTS.CHANGE) {
4728
- const isThrottled = !this._throttle(EVENTS.CHANGE, path9, 50);
4689
+ const isThrottled = !this._throttle(EVENTS.CHANGE, path7, 50);
4729
4690
  if (isThrottled)
4730
4691
  return this;
4731
4692
  }
4732
4693
  if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
4733
- const fullPath = opts.cwd ? sp2.join(opts.cwd, path9) : path9;
4694
+ const fullPath = opts.cwd ? sp2.join(opts.cwd, path7) : path7;
4734
4695
  let stats2;
4735
4696
  try {
4736
4697
  stats2 = await (0, import_promises3.stat)(fullPath);
@@ -4761,23 +4722,23 @@ var FSWatcher = class extends import_node_events.EventEmitter {
4761
4722
  * @param timeout duration of time to suppress duplicate actions
4762
4723
  * @returns tracking object or false if action should be suppressed
4763
4724
  */
4764
- _throttle(actionType, path9, timeout) {
4725
+ _throttle(actionType, path7, timeout) {
4765
4726
  if (!this._throttled.has(actionType)) {
4766
4727
  this._throttled.set(actionType, /* @__PURE__ */ new Map());
4767
4728
  }
4768
4729
  const action = this._throttled.get(actionType);
4769
4730
  if (!action)
4770
4731
  throw new Error("invalid throttle");
4771
- const actionPath = action.get(path9);
4732
+ const actionPath = action.get(path7);
4772
4733
  if (actionPath) {
4773
4734
  actionPath.count++;
4774
4735
  return false;
4775
4736
  }
4776
4737
  let timeoutObject;
4777
4738
  const clear = () => {
4778
- const item = action.get(path9);
4739
+ const item = action.get(path7);
4779
4740
  const count = item ? item.count : 0;
4780
- action.delete(path9);
4741
+ action.delete(path7);
4781
4742
  clearTimeout(timeoutObject);
4782
4743
  if (item)
4783
4744
  clearTimeout(item.timeoutObject);
@@ -4785,7 +4746,7 @@ var FSWatcher = class extends import_node_events.EventEmitter {
4785
4746
  };
4786
4747
  timeoutObject = setTimeout(clear, timeout);
4787
4748
  const thr = { timeoutObject, clear, count: 0 };
4788
- action.set(path9, thr);
4749
+ action.set(path7, thr);
4789
4750
  return thr;
4790
4751
  }
4791
4752
  _incrReadyCount() {
@@ -4799,44 +4760,44 @@ var FSWatcher = class extends import_node_events.EventEmitter {
4799
4760
  * @param event
4800
4761
  * @param awfEmit Callback to be called when ready for event to be emitted.
4801
4762
  */
4802
- _awaitWriteFinish(path9, threshold, event, awfEmit) {
4763
+ _awaitWriteFinish(path7, threshold, event, awfEmit) {
4803
4764
  const awf = this.options.awaitWriteFinish;
4804
4765
  if (typeof awf !== "object")
4805
4766
  return;
4806
4767
  const pollInterval = awf.pollInterval;
4807
4768
  let timeoutHandler;
4808
- let fullPath = path9;
4809
- if (this.options.cwd && !sp2.isAbsolute(path9)) {
4810
- fullPath = sp2.join(this.options.cwd, path9);
4769
+ let fullPath = path7;
4770
+ if (this.options.cwd && !sp2.isAbsolute(path7)) {
4771
+ fullPath = sp2.join(this.options.cwd, path7);
4811
4772
  }
4812
4773
  const now = /* @__PURE__ */ new Date();
4813
4774
  const writes = this._pendingWrites;
4814
4775
  function awaitWriteFinishFn(prevStat) {
4815
4776
  (0, import_node_fs2.stat)(fullPath, (err, curStat) => {
4816
- if (err || !writes.has(path9)) {
4777
+ if (err || !writes.has(path7)) {
4817
4778
  if (err && err.code !== "ENOENT")
4818
4779
  awfEmit(err);
4819
4780
  return;
4820
4781
  }
4821
4782
  const now2 = Number(/* @__PURE__ */ new Date());
4822
4783
  if (prevStat && curStat.size !== prevStat.size) {
4823
- writes.get(path9).lastChange = now2;
4784
+ writes.get(path7).lastChange = now2;
4824
4785
  }
4825
- const pw = writes.get(path9);
4786
+ const pw = writes.get(path7);
4826
4787
  const df = now2 - pw.lastChange;
4827
4788
  if (df >= threshold) {
4828
- writes.delete(path9);
4789
+ writes.delete(path7);
4829
4790
  awfEmit(void 0, curStat);
4830
4791
  } else {
4831
4792
  timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
4832
4793
  }
4833
4794
  });
4834
4795
  }
4835
- if (!writes.has(path9)) {
4836
- writes.set(path9, {
4796
+ if (!writes.has(path7)) {
4797
+ writes.set(path7, {
4837
4798
  lastChange: now,
4838
4799
  cancelWait: () => {
4839
- writes.delete(path9);
4800
+ writes.delete(path7);
4840
4801
  clearTimeout(timeoutHandler);
4841
4802
  return event;
4842
4803
  }
@@ -4847,8 +4808,8 @@ var FSWatcher = class extends import_node_events.EventEmitter {
4847
4808
  /**
4848
4809
  * Determines whether user has asked to ignore this path.
4849
4810
  */
4850
- _isIgnored(path9, stats) {
4851
- if (this.options.atomic && DOT_RE.test(path9))
4811
+ _isIgnored(path7, stats) {
4812
+ if (this.options.atomic && DOT_RE.test(path7))
4852
4813
  return true;
4853
4814
  if (!this._userIgnored) {
4854
4815
  const { cwd } = this.options;
@@ -4858,17 +4819,17 @@ var FSWatcher = class extends import_node_events.EventEmitter {
4858
4819
  const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
4859
4820
  this._userIgnored = anymatch(list, void 0);
4860
4821
  }
4861
- return this._userIgnored(path9, stats);
4822
+ return this._userIgnored(path7, stats);
4862
4823
  }
4863
- _isntIgnored(path9, stat4) {
4864
- return !this._isIgnored(path9, stat4);
4824
+ _isntIgnored(path7, stat4) {
4825
+ return !this._isIgnored(path7, stat4);
4865
4826
  }
4866
4827
  /**
4867
4828
  * Provides a set of common helpers and properties relating to symlink handling.
4868
4829
  * @param path file or directory pattern being watched
4869
4830
  */
4870
- _getWatchHelpers(path9) {
4871
- return new WatchHelper(path9, this.options.followSymlinks, this);
4831
+ _getWatchHelpers(path7) {
4832
+ return new WatchHelper(path7, this.options.followSymlinks, this);
4872
4833
  }
4873
4834
  // Directory helpers
4874
4835
  // -----------------
@@ -4900,63 +4861,63 @@ var FSWatcher = class extends import_node_events.EventEmitter {
4900
4861
  * @param item base path of item/directory
4901
4862
  */
4902
4863
  _remove(directory, item, isDirectory) {
4903
- const path9 = sp2.join(directory, item);
4904
- const fullPath = sp2.resolve(path9);
4905
- isDirectory = isDirectory != null ? isDirectory : this._watched.has(path9) || this._watched.has(fullPath);
4906
- if (!this._throttle("remove", path9, 100))
4864
+ const path7 = sp2.join(directory, item);
4865
+ const fullPath = sp2.resolve(path7);
4866
+ isDirectory = isDirectory != null ? isDirectory : this._watched.has(path7) || this._watched.has(fullPath);
4867
+ if (!this._throttle("remove", path7, 100))
4907
4868
  return;
4908
4869
  if (!isDirectory && this._watched.size === 1) {
4909
4870
  this.add(directory, item, true);
4910
4871
  }
4911
- const wp = this._getWatchedDir(path9);
4872
+ const wp = this._getWatchedDir(path7);
4912
4873
  const nestedDirectoryChildren = wp.getChildren();
4913
- nestedDirectoryChildren.forEach((nested) => this._remove(path9, nested));
4874
+ nestedDirectoryChildren.forEach((nested) => this._remove(path7, nested));
4914
4875
  const parent = this._getWatchedDir(directory);
4915
4876
  const wasTracked = parent.has(item);
4916
4877
  parent.remove(item);
4917
4878
  if (this._symlinkPaths.has(fullPath)) {
4918
4879
  this._symlinkPaths.delete(fullPath);
4919
4880
  }
4920
- let relPath = path9;
4881
+ let relPath = path7;
4921
4882
  if (this.options.cwd)
4922
- relPath = sp2.relative(this.options.cwd, path9);
4883
+ relPath = sp2.relative(this.options.cwd, path7);
4923
4884
  if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
4924
4885
  const event = this._pendingWrites.get(relPath).cancelWait();
4925
4886
  if (event === EVENTS.ADD)
4926
4887
  return;
4927
4888
  }
4928
- this._watched.delete(path9);
4889
+ this._watched.delete(path7);
4929
4890
  this._watched.delete(fullPath);
4930
4891
  const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
4931
- if (wasTracked && !this._isIgnored(path9))
4932
- this._emit(eventName, path9);
4933
- this._closePath(path9);
4892
+ if (wasTracked && !this._isIgnored(path7))
4893
+ this._emit(eventName, path7);
4894
+ this._closePath(path7);
4934
4895
  }
4935
4896
  /**
4936
4897
  * Closes all watchers for a path
4937
4898
  */
4938
- _closePath(path9) {
4939
- this._closeFile(path9);
4940
- const dir = sp2.dirname(path9);
4941
- this._getWatchedDir(dir).remove(sp2.basename(path9));
4899
+ _closePath(path7) {
4900
+ this._closeFile(path7);
4901
+ const dir = sp2.dirname(path7);
4902
+ this._getWatchedDir(dir).remove(sp2.basename(path7));
4942
4903
  }
4943
4904
  /**
4944
4905
  * Closes only file-specific watchers
4945
4906
  */
4946
- _closeFile(path9) {
4947
- const closers = this._closers.get(path9);
4907
+ _closeFile(path7) {
4908
+ const closers = this._closers.get(path7);
4948
4909
  if (!closers)
4949
4910
  return;
4950
4911
  closers.forEach((closer) => closer());
4951
- this._closers.delete(path9);
4912
+ this._closers.delete(path7);
4952
4913
  }
4953
- _addPathCloser(path9, closer) {
4914
+ _addPathCloser(path7, closer) {
4954
4915
  if (!closer)
4955
4916
  return;
4956
- let list = this._closers.get(path9);
4917
+ let list = this._closers.get(path7);
4957
4918
  if (!list) {
4958
4919
  list = [];
4959
- this._closers.set(path9, list);
4920
+ this._closers.set(path7, list);
4960
4921
  }
4961
4922
  list.push(closer);
4962
4923
  }
@@ -4986,7 +4947,7 @@ function watch(paths, options = {}) {
4986
4947
  var chokidar_default = { watch, FSWatcher };
4987
4948
 
4988
4949
  // src/watcher/index.ts
4989
- var path7 = __toESM(require("path"), 1);
4950
+ var path5 = __toESM(require("path"), 1);
4990
4951
  var FileWatcher = class {
4991
4952
  watcher = null;
4992
4953
  projectRoot;
@@ -5007,7 +4968,7 @@ var FileWatcher = class {
5007
4968
  const ignoreFilter = createIgnoreFilter(this.projectRoot);
5008
4969
  this.watcher = chokidar_default.watch(this.projectRoot, {
5009
4970
  ignored: (filePath) => {
5010
- const relativePath = path7.relative(this.projectRoot, filePath);
4971
+ const relativePath = path5.relative(this.projectRoot, filePath);
5011
4972
  if (!relativePath) return false;
5012
4973
  if (ignoreFilter.ignores(relativePath)) {
5013
4974
  return true;
@@ -5051,7 +5012,7 @@ var FileWatcher = class {
5051
5012
  return;
5052
5013
  }
5053
5014
  const changes = Array.from(this.pendingChanges.entries()).map(
5054
- ([path9, type]) => ({ path: path9, type })
5015
+ ([path7, type]) => ({ path: path7, type })
5055
5016
  );
5056
5017
  this.pendingChanges.clear();
5057
5018
  try {
@@ -5243,10 +5204,10 @@ function formatStatus(status) {
5243
5204
 
5244
5205
  // src/index.ts
5245
5206
  function loadPluginConfig(projectRoot) {
5246
- const configPath = path8.join(projectRoot, ".opencode", "codebase-index.json");
5207
+ const configPath = path6.join(projectRoot, ".opencode", "codebase-index.json");
5247
5208
  try {
5248
- if ((0, import_fs6.existsSync)(configPath)) {
5249
- const content = (0, import_fs6.readFileSync)(configPath, "utf-8");
5209
+ if ((0, import_fs4.existsSync)(configPath)) {
5210
+ const content = (0, import_fs4.readFileSync)(configPath, "utf-8");
5250
5211
  return JSON.parse(content);
5251
5212
  }
5252
5213
  } catch {
@@ -5275,6 +5236,39 @@ var plugin = async ({ directory }) => {
5275
5236
  index_codebase,
5276
5237
  index_status,
5277
5238
  index_health_check
5239
+ },
5240
+ async config(cfg) {
5241
+ cfg.command = cfg.command ?? {};
5242
+ cfg.command["search"] = {
5243
+ description: "Search codebase by meaning using semantic search",
5244
+ template: `Use the \`codebase_search\` tool to find code related to: $ARGUMENTS
5245
+
5246
+ If the index doesn't exist yet, run \`index_codebase\` first.
5247
+
5248
+ Return the most relevant results with file paths and line numbers.`
5249
+ };
5250
+ cfg.command["find"] = {
5251
+ description: "Find code using hybrid approach (semantic + grep)",
5252
+ template: `Find code related to: $ARGUMENTS
5253
+
5254
+ Strategy:
5255
+ 1. First use \`codebase_search\` to find semantically related code
5256
+ 2. From the results, identify specific function/class names
5257
+ 3. Use grep to find all occurrences of those identifiers
5258
+ 4. Combine findings into a comprehensive answer
5259
+
5260
+ If the semantic index doesn't exist, run \`index_codebase\` first.`
5261
+ };
5262
+ cfg.command["index"] = {
5263
+ description: "Index the codebase for semantic search",
5264
+ template: `Run the \`index_codebase\` tool to create or update the semantic search index.
5265
+
5266
+ Show progress and final statistics including:
5267
+ - Number of files processed
5268
+ - Number of chunks indexed
5269
+ - Tokens used
5270
+ - Duration`
5271
+ };
5278
5272
  }
5279
5273
  };
5280
5274
  };