sweet-search 0.0.1 → 2.3.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.
- package/LICENSE +190 -0
- package/NOTICE +23 -0
- package/core/cli.js +51 -0
- package/core/config.js +27 -0
- package/core/embedding/embedding-cache.js +467 -0
- package/core/embedding/embedding-local-model.js +845 -0
- package/core/embedding/embedding-remote.js +492 -0
- package/core/embedding/embedding-service.js +712 -0
- package/core/embedding/embedding-telemetry.js +219 -0
- package/core/embedding/index.js +40 -0
- package/core/graph/community-detector.js +294 -0
- package/core/graph/graph-expansion.js +839 -0
- package/core/graph/graph-extractor.js +2304 -0
- package/core/graph/graph-search.js +2148 -0
- package/core/graph/hcgs-generator.js +666 -0
- package/core/graph/index.js +16 -0
- package/core/graph/leiden-algorithm.js +547 -0
- package/core/graph/relationship-resolver.js +366 -0
- package/core/graph/repo-map.js +408 -0
- package/core/graph/summary-manager.js +549 -0
- package/core/indexing/artifact-builder.js +1054 -0
- package/core/indexing/ast-chunker.js +709 -0
- package/core/indexing/chunking/chunk-builder.js +170 -0
- package/core/indexing/chunking/markdown-chunker.js +503 -0
- package/core/indexing/chunking/plaintext-chunker.js +104 -0
- package/core/indexing/dedup/dedup-phase.js +159 -0
- package/core/indexing/dedup/exemplar-selector.js +65 -0
- package/core/indexing/document-chunker.js +56 -0
- package/core/indexing/incremental-parser.js +390 -0
- package/core/indexing/incremental-tracker.js +761 -0
- package/core/indexing/index-codebase-v21.js +472 -0
- package/core/indexing/index-maintainer.mjs +1674 -0
- package/core/indexing/index.js +90 -0
- package/core/indexing/indexer-ann.js +1077 -0
- package/core/indexing/indexer-build.js +742 -0
- package/core/indexing/indexer-phases.js +800 -0
- package/core/indexing/indexer-pool.js +764 -0
- package/core/indexing/indexer-sparse-gram.js +98 -0
- package/core/indexing/indexer-utils.js +536 -0
- package/core/indexing/indexer-worker.js +148 -0
- package/core/indexing/li-skip-policy.js +225 -0
- package/core/indexing/merkle-tracker.js +244 -0
- package/core/indexing/model-pool.js +166 -0
- package/core/infrastructure/code-graph-repository.js +120 -0
- package/core/infrastructure/codebase-repository.js +131 -0
- package/core/infrastructure/config/dedup.js +54 -0
- package/core/infrastructure/config/embedding.js +298 -0
- package/core/infrastructure/config/graph.js +80 -0
- package/core/infrastructure/config/index.js +82 -0
- package/core/infrastructure/config/indexing.js +8 -0
- package/core/infrastructure/config/platform.js +254 -0
- package/core/infrastructure/config/ranking.js +221 -0
- package/core/infrastructure/config/search.js +396 -0
- package/core/infrastructure/config/translation.js +89 -0
- package/core/infrastructure/config/vector-store.js +114 -0
- package/core/infrastructure/constants.js +86 -0
- package/core/infrastructure/coreml-cascade.js +909 -0
- package/core/infrastructure/coreml-cascade.json +46 -0
- package/core/infrastructure/coreml-provider.js +81 -0
- package/core/infrastructure/db-utils.js +69 -0
- package/core/infrastructure/dedup-hashing.js +83 -0
- package/core/infrastructure/hardware-capability.js +332 -0
- package/core/infrastructure/index.js +104 -0
- package/core/infrastructure/language-patterns/maps.js +121 -0
- package/core/infrastructure/language-patterns/registry-core.js +323 -0
- package/core/infrastructure/language-patterns/registry-data-query.js +155 -0
- package/core/infrastructure/language-patterns/registry-object-oriented.js +285 -0
- package/core/infrastructure/language-patterns/registry-tooling.js +240 -0
- package/core/infrastructure/language-patterns/registry-web-style.js +143 -0
- package/core/infrastructure/language-patterns/registry.js +19 -0
- package/core/infrastructure/language-patterns.js +141 -0
- package/core/infrastructure/llm-provider.js +733 -0
- package/core/infrastructure/manifest.json +46 -0
- package/core/infrastructure/maxsim.wasm +0 -0
- package/core/infrastructure/model-fetcher.js +423 -0
- package/core/infrastructure/model-registry.js +214 -0
- package/core/infrastructure/native-inference.js +587 -0
- package/core/infrastructure/native-resolver.js +187 -0
- package/core/infrastructure/native-sparse-gram.js +257 -0
- package/core/infrastructure/native-tokenizer.js +160 -0
- package/core/infrastructure/onnx-mutex.js +45 -0
- package/core/infrastructure/onnx-session-utils.js +261 -0
- package/core/infrastructure/ort-pipeline.js +111 -0
- package/core/infrastructure/project-detector.js +102 -0
- package/core/infrastructure/quantization.js +410 -0
- package/core/infrastructure/simd-distance.js +502 -0
- package/core/infrastructure/simd-distance.wasm +0 -0
- package/core/infrastructure/tree-sitter-provider.js +665 -0
- package/core/infrastructure/webgpu-maxsim.js +222 -0
- package/core/query/index.js +35 -0
- package/core/query/intent-detector.js +201 -0
- package/core/query/intent-router.js +156 -0
- package/core/query/query-router-catboost.js +222 -0
- package/core/query/query-router-ml.js +266 -0
- package/core/query/query-router.js +213 -0
- package/core/ranking/cascaded-scorer.js +379 -0
- package/core/ranking/flashrank.js +810 -0
- package/core/ranking/index.js +49 -0
- package/core/ranking/late-interaction-index.js +2383 -0
- package/core/ranking/late-interaction-model.js +812 -0
- package/core/ranking/local-reranker.js +374 -0
- package/core/ranking/mmr.js +379 -0
- package/core/ranking/quality-scorer.js +363 -0
- package/core/search/context-expander.js +1167 -0
- package/core/search/dedup/sibling-expander.js +327 -0
- package/core/search/index.js +16 -0
- package/core/search/search-boost.js +259 -0
- package/core/search/search-cli.js +544 -0
- package/core/search/search-format.js +282 -0
- package/core/search/search-fusion.js +327 -0
- package/core/search/search-hybrid.js +204 -0
- package/core/search/search-pattern-chunks.js +337 -0
- package/core/search/search-pattern-planner.js +439 -0
- package/core/search/search-pattern-prefilter.js +412 -0
- package/core/search/search-pattern-ripgrep.js +663 -0
- package/core/search/search-pattern.js +463 -0
- package/core/search/search-postprocess.js +452 -0
- package/core/search/search-semantic.js +706 -0
- package/core/search/search-server.js +554 -0
- package/core/search/session-daemon-prewarm.mjs +164 -0
- package/core/search/session-warmup.js +595 -0
- package/core/search/sweet-search.js +632 -0
- package/core/search/warmup-metrics.js +532 -0
- package/core/start-server.js +6 -0
- package/core/training/query-router/features/extractor.js +762 -0
- package/core/training/query-router/features/multilingual-patterns.js +431 -0
- package/core/training/query-router/features/text-segmenter.js +303 -0
- package/core/training/query-router/features/unicode-utils.js +383 -0
- package/core/training/query-router/output/v45_router_d4.js +11521 -0
- package/core/training/query-router/output/v46_router_d4.js +11498 -0
- package/core/vector-store/binary-heap.js +227 -0
- package/core/vector-store/binary-hnsw-index.js +1004 -0
- package/core/vector-store/float-vector-store.js +234 -0
- package/core/vector-store/hnsw-index.js +580 -0
- package/core/vector-store/index.js +39 -0
- package/core/vector-store/seismic-index.js +498 -0
- package/core/vocabulary/index.js +84 -0
- package/core/vocabulary/vocab-constants.js +20 -0
- package/core/vocabulary/vocab-miner-extractors.js +375 -0
- package/core/vocabulary/vocab-miner-nl.js +404 -0
- package/core/vocabulary/vocab-miner-utils.js +146 -0
- package/core/vocabulary/vocab-miner.js +574 -0
- package/core/vocabulary/vocab-prewarm-cli.js +110 -0
- package/core/vocabulary/vocab-ranker.js +492 -0
- package/core/vocabulary/vocab-warmer.js +523 -0
- package/core/vocabulary/vocab-warmup-orchestrator.js +425 -0
- package/core/vocabulary/vocabulary-utils.js +704 -0
- package/crates/wasm-router/pkg/package.json +13 -0
- package/crates/wasm-router/pkg/query_router_wasm.d.ts +36 -0
- package/crates/wasm-router/pkg/query_router_wasm.js +271 -0
- package/crates/wasm-router/pkg/query_router_wasm_bg.wasm +0 -0
- package/crates/wasm-router/pkg/query_router_wasm_bg.wasm.d.ts +19 -0
- package/mcp/config-gen.js +121 -0
- package/mcp/server.js +335 -0
- package/mcp/tool-handlers.js +476 -0
- package/package.json +131 -9
- package/scripts/benchmark-harness.js +794 -0
- package/scripts/init.js +1058 -0
- package/scripts/smoke-test.js +435 -0
- package/scripts/uninstall.js +478 -0
- package/scripts/verify-runtime.js +176 -0
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regex Prefiltering Module — literal extraction and sparse gram candidate lookup.
|
|
3
|
+
*
|
|
4
|
+
* Extracts required literal substrings from regex patterns, then uses either
|
|
5
|
+
* ripgrep fixed-string prefiltering or the sparse trigram index to narrow the
|
|
6
|
+
* file set before the full regex scan. Keeps the hot-path fast by skipping
|
|
7
|
+
* files that cannot possibly match.
|
|
8
|
+
*
|
|
9
|
+
* Split from search-pattern.js for the 500-line-limit rule.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import {
|
|
13
|
+
extractRegexLiteralClauses,
|
|
14
|
+
loadSparseGramIndex,
|
|
15
|
+
resolveSparseSymbolMask as _resolveSparseSymbolMask,
|
|
16
|
+
nativeGrepFilesWithMatches as _nativeGrepFilesWithMatches,
|
|
17
|
+
nativeGrepFilesWithMatchesFixed as _nativeGrepFilesWithMatchesFixed,
|
|
18
|
+
nativeGrepLines as _nativeGrepLines,
|
|
19
|
+
nativeGrepFull as _nativeGrepFull,
|
|
20
|
+
getSparseGramAllFiles as _getSparseGramAllFiles,
|
|
21
|
+
queryAndGrepLines as _queryAndGrepLines,
|
|
22
|
+
queryAndGrepFull as _queryAndGrepFull,
|
|
23
|
+
searchLines as _searchLines,
|
|
24
|
+
searchFull as _searchFull,
|
|
25
|
+
} from '../infrastructure/native-sparse-gram.js';
|
|
26
|
+
|
|
27
|
+
// Re-export for search-pattern.js (avoids circular import through native-sparse-gram.js)
|
|
28
|
+
export const resolveSparseSymbolMask = _resolveSparseSymbolMask;
|
|
29
|
+
export const nativeGrepFilesWithMatches = _nativeGrepFilesWithMatches;
|
|
30
|
+
export const nativeGrepFilesWithMatchesFixed = _nativeGrepFilesWithMatchesFixed;
|
|
31
|
+
export const nativeGrepLines = _nativeGrepLines;
|
|
32
|
+
export const nativeGrepFull = _nativeGrepFull;
|
|
33
|
+
export const getSparseGramAllFiles = _getSparseGramAllFiles;
|
|
34
|
+
export const queryAndGrepLines = _queryAndGrepLines;
|
|
35
|
+
export const queryAndGrepFull = _queryAndGrepFull;
|
|
36
|
+
export const searchLines = _searchLines;
|
|
37
|
+
export const searchFull = _searchFull;
|
|
38
|
+
import { DB_PATHS, PROJECT_ROOT } from '../infrastructure/config/index.js';
|
|
39
|
+
import { CODE_FILE_EXTENSIONS } from '../infrastructure/constants.js';
|
|
40
|
+
import { isRipgrepCodePath, resolveSearchSymbolFilter } from './search-pattern-chunks.js';
|
|
41
|
+
|
|
42
|
+
// =============================================================================
|
|
43
|
+
// Case-insensitive flag detection
|
|
44
|
+
// =============================================================================
|
|
45
|
+
|
|
46
|
+
export function hasCaseInsensitiveRegexFlag(regex) {
|
|
47
|
+
return /\(\?[a-z-]*i[a-z-]*:?/.test(regex);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// =============================================================================
|
|
51
|
+
// Literal extraction from regex patterns
|
|
52
|
+
// =============================================================================
|
|
53
|
+
|
|
54
|
+
export function extractRequiredLiteralsHeuristic(regex) {
|
|
55
|
+
if (!regex || typeof regex !== 'string') return [];
|
|
56
|
+
|
|
57
|
+
let inClass = false;
|
|
58
|
+
let escape = false;
|
|
59
|
+
let current = '';
|
|
60
|
+
const literals = [];
|
|
61
|
+
|
|
62
|
+
const pushCurrent = () => {
|
|
63
|
+
if (current.length >= 3) literals.push(current);
|
|
64
|
+
current = '';
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
for (const char of regex) {
|
|
68
|
+
if (escape) {
|
|
69
|
+
if (/[\w/-]/.test(char)) {
|
|
70
|
+
current += char;
|
|
71
|
+
} else {
|
|
72
|
+
pushCurrent();
|
|
73
|
+
}
|
|
74
|
+
escape = false;
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (char === '\\') {
|
|
79
|
+
pushCurrent();
|
|
80
|
+
escape = true;
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (inClass) {
|
|
85
|
+
if (char === ']') inClass = false;
|
|
86
|
+
pushCurrent();
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (char === '[') {
|
|
91
|
+
inClass = true;
|
|
92
|
+
pushCurrent();
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (char === '|') {
|
|
97
|
+
// Alternation means neither side is universally required.
|
|
98
|
+
// Return empty to avoid false negatives — a prefilter using
|
|
99
|
+
// literals from one branch would exclude files matching the other.
|
|
100
|
+
return [];
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (/[.*+?^${}()]/.test(char)) {
|
|
104
|
+
pushCurrent();
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (/\s/.test(char)) {
|
|
109
|
+
pushCurrent();
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
current += char;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
pushCurrent();
|
|
117
|
+
|
|
118
|
+
return [...new Set(literals)];
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export function extractLiteralClausesHeuristic(regex) {
|
|
122
|
+
const literals = extractRequiredLiteralsHeuristic(regex);
|
|
123
|
+
return literals.length > 0 ? [literals] : [];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export function normalizeLiteralClauses(clauses) {
|
|
127
|
+
if (!Array.isArray(clauses)) return [];
|
|
128
|
+
|
|
129
|
+
const normalized = [];
|
|
130
|
+
for (const clause of clauses) {
|
|
131
|
+
if (!Array.isArray(clause)) continue;
|
|
132
|
+
const deduped = [];
|
|
133
|
+
for (const literal of clause) {
|
|
134
|
+
if (typeof literal !== 'string') continue;
|
|
135
|
+
const trimmed = literal.trim();
|
|
136
|
+
if (trimmed.length < 3 || deduped.includes(trimmed)) continue;
|
|
137
|
+
deduped.push(trimmed);
|
|
138
|
+
}
|
|
139
|
+
if (deduped.length === 0) continue;
|
|
140
|
+
if (!normalized.some(existing => existing.length === deduped.length && existing.every((value, idx) => value === deduped[idx]))) {
|
|
141
|
+
normalized.push(deduped);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return normalized;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export function extractLiteralClauses(regex, options = {}) {
|
|
149
|
+
if (!regex || typeof regex !== 'string') {
|
|
150
|
+
return { clauses: [], source: 'none' };
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (!options.forceHeuristic) {
|
|
154
|
+
try {
|
|
155
|
+
const nativeResult = extractRegexLiteralClauses(regex);
|
|
156
|
+
const nativeClauses = normalizeLiteralClauses(nativeResult?.clauses);
|
|
157
|
+
if (nativeClauses.length > 0) {
|
|
158
|
+
return { clauses: nativeClauses, source: 'native' };
|
|
159
|
+
}
|
|
160
|
+
} catch {
|
|
161
|
+
// Fall back to heuristic extraction below.
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const heuristicClauses = extractLiteralClausesHeuristic(regex);
|
|
166
|
+
if (heuristicClauses.length > 0) {
|
|
167
|
+
return { clauses: heuristicClauses, source: 'heuristic' };
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return { clauses: [], source: 'none' };
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// =============================================================================
|
|
174
|
+
// Literal prefiltering via ripgrep fixed-string mode
|
|
175
|
+
// =============================================================================
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Run literal prefilter for a single AND-clause of literals.
|
|
179
|
+
*
|
|
180
|
+
* Accepts `rgFunctions` to avoid a circular import with search-pattern.js.
|
|
181
|
+
* The caller (generateRegexMatches) passes { getRgCapabilities, runRipgrepFilesWithMatches }.
|
|
182
|
+
*/
|
|
183
|
+
async function runLiteralPrefilter(literals, searchDir, files, opts, rgFunctions) {
|
|
184
|
+
if (!Array.isArray(literals) || literals.length === 0) {
|
|
185
|
+
return Array.isArray(files) ? [...files] : null;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const caseInsensitive = opts.caseInsensitive ?? false;
|
|
189
|
+
const timeout = opts.timeout ?? 10000;
|
|
190
|
+
const globs = opts.globs ?? [];
|
|
191
|
+
const { supportsAnd } = rgFunctions.getRgCapabilities();
|
|
192
|
+
|
|
193
|
+
if (supportsAnd && literals.length > 1) {
|
|
194
|
+
return rgFunctions.runRipgrepFilesWithMatches(literals, searchDir, {
|
|
195
|
+
files,
|
|
196
|
+
fixedString: true,
|
|
197
|
+
caseInsensitive,
|
|
198
|
+
globs,
|
|
199
|
+
timeout,
|
|
200
|
+
useAnd: true,
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
let currentFiles = files;
|
|
205
|
+
for (const literal of literals) {
|
|
206
|
+
currentFiles = await rgFunctions.runRipgrepFilesWithMatches(literal, searchDir, {
|
|
207
|
+
files: currentFiles,
|
|
208
|
+
fixedString: true,
|
|
209
|
+
caseInsensitive,
|
|
210
|
+
globs,
|
|
211
|
+
timeout,
|
|
212
|
+
});
|
|
213
|
+
if (Array.isArray(currentFiles) && currentFiles.length === 0) {
|
|
214
|
+
break;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return currentFiles;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Run literal prefilter across OR-clauses (each clause is an AND-set of literals).
|
|
223
|
+
*
|
|
224
|
+
* Accepts `rgFunctions` to avoid a circular import with search-pattern.js.
|
|
225
|
+
*/
|
|
226
|
+
export async function runLiteralPrefilterClauses(clauses, searchDir, files = null, opts = {}, rgFunctions = {}) {
|
|
227
|
+
if (!Array.isArray(clauses) || clauses.length === 0) {
|
|
228
|
+
return Array.isArray(files) ? [...files] : null;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const combined = new Set();
|
|
232
|
+
for (const clause of clauses) {
|
|
233
|
+
if (!Array.isArray(clause) || clause.length === 0) {
|
|
234
|
+
return Array.isArray(files) ? [...files] : null;
|
|
235
|
+
}
|
|
236
|
+
const clauseMatches = await runLiteralPrefilter(clause, searchDir, files, opts, rgFunctions);
|
|
237
|
+
if (!Array.isArray(clauseMatches)) {
|
|
238
|
+
return null;
|
|
239
|
+
}
|
|
240
|
+
for (const file of clauseMatches) combined.add(file);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return [...combined];
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// =============================================================================
|
|
247
|
+
// Sparse gram index candidate lookup
|
|
248
|
+
// =============================================================================
|
|
249
|
+
|
|
250
|
+
export function ensureSparseGramIndex(searcher, options = {}) {
|
|
251
|
+
if (!searcher) return null;
|
|
252
|
+
const useGramIndex = options.useGramIndex ?? options.gramIndex ?? true;
|
|
253
|
+
if (!useGramIndex) return null;
|
|
254
|
+
if (searcher.sparseGramIndex) return searcher.sparseGramIndex;
|
|
255
|
+
|
|
256
|
+
const indexPath = options.sparseGramIndexPath || searcher.sparseGramIndexPath || DB_PATHS.sparseGramIndex;
|
|
257
|
+
const loaded = loadSparseGramIndex(indexPath);
|
|
258
|
+
if (loaded) {
|
|
259
|
+
searcher.sparseGramIndex = loaded;
|
|
260
|
+
}
|
|
261
|
+
return loaded;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
export function querySparseGramCandidates(searcher, literalClauses, options = {}) {
|
|
265
|
+
const useGramIndex = options.useGramIndex ?? options.gramIndex ?? true;
|
|
266
|
+
if (!useGramIndex) {
|
|
267
|
+
return {
|
|
268
|
+
eligible: false,
|
|
269
|
+
reason: 'disabled',
|
|
270
|
+
totalFiles: 0,
|
|
271
|
+
gramsUsed: 0,
|
|
272
|
+
denseGramsTouched: 0,
|
|
273
|
+
sparseGramsTouched: 0,
|
|
274
|
+
candidateFiles: 0,
|
|
275
|
+
files: null,
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
if (!Array.isArray(literalClauses) || literalClauses.length === 0) {
|
|
279
|
+
return {
|
|
280
|
+
eligible: false,
|
|
281
|
+
reason: 'not_eligible',
|
|
282
|
+
totalFiles: 0,
|
|
283
|
+
gramsUsed: 0,
|
|
284
|
+
denseGramsTouched: 0,
|
|
285
|
+
sparseGramsTouched: 0,
|
|
286
|
+
candidateFiles: 0,
|
|
287
|
+
files: null,
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
try {
|
|
292
|
+
const sparseGramIndex = ensureSparseGramIndex(searcher, options);
|
|
293
|
+
if (!sparseGramIndex) {
|
|
294
|
+
return {
|
|
295
|
+
eligible: false,
|
|
296
|
+
reason: 'not_loaded',
|
|
297
|
+
totalFiles: 0,
|
|
298
|
+
gramsUsed: 0,
|
|
299
|
+
denseGramsTouched: 0,
|
|
300
|
+
sparseGramsTouched: 0,
|
|
301
|
+
candidateFiles: 0,
|
|
302
|
+
files: null,
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
const maxCandidateFiles = options.maxGramCandidateFiles ?? 100000;
|
|
307
|
+
const maxCandidateRatio = options.maxGramCandidateRatio ?? 1.0;
|
|
308
|
+
const symbolMask = _resolveSparseSymbolMask(resolveSearchSymbolFilter(options));
|
|
309
|
+
const combined = new Set();
|
|
310
|
+
let totalFiles = 0;
|
|
311
|
+
let gramsUsed = 0;
|
|
312
|
+
let denseGramsTouched = 0;
|
|
313
|
+
let sparseGramsTouched = 0;
|
|
314
|
+
|
|
315
|
+
for (const clause of literalClauses) {
|
|
316
|
+
if (!Array.isArray(clause) || clause.length === 0) {
|
|
317
|
+
return {
|
|
318
|
+
eligible: false,
|
|
319
|
+
reason: 'not_eligible',
|
|
320
|
+
totalFiles,
|
|
321
|
+
gramsUsed,
|
|
322
|
+
denseGramsTouched,
|
|
323
|
+
sparseGramsTouched,
|
|
324
|
+
candidateFiles: 0,
|
|
325
|
+
files: null,
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
const result = sparseGramIndex.queryLiterals(
|
|
329
|
+
clause,
|
|
330
|
+
options.maxGramCandidates ?? 0,
|
|
331
|
+
symbolMask || 0
|
|
332
|
+
);
|
|
333
|
+
if (!result?.eligible) {
|
|
334
|
+
return {
|
|
335
|
+
eligible: false,
|
|
336
|
+
reason: 'not_eligible',
|
|
337
|
+
totalFiles: Math.max(totalFiles, result?.totalFiles || 0),
|
|
338
|
+
gramsUsed: gramsUsed + (result?.gramsUsed || 0),
|
|
339
|
+
denseGramsTouched: denseGramsTouched + (result?.denseGramsTouched || 0),
|
|
340
|
+
sparseGramsTouched: sparseGramsTouched + (result?.sparseGramsTouched || 0),
|
|
341
|
+
candidateFiles: Array.isArray(result?.files) ? result.files.length : 0,
|
|
342
|
+
files: null,
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
totalFiles = Math.max(totalFiles, result.totalFiles || 0);
|
|
346
|
+
gramsUsed += result.gramsUsed || 0;
|
|
347
|
+
denseGramsTouched += result.denseGramsTouched || 0;
|
|
348
|
+
sparseGramsTouched += result.sparseGramsTouched || 0;
|
|
349
|
+
const clauseFiles = Array.isArray(result.files)
|
|
350
|
+
? result.files.filter(isRipgrepCodePath)
|
|
351
|
+
: [];
|
|
352
|
+
if (
|
|
353
|
+
clauseFiles.length === 0 ||
|
|
354
|
+
clauseFiles.length > maxCandidateFiles ||
|
|
355
|
+
(result.totalFiles > 0 && (clauseFiles.length / result.totalFiles) > maxCandidateRatio)
|
|
356
|
+
) {
|
|
357
|
+
return {
|
|
358
|
+
eligible: false,
|
|
359
|
+
reason: 'too_broad',
|
|
360
|
+
totalFiles,
|
|
361
|
+
gramsUsed,
|
|
362
|
+
denseGramsTouched,
|
|
363
|
+
sparseGramsTouched,
|
|
364
|
+
candidateFiles: clauseFiles.length,
|
|
365
|
+
files: null,
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
for (const file of clauseFiles) combined.add(file);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
const files = [...combined];
|
|
372
|
+
if (
|
|
373
|
+
files.length === 0 ||
|
|
374
|
+
files.length > maxCandidateFiles ||
|
|
375
|
+
(totalFiles > 0 && (files.length / totalFiles) > maxCandidateRatio)
|
|
376
|
+
) {
|
|
377
|
+
return {
|
|
378
|
+
eligible: false,
|
|
379
|
+
reason: 'too_broad',
|
|
380
|
+
totalFiles,
|
|
381
|
+
gramsUsed,
|
|
382
|
+
denseGramsTouched,
|
|
383
|
+
sparseGramsTouched,
|
|
384
|
+
candidateFiles: files.length,
|
|
385
|
+
files: null,
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
return {
|
|
390
|
+
eligible: true,
|
|
391
|
+
reason: 'ok',
|
|
392
|
+
totalFiles,
|
|
393
|
+
gramsUsed,
|
|
394
|
+
denseGramsTouched,
|
|
395
|
+
sparseGramsTouched,
|
|
396
|
+
candidateFiles: files.length,
|
|
397
|
+
files,
|
|
398
|
+
};
|
|
399
|
+
} catch {
|
|
400
|
+
return {
|
|
401
|
+
eligible: false,
|
|
402
|
+
reason: 'error',
|
|
403
|
+
totalFiles: 0,
|
|
404
|
+
gramsUsed: 0,
|
|
405
|
+
denseGramsTouched: 0,
|
|
406
|
+
sparseGramsTouched: 0,
|
|
407
|
+
candidateFiles: 0,
|
|
408
|
+
files: null,
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|