opencode-codebase-index 0.22.4 → 0.23.0

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.
@@ -2342,7 +2342,7 @@ function analyzeQueryIntent(query) {
2342
2342
  }
2343
2343
  function isTestPath(filePath) {
2344
2344
  const normalized = normalizePath(filePath);
2345
- return /(?:^|\/)(?:test|tests|__tests__|spec|specs)(?:\/|$)/u.test(normalized) || /\.(?:test|spec)\.[^/]+$/u.test(normalized);
2345
+ return /(?:^|\/)(?:test|tests|__tests__|spec|specs)(?:\/|$)/u.test(normalized) || /(?:\.(?:test|spec)|_(?:test|spec))\.[^/]+$/u.test(normalized) || /(?:^|\/)(?:test|spec)_[^/]+\.[^/]+$/u.test(normalized);
2346
2346
  }
2347
2347
  function isFixturePath(filePath) {
2348
2348
  const normalized = normalizePath(filePath);
@@ -6432,85 +6432,6 @@ function createEmbeddingProvider(configuredProviderInfo) {
6432
6432
  }
6433
6433
  }
6434
6434
 
6435
- // src/rerank/index.ts
6436
- function createReranker(config) {
6437
- if (!config.enabled) {
6438
- return new NoOpReranker();
6439
- }
6440
- return new SiliconFlowReranker(config);
6441
- }
6442
- var NoOpReranker = class {
6443
- isAvailable() {
6444
- return false;
6445
- }
6446
- async rerank(_query, documents, _topN) {
6447
- return {
6448
- results: documents.map((_, index) => ({ index, relevanceScore: 0 }))
6449
- };
6450
- }
6451
- };
6452
- var SiliconFlowReranker = class {
6453
- config;
6454
- constructor(config) {
6455
- this.config = config;
6456
- }
6457
- isAvailable() {
6458
- return this.config.enabled && !!this.config.baseUrl && !!this.config.model;
6459
- }
6460
- async rerank(query, documents, topN) {
6461
- if (documents.length === 0) {
6462
- return { results: [] };
6463
- }
6464
- const headers = {
6465
- "Content-Type": "application/json"
6466
- };
6467
- if (this.config.apiKey) {
6468
- headers["Authorization"] = `Bearer ${this.config.apiKey}`;
6469
- }
6470
- const baseUrl = this.config.baseUrl;
6471
- if (!baseUrl) {
6472
- throw new Error("Reranker baseUrl is required. Configure reranker.baseUrl in your codebase-index.json.");
6473
- }
6474
- const timeoutMs = this.config.timeoutMs ?? 3e4;
6475
- const controller = new AbortController();
6476
- const timeout = setTimeout(() => controller.abort(), timeoutMs);
6477
- try {
6478
- const response = await fetch(`${baseUrl}/rerank`, {
6479
- method: "POST",
6480
- headers,
6481
- body: JSON.stringify({
6482
- model: this.config.model,
6483
- query,
6484
- documents,
6485
- top_n: topN ?? this.config.topN ?? 20,
6486
- return_documents: false
6487
- }),
6488
- signal: controller.signal
6489
- });
6490
- clearTimeout(timeout);
6491
- if (!response.ok) {
6492
- const errorText = await response.text();
6493
- throw new Error(`Rerank API error: ${response.status} - ${errorText}`);
6494
- }
6495
- const data = await response.json();
6496
- return {
6497
- results: data.results.map((r) => ({
6498
- index: r.index,
6499
- relevanceScore: r.relevance_score,
6500
- document: r.document?.text
6501
- })),
6502
- tokensUsed: data.meta?.tokens?.input_tokens
6503
- };
6504
- } catch (error) {
6505
- clearTimeout(timeout);
6506
- if (error instanceof Error && error.name === "AbortError") {
6507
- throw new Error(`Rerank API request timed out after ${timeoutMs}ms`);
6508
- }
6509
- throw error;
6510
- }
6511
- }
6512
- };
6513
-
6514
6435
  // src/utils/logger.ts
6515
6436
  var LOG_LEVEL_PRIORITY = {
6516
6437
  error: 0,
@@ -8625,7 +8546,8 @@ function rankHybridResults(query, semanticResults, keywordResults, options) {
8625
8546
  return cached;
8626
8547
  }
8627
8548
  }
8628
- const overfetchLimit = Math.max(options.limit * 4, options.limit);
8549
+ const overfetchFactor = prioritizeSourcePaths ? 12 : 4;
8550
+ const overfetchLimit = Math.max(options.limit * overfetchFactor, options.limit);
8629
8551
  const fused = options.fusionStrategy === "rrf" ? fuseResultsRrf(semanticResults, keywordResults, options.rrfK, overfetchLimit) : fuseResultsWeighted(semanticResults, keywordResults, options.hybridWeight, overfetchLimit);
8630
8552
  const rerankPoolLimit = Math.max(overfetchLimit, options.rerankTopN * 3, options.limit * 6);
8631
8553
  const rerankPool = fused.slice(0, rerankPoolLimit);
@@ -9011,6 +8933,29 @@ function extractPrimaryIdentifierQueryHint(query) {
9011
8933
  const best = codeTerms.find((term) => term.length >= 6);
9012
8934
  return best ?? null;
9013
8935
  }
8936
+ function pathSegmentsForAffinityMatch(filePath) {
8937
+ const normalizedPath2 = normalizeRankingText(filePath).replace(/\\/g, "/");
8938
+ const segments = normalizedPath2.split("/").filter((segment) => segment.length > 0);
8939
+ if (segments.length === 0) {
8940
+ return [];
8941
+ }
8942
+ const basename5 = segments[segments.length - 1] ?? "";
8943
+ const basenameWithoutExt = basename5.replace(/\.[^/.]+$/u, "");
8944
+ const normalizedSegments = segments.map((segment) => segment.toLowerCase());
8945
+ return Array.from(/* @__PURE__ */ new Set([
8946
+ ...normalizedSegments,
8947
+ basenameWithoutExt.toLowerCase()
8948
+ ]));
8949
+ }
8950
+ function hasModuleAffinity(filePath, exactIdentifierVariants) {
8951
+ const haystack = pathSegmentsForAffinityMatch(filePath);
8952
+ return exactIdentifierVariants.some((variant) => {
8953
+ if (!variant || variant.length < 2) {
8954
+ return false;
8955
+ }
8956
+ return haystack.includes(variant);
8957
+ });
8958
+ }
9014
8959
  var FILE_PATH_HINT_EXTENSIONS = [
9015
8960
  "ts",
9016
8961
  "tsx",
@@ -9086,10 +9031,13 @@ function buildDeterministicIdentifierPass(query, candidates, limit, prioritizeSo
9086
9031
  ).map((candidate) => {
9087
9032
  const nameLower = (candidate.metadata.name ?? "").toLowerCase();
9088
9033
  const pathLower = candidate.metadata.filePath.toLowerCase();
9089
- let maxMatch = 0;
9090
- const nameMatchesPrimary = primaryVariants.some(
9034
+ const exactIdentifierVariants = primaryVariants.filter((value) => value.length >= 2);
9035
+ const exactMatch = exactIdentifierVariants.some(
9091
9036
  (variant) => nameLower === variant || nameLower.replace(/[^a-z0-9]/g, "") === variant.replace(/[^a-z0-9]/g, "")
9092
9037
  );
9038
+ let maxMatch = 0;
9039
+ const nameMatchesPrimary = exactMatch;
9040
+ const pathAffinity = exactMatch ? hasModuleAffinity(candidate.metadata.filePath, exactIdentifierVariants) : false;
9093
9041
  const pathMatchesFileHint = filePathHint ? pathMatchesHint(candidate.metadata.filePath, filePathHint) : false;
9094
9042
  for (const hint of hints) {
9095
9043
  const variants = normalizeIdentifierVariants(hint);
@@ -9110,12 +9058,17 @@ function buildDeterministicIdentifierPass(query, candidates, limit, prioritizeSo
9110
9058
  candidate,
9111
9059
  maxMatch,
9112
9060
  pathMatchesFileHint,
9113
- nameMatchesPrimary
9061
+ nameMatchesPrimary,
9062
+ pathAffinity
9114
9063
  };
9115
9064
  }).filter((entry) => entry.maxMatch >= 0.7).sort((a, b) => {
9116
9065
  const aAnchored = a.pathMatchesFileHint && a.nameMatchesPrimary ? 1 : 0;
9117
9066
  const bAnchored = b.pathMatchesFileHint && b.nameMatchesPrimary ? 1 : 0;
9118
9067
  if (aAnchored !== bAnchored) return bAnchored - aAnchored;
9068
+ if (a.nameMatchesPrimary !== b.nameMatchesPrimary) {
9069
+ return b.nameMatchesPrimary ? 1 : -1;
9070
+ }
9071
+ if (a.pathAffinity !== b.pathAffinity) return b.pathAffinity ? 1 : -1;
9119
9072
  if (b.maxMatch !== a.maxMatch) return b.maxMatch - a.maxMatch;
9120
9073
  if (b.candidate.score !== a.candidate.score) return b.candidate.score - a.candidate.score;
9121
9074
  return a.candidate.id.localeCompare(b.candidate.id);
@@ -10105,7 +10058,6 @@ var Indexer = class _Indexer {
10105
10058
  database = null;
10106
10059
  provider = null;
10107
10060
  configuredProviderInfo = null;
10108
- reranker = null;
10109
10061
  fileHashCache = /* @__PURE__ */ new Map();
10110
10062
  fileHashCachePath = "";
10111
10063
  failedBatchesPath = "";
@@ -10265,7 +10217,6 @@ var Indexer = class _Indexer {
10265
10217
  this.database = null;
10266
10218
  this.provider = null;
10267
10219
  this.configuredProviderInfo = null;
10268
- this.reranker = null;
10269
10220
  this.indexCompatibility = null;
10270
10221
  this.initializationMode = "none";
10271
10222
  this.readIssues = [];
@@ -11562,15 +11513,6 @@ var Indexer = class _Indexer {
11562
11513
  rerankerEnabled: this.config.reranker?.enabled ?? false
11563
11514
  });
11564
11515
  this.provider = createEmbeddingProvider(this.configuredProviderInfo);
11565
- if (this.config.reranker?.enabled) {
11566
- this.reranker = createReranker(this.config.reranker);
11567
- if (this.reranker.isAvailable()) {
11568
- this.logger.info("Reranker initialized", {
11569
- model: this.config.reranker.model,
11570
- baseUrl: this.config.reranker.baseUrl
11571
- });
11572
- }
11573
- }
11574
11516
  const dimensions = this.configuredProviderInfo.modelInfo.dimensions;
11575
11517
  const storePath = path19.join(this.indexPath, "vectors");
11576
11518
  const vectorMetadataPath = `${storePath}.meta.json`;
@@ -12975,6 +12917,7 @@ var Indexer = class _Indexer {
12975
12917
  const filterByBranch = options?.filterByBranch ?? true;
12976
12918
  const sourceIntent = options?.definitionIntent === true || classifyQueryIntentRaw(query) === "source";
12977
12919
  const identifierHints = extractIdentifierHints(query);
12920
+ const candidateLimit = maxResults * (sourceIntent ? 12 : 4);
12978
12921
  this.logger.search("debug", "Starting search", {
12979
12922
  query,
12980
12923
  maxResults,
@@ -13011,7 +12954,7 @@ var Indexer = class _Indexer {
13011
12954
  const semanticCandidates = embedding ? this.searchSemanticCandidates(
13012
12955
  store,
13013
12956
  embedding,
13014
- maxResults * 4,
12957
+ candidateLimit,
13015
12958
  branchChunkIds,
13016
12959
  shouldPrefilterByBranch
13017
12960
  ) : [];
@@ -13019,7 +12962,7 @@ var Indexer = class _Indexer {
13019
12962
  const keywordStartTime = import_perf_hooks.performance.now();
13020
12963
  const keywordCandidates = await this.keywordSearch(
13021
12964
  query,
13022
- maxResults * 4,
12965
+ candidateLimit,
13023
12966
  store,
13024
12967
  invertedIndex,
13025
12968
  branchChunkIds,
@@ -14181,7 +14124,6 @@ var Indexer = class _Indexer {
14181
14124
  this.store = null;
14182
14125
  this.invertedIndex = null;
14183
14126
  this.provider = null;
14184
- this.reranker = null;
14185
14127
  this.configuredProviderInfo = null;
14186
14128
  this.indexCompatibility = null;
14187
14129
  this.initializationMode = "none";