raggrep 0.6.1 → 0.7.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/README.md +2 -0
- package/dist/cli/main.js +670 -123
- package/dist/cli/main.js.map +11 -7
- package/dist/domain/entities/index.d.ts +2 -0
- package/dist/domain/entities/literal.d.ts +101 -0
- package/dist/domain/services/index.d.ts +3 -0
- package/dist/domain/services/literalExtractor.d.ts +35 -0
- package/dist/domain/services/literalScorer.d.ts +93 -0
- package/dist/domain/services/queryLiteralParser.d.ts +20 -0
- package/dist/domain/services/queryLiteralParser.test.d.ts +7 -0
- package/dist/index.js +665 -118
- package/dist/index.js.map +11 -7
- package/dist/infrastructure/storage/index.d.ts +1 -0
- package/dist/infrastructure/storage/literalIndex.d.ts +103 -0
- package/dist/modules/language/typescript/index.d.ts +8 -4
- package/package.json +1 -1
package/dist/cli/main.js
CHANGED
|
@@ -430,10 +430,14 @@ var init_config = __esm(() => {
|
|
|
430
430
|
];
|
|
431
431
|
});
|
|
432
432
|
|
|
433
|
+
// src/domain/entities/literal.ts
|
|
434
|
+
var init_literal = () => {};
|
|
435
|
+
|
|
433
436
|
// src/domain/entities/index.ts
|
|
434
437
|
var init_entities = __esm(() => {
|
|
435
438
|
init_searchResult();
|
|
436
439
|
init_config();
|
|
440
|
+
init_literal();
|
|
437
441
|
});
|
|
438
442
|
|
|
439
443
|
// src/infrastructure/config/configLoader.ts
|
|
@@ -2660,10 +2664,299 @@ function generateChunkId(filepath, startLine, endLine) {
|
|
|
2660
2664
|
}
|
|
2661
2665
|
var DEFAULT_CHUNK_SIZE = 30, DEFAULT_OVERLAP = 5;
|
|
2662
2666
|
|
|
2667
|
+
// src/domain/services/queryLiteralParser.ts
|
|
2668
|
+
function parseQueryLiterals(query) {
|
|
2669
|
+
if (!query || query.trim() === "") {
|
|
2670
|
+
return { literals: [], remainingQuery: "" };
|
|
2671
|
+
}
|
|
2672
|
+
const literals = [];
|
|
2673
|
+
let remainingQuery = query;
|
|
2674
|
+
const matchedPositions = new Set;
|
|
2675
|
+
const backtickResult = extractExplicitLiterals(remainingQuery, /`([^`]+)`/g, "explicit-backtick", matchedPositions);
|
|
2676
|
+
literals.push(...backtickResult.literals);
|
|
2677
|
+
remainingQuery = backtickResult.remainingQuery;
|
|
2678
|
+
const quoteResult = extractExplicitLiterals(remainingQuery, /"([^"]+)"/g, "explicit-quote", matchedPositions);
|
|
2679
|
+
literals.push(...quoteResult.literals);
|
|
2680
|
+
remainingQuery = quoteResult.remainingQuery;
|
|
2681
|
+
const implicitLiterals = extractImplicitLiterals(query, matchedPositions);
|
|
2682
|
+
literals.push(...implicitLiterals);
|
|
2683
|
+
return {
|
|
2684
|
+
literals,
|
|
2685
|
+
remainingQuery: remainingQuery.trim()
|
|
2686
|
+
};
|
|
2687
|
+
}
|
|
2688
|
+
function extractExplicitLiterals(query, pattern, method, matchedPositions) {
|
|
2689
|
+
const literals = [];
|
|
2690
|
+
let remainingQuery = query;
|
|
2691
|
+
pattern.lastIndex = 0;
|
|
2692
|
+
let match;
|
|
2693
|
+
const replacements = [];
|
|
2694
|
+
while ((match = pattern.exec(query)) !== null) {
|
|
2695
|
+
const value = match[1];
|
|
2696
|
+
const rawValue = match[0];
|
|
2697
|
+
if (!value || value.trim() === "") {
|
|
2698
|
+
continue;
|
|
2699
|
+
}
|
|
2700
|
+
const posKey = `${match.index}:${match.index + rawValue.length}`;
|
|
2701
|
+
matchedPositions.add(posKey);
|
|
2702
|
+
matchedPositions.add(`value:${value.toLowerCase()}`);
|
|
2703
|
+
literals.push({
|
|
2704
|
+
value,
|
|
2705
|
+
rawValue,
|
|
2706
|
+
confidence: "high",
|
|
2707
|
+
detectionMethod: method,
|
|
2708
|
+
inferredType: inferTypeFromValue(value)
|
|
2709
|
+
});
|
|
2710
|
+
replacements.push({
|
|
2711
|
+
start: match.index,
|
|
2712
|
+
end: match.index + rawValue.length,
|
|
2713
|
+
text: ""
|
|
2714
|
+
});
|
|
2715
|
+
}
|
|
2716
|
+
replacements.sort((a, b) => b.start - a.start).forEach((r) => {
|
|
2717
|
+
remainingQuery = remainingQuery.slice(0, r.start) + r.text + remainingQuery.slice(r.end);
|
|
2718
|
+
});
|
|
2719
|
+
return { literals, remainingQuery };
|
|
2720
|
+
}
|
|
2721
|
+
function extractImplicitLiterals(query, matchedPositions) {
|
|
2722
|
+
const literals = [];
|
|
2723
|
+
const seenValues = new Set;
|
|
2724
|
+
for (const patternDef of IMPLICIT_PATTERNS) {
|
|
2725
|
+
patternDef.pattern.lastIndex = 0;
|
|
2726
|
+
let match;
|
|
2727
|
+
while ((match = patternDef.pattern.exec(query)) !== null) {
|
|
2728
|
+
const value = match[1];
|
|
2729
|
+
if (patternDef.minLength && value.length < patternDef.minLength) {
|
|
2730
|
+
continue;
|
|
2731
|
+
}
|
|
2732
|
+
const posKey = `${match.index}:${match.index + value.length}`;
|
|
2733
|
+
if (matchedPositions.has(posKey)) {
|
|
2734
|
+
continue;
|
|
2735
|
+
}
|
|
2736
|
+
if (matchedPositions.has(`value:${value.toLowerCase()}`)) {
|
|
2737
|
+
continue;
|
|
2738
|
+
}
|
|
2739
|
+
const lowerValue = value.toLowerCase();
|
|
2740
|
+
if (seenValues.has(lowerValue)) {
|
|
2741
|
+
continue;
|
|
2742
|
+
}
|
|
2743
|
+
seenValues.add(lowerValue);
|
|
2744
|
+
if (isCommonWord(value)) {
|
|
2745
|
+
continue;
|
|
2746
|
+
}
|
|
2747
|
+
literals.push({
|
|
2748
|
+
value,
|
|
2749
|
+
rawValue: value,
|
|
2750
|
+
confidence: patternDef.confidence,
|
|
2751
|
+
detectionMethod: "implicit-casing",
|
|
2752
|
+
inferredType: patternDef.inferredType
|
|
2753
|
+
});
|
|
2754
|
+
}
|
|
2755
|
+
}
|
|
2756
|
+
return literals;
|
|
2757
|
+
}
|
|
2758
|
+
function inferTypeFromValue(value) {
|
|
2759
|
+
if (/^[A-Z][a-z]+(?:[A-Z][a-z0-9]*)+$/.test(value)) {
|
|
2760
|
+
return "className";
|
|
2761
|
+
}
|
|
2762
|
+
if (/^[a-z][a-z0-9]*(?:[A-Z][a-zA-Z0-9]*)+$/.test(value)) {
|
|
2763
|
+
return "functionName";
|
|
2764
|
+
}
|
|
2765
|
+
if (/^[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)+$/.test(value)) {
|
|
2766
|
+
return "variableName";
|
|
2767
|
+
}
|
|
2768
|
+
if (/^[a-z][a-z0-9]*(?:_[a-z0-9]+)+$/.test(value)) {
|
|
2769
|
+
return "identifier";
|
|
2770
|
+
}
|
|
2771
|
+
if (/^[a-z][a-z0-9]*(?:-[a-z0-9]+)+$/.test(value)) {
|
|
2772
|
+
return "packageName";
|
|
2773
|
+
}
|
|
2774
|
+
return;
|
|
2775
|
+
}
|
|
2776
|
+
function isCommonWord(word) {
|
|
2777
|
+
const commonWords = new Set([
|
|
2778
|
+
"find",
|
|
2779
|
+
"the",
|
|
2780
|
+
"a",
|
|
2781
|
+
"an",
|
|
2782
|
+
"is",
|
|
2783
|
+
"are",
|
|
2784
|
+
"was",
|
|
2785
|
+
"were",
|
|
2786
|
+
"what",
|
|
2787
|
+
"where",
|
|
2788
|
+
"when",
|
|
2789
|
+
"how",
|
|
2790
|
+
"why",
|
|
2791
|
+
"which",
|
|
2792
|
+
"who",
|
|
2793
|
+
"this",
|
|
2794
|
+
"that",
|
|
2795
|
+
"these",
|
|
2796
|
+
"those",
|
|
2797
|
+
"and",
|
|
2798
|
+
"or",
|
|
2799
|
+
"but",
|
|
2800
|
+
"for",
|
|
2801
|
+
"with",
|
|
2802
|
+
"from",
|
|
2803
|
+
"to",
|
|
2804
|
+
"in",
|
|
2805
|
+
"on",
|
|
2806
|
+
"at",
|
|
2807
|
+
"by",
|
|
2808
|
+
"of",
|
|
2809
|
+
"all",
|
|
2810
|
+
"any",
|
|
2811
|
+
"some",
|
|
2812
|
+
"get",
|
|
2813
|
+
"set",
|
|
2814
|
+
"new",
|
|
2815
|
+
"class",
|
|
2816
|
+
"function",
|
|
2817
|
+
"const",
|
|
2818
|
+
"let",
|
|
2819
|
+
"var",
|
|
2820
|
+
"type",
|
|
2821
|
+
"interface",
|
|
2822
|
+
"import",
|
|
2823
|
+
"export",
|
|
2824
|
+
"default",
|
|
2825
|
+
"return",
|
|
2826
|
+
"async",
|
|
2827
|
+
"await",
|
|
2828
|
+
"null",
|
|
2829
|
+
"undefined",
|
|
2830
|
+
"true",
|
|
2831
|
+
"false"
|
|
2832
|
+
]);
|
|
2833
|
+
return commonWords.has(word.toLowerCase());
|
|
2834
|
+
}
|
|
2835
|
+
var IMPLICIT_PATTERNS;
|
|
2836
|
+
var init_queryLiteralParser = __esm(() => {
|
|
2837
|
+
IMPLICIT_PATTERNS = [
|
|
2838
|
+
{
|
|
2839
|
+
pattern: /\b([A-Z][a-z]+(?:[A-Z][a-z0-9]*)+)\b/g,
|
|
2840
|
+
confidence: "medium",
|
|
2841
|
+
inferredType: "className",
|
|
2842
|
+
minLength: 3
|
|
2843
|
+
},
|
|
2844
|
+
{
|
|
2845
|
+
pattern: /\b([a-z][a-z0-9]*(?:[A-Z][a-zA-Z0-9]*)+)\b/g,
|
|
2846
|
+
confidence: "medium",
|
|
2847
|
+
inferredType: "functionName",
|
|
2848
|
+
minLength: 3
|
|
2849
|
+
},
|
|
2850
|
+
{
|
|
2851
|
+
pattern: /\b([A-Z][A-Z0-9]*(?:_[A-Z0-9]+)+)\b/g,
|
|
2852
|
+
confidence: "medium",
|
|
2853
|
+
inferredType: "variableName",
|
|
2854
|
+
minLength: 3
|
|
2855
|
+
},
|
|
2856
|
+
{
|
|
2857
|
+
pattern: /\b([a-z][a-z0-9]*(?:_[a-z0-9]+)+)\b/g,
|
|
2858
|
+
confidence: "low",
|
|
2859
|
+
inferredType: "identifier",
|
|
2860
|
+
minLength: 3
|
|
2861
|
+
},
|
|
2862
|
+
{
|
|
2863
|
+
pattern: /(?<![/:.])\b([a-z][a-z0-9]*(?:-[a-z0-9]+)+)\b(?![/:])/g,
|
|
2864
|
+
confidence: "low",
|
|
2865
|
+
inferredType: "packageName",
|
|
2866
|
+
minLength: 3
|
|
2867
|
+
}
|
|
2868
|
+
];
|
|
2869
|
+
});
|
|
2870
|
+
|
|
2871
|
+
// src/domain/services/literalExtractor.ts
|
|
2872
|
+
function extractLiterals(chunk) {
|
|
2873
|
+
const literals = [];
|
|
2874
|
+
if (chunk.name) {
|
|
2875
|
+
const literalType = CHUNK_TYPE_TO_LITERAL_TYPE[chunk.type] || "identifier";
|
|
2876
|
+
literals.push({
|
|
2877
|
+
value: chunk.name,
|
|
2878
|
+
type: literalType,
|
|
2879
|
+
matchType: "definition"
|
|
2880
|
+
});
|
|
2881
|
+
}
|
|
2882
|
+
return literals;
|
|
2883
|
+
}
|
|
2884
|
+
var CHUNK_TYPE_TO_LITERAL_TYPE;
|
|
2885
|
+
var init_literalExtractor = __esm(() => {
|
|
2886
|
+
CHUNK_TYPE_TO_LITERAL_TYPE = {
|
|
2887
|
+
class: "className",
|
|
2888
|
+
function: "functionName",
|
|
2889
|
+
interface: "interfaceName",
|
|
2890
|
+
type: "typeName",
|
|
2891
|
+
enum: "enumName",
|
|
2892
|
+
variable: "variableName"
|
|
2893
|
+
};
|
|
2894
|
+
});
|
|
2895
|
+
|
|
2896
|
+
// src/domain/services/literalScorer.ts
|
|
2897
|
+
function calculateLiteralMultiplier(matchType, confidence) {
|
|
2898
|
+
return LITERAL_SCORING_CONSTANTS.MULTIPLIERS[matchType][confidence];
|
|
2899
|
+
}
|
|
2900
|
+
function calculateMaxMultiplier(matches) {
|
|
2901
|
+
if (!matches || matches.length === 0) {
|
|
2902
|
+
return 1;
|
|
2903
|
+
}
|
|
2904
|
+
return Math.max(...matches.map((m) => calculateLiteralMultiplier(m.indexedLiteral.matchType, m.queryLiteral.confidence)));
|
|
2905
|
+
}
|
|
2906
|
+
function calculateLiteralContribution(matches, hasSemanticOrBm25) {
|
|
2907
|
+
if (!matches || matches.length === 0) {
|
|
2908
|
+
return {
|
|
2909
|
+
multiplier: 1,
|
|
2910
|
+
literalOnly: false,
|
|
2911
|
+
matchCount: 0
|
|
2912
|
+
};
|
|
2913
|
+
}
|
|
2914
|
+
let bestMatch = null;
|
|
2915
|
+
let bestMultiplier = 0;
|
|
2916
|
+
for (const match of matches) {
|
|
2917
|
+
const mult = calculateLiteralMultiplier(match.indexedLiteral.matchType, match.queryLiteral.confidence);
|
|
2918
|
+
if (mult > bestMultiplier) {
|
|
2919
|
+
bestMultiplier = mult;
|
|
2920
|
+
bestMatch = match;
|
|
2921
|
+
}
|
|
2922
|
+
}
|
|
2923
|
+
return {
|
|
2924
|
+
multiplier: bestMultiplier,
|
|
2925
|
+
literalOnly: !hasSemanticOrBm25,
|
|
2926
|
+
bestMatchType: bestMatch?.indexedLiteral.matchType,
|
|
2927
|
+
bestConfidence: bestMatch?.queryLiteral.confidence,
|
|
2928
|
+
matchCount: matches.length
|
|
2929
|
+
};
|
|
2930
|
+
}
|
|
2931
|
+
function applyLiteralBoost(baseScore, matches, hasSemanticOrBm25) {
|
|
2932
|
+
if (!matches || matches.length === 0) {
|
|
2933
|
+
return baseScore;
|
|
2934
|
+
}
|
|
2935
|
+
const multiplier = calculateMaxMultiplier(matches);
|
|
2936
|
+
if (!hasSemanticOrBm25) {
|
|
2937
|
+
return LITERAL_SCORING_CONSTANTS.BASE_SCORE * multiplier;
|
|
2938
|
+
}
|
|
2939
|
+
return baseScore * multiplier;
|
|
2940
|
+
}
|
|
2941
|
+
var LITERAL_SCORING_CONSTANTS;
|
|
2942
|
+
var init_literalScorer = __esm(() => {
|
|
2943
|
+
LITERAL_SCORING_CONSTANTS = {
|
|
2944
|
+
BASE_SCORE: 0.5,
|
|
2945
|
+
MULTIPLIERS: {
|
|
2946
|
+
definition: { high: 2.5, medium: 2, low: 1.5 },
|
|
2947
|
+
reference: { high: 2, medium: 1.5, low: 1.3 },
|
|
2948
|
+
import: { high: 1.5, medium: 1.3, low: 1.1 }
|
|
2949
|
+
}
|
|
2950
|
+
};
|
|
2951
|
+
});
|
|
2952
|
+
|
|
2663
2953
|
// src/domain/services/index.ts
|
|
2664
2954
|
var init_services = __esm(() => {
|
|
2665
2955
|
init_keywords();
|
|
2666
2956
|
init_queryIntent();
|
|
2957
|
+
init_queryLiteralParser();
|
|
2958
|
+
init_literalExtractor();
|
|
2959
|
+
init_literalScorer();
|
|
2667
2960
|
});
|
|
2668
2961
|
|
|
2669
2962
|
// src/modules/language/typescript/parseCode.ts
|
|
@@ -2983,10 +3276,158 @@ var init_symbolicIndex = __esm(() => {
|
|
|
2983
3276
|
init_keywords();
|
|
2984
3277
|
});
|
|
2985
3278
|
|
|
3279
|
+
// src/infrastructure/storage/literalIndex.ts
|
|
3280
|
+
import * as fs4 from "fs/promises";
|
|
3281
|
+
import * as path9 from "path";
|
|
3282
|
+
|
|
3283
|
+
class LiteralIndex {
|
|
3284
|
+
indexPath;
|
|
3285
|
+
moduleId;
|
|
3286
|
+
entries = new Map;
|
|
3287
|
+
static VERSION = "1.0.0";
|
|
3288
|
+
constructor(indexDir, moduleId) {
|
|
3289
|
+
this.indexPath = path9.join(indexDir, "index", moduleId, "literals");
|
|
3290
|
+
this.moduleId = moduleId;
|
|
3291
|
+
}
|
|
3292
|
+
async initialize() {
|
|
3293
|
+
try {
|
|
3294
|
+
await this.load();
|
|
3295
|
+
} catch {
|
|
3296
|
+
this.entries = new Map;
|
|
3297
|
+
}
|
|
3298
|
+
}
|
|
3299
|
+
addLiterals(chunkId, filepath, literals) {
|
|
3300
|
+
for (const literal of literals) {
|
|
3301
|
+
const key = literal.value.toLowerCase();
|
|
3302
|
+
const existingEntries = this.entries.get(key) || [];
|
|
3303
|
+
const existingIndex = existingEntries.findIndex((e) => e.chunkId === chunkId);
|
|
3304
|
+
const newEntry = {
|
|
3305
|
+
chunkId,
|
|
3306
|
+
filepath,
|
|
3307
|
+
originalCasing: literal.value,
|
|
3308
|
+
type: literal.type,
|
|
3309
|
+
matchType: literal.matchType
|
|
3310
|
+
};
|
|
3311
|
+
if (existingIndex >= 0) {
|
|
3312
|
+
const existing = existingEntries[existingIndex];
|
|
3313
|
+
if (shouldReplaceMatchType(existing.matchType, literal.matchType)) {
|
|
3314
|
+
existingEntries[existingIndex] = newEntry;
|
|
3315
|
+
}
|
|
3316
|
+
} else {
|
|
3317
|
+
existingEntries.push(newEntry);
|
|
3318
|
+
}
|
|
3319
|
+
this.entries.set(key, existingEntries);
|
|
3320
|
+
}
|
|
3321
|
+
}
|
|
3322
|
+
removeChunk(chunkId) {
|
|
3323
|
+
for (const [key, entries] of this.entries) {
|
|
3324
|
+
const filtered = entries.filter((e) => e.chunkId !== chunkId);
|
|
3325
|
+
if (filtered.length === 0) {
|
|
3326
|
+
this.entries.delete(key);
|
|
3327
|
+
} else if (filtered.length !== entries.length) {
|
|
3328
|
+
this.entries.set(key, filtered);
|
|
3329
|
+
}
|
|
3330
|
+
}
|
|
3331
|
+
}
|
|
3332
|
+
findMatches(queryLiterals) {
|
|
3333
|
+
const matches = [];
|
|
3334
|
+
for (const queryLiteral of queryLiterals) {
|
|
3335
|
+
const key = queryLiteral.value.toLowerCase();
|
|
3336
|
+
const entries = this.entries.get(key);
|
|
3337
|
+
if (!entries) {
|
|
3338
|
+
continue;
|
|
3339
|
+
}
|
|
3340
|
+
for (const entry of entries) {
|
|
3341
|
+
const exactMatch = entry.originalCasing === queryLiteral.value;
|
|
3342
|
+
matches.push({
|
|
3343
|
+
queryLiteral,
|
|
3344
|
+
indexedLiteral: {
|
|
3345
|
+
value: entry.originalCasing,
|
|
3346
|
+
type: entry.type,
|
|
3347
|
+
matchType: entry.matchType
|
|
3348
|
+
},
|
|
3349
|
+
chunkId: entry.chunkId,
|
|
3350
|
+
filepath: entry.filepath,
|
|
3351
|
+
exactMatch
|
|
3352
|
+
});
|
|
3353
|
+
}
|
|
3354
|
+
}
|
|
3355
|
+
return matches;
|
|
3356
|
+
}
|
|
3357
|
+
getChunksForLiteral(literal) {
|
|
3358
|
+
const key = literal.toLowerCase();
|
|
3359
|
+
const entries = this.entries.get(key);
|
|
3360
|
+
return entries ? entries.map((e) => e.chunkId) : [];
|
|
3361
|
+
}
|
|
3362
|
+
async save() {
|
|
3363
|
+
await fs4.mkdir(this.indexPath, { recursive: true });
|
|
3364
|
+
const data = {
|
|
3365
|
+
version: LiteralIndex.VERSION,
|
|
3366
|
+
entries: Object.fromEntries(this.entries)
|
|
3367
|
+
};
|
|
3368
|
+
const indexFile = path9.join(this.indexPath, "_index.json");
|
|
3369
|
+
await fs4.writeFile(indexFile, JSON.stringify(data, null, 2));
|
|
3370
|
+
}
|
|
3371
|
+
async load() {
|
|
3372
|
+
const indexFile = path9.join(this.indexPath, "_index.json");
|
|
3373
|
+
const content = await fs4.readFile(indexFile, "utf-8");
|
|
3374
|
+
const data = JSON.parse(content);
|
|
3375
|
+
if (data.version !== LiteralIndex.VERSION) {
|
|
3376
|
+
console.warn(`Literal index version mismatch: expected ${LiteralIndex.VERSION}, got ${data.version}`);
|
|
3377
|
+
}
|
|
3378
|
+
this.entries = new Map(Object.entries(data.entries));
|
|
3379
|
+
}
|
|
3380
|
+
async exists() {
|
|
3381
|
+
try {
|
|
3382
|
+
const indexFile = path9.join(this.indexPath, "_index.json");
|
|
3383
|
+
await fs4.access(indexFile);
|
|
3384
|
+
return true;
|
|
3385
|
+
} catch {
|
|
3386
|
+
return false;
|
|
3387
|
+
}
|
|
3388
|
+
}
|
|
3389
|
+
clear() {
|
|
3390
|
+
this.entries.clear();
|
|
3391
|
+
}
|
|
3392
|
+
get size() {
|
|
3393
|
+
return this.entries.size;
|
|
3394
|
+
}
|
|
3395
|
+
get totalMappings() {
|
|
3396
|
+
let count = 0;
|
|
3397
|
+
for (const entries of this.entries.values()) {
|
|
3398
|
+
count += entries.length;
|
|
3399
|
+
}
|
|
3400
|
+
return count;
|
|
3401
|
+
}
|
|
3402
|
+
getAllLiterals() {
|
|
3403
|
+
return Array.from(this.entries.keys());
|
|
3404
|
+
}
|
|
3405
|
+
buildMatchMap(queryLiterals) {
|
|
3406
|
+
const matches = this.findMatches(queryLiterals);
|
|
3407
|
+
const matchMap = new Map;
|
|
3408
|
+
for (const match of matches) {
|
|
3409
|
+
const existing = matchMap.get(match.chunkId) || [];
|
|
3410
|
+
existing.push(match);
|
|
3411
|
+
matchMap.set(match.chunkId, existing);
|
|
3412
|
+
}
|
|
3413
|
+
return matchMap;
|
|
3414
|
+
}
|
|
3415
|
+
}
|
|
3416
|
+
function shouldReplaceMatchType(existing, incoming) {
|
|
3417
|
+
const priority = {
|
|
3418
|
+
definition: 3,
|
|
3419
|
+
reference: 2,
|
|
3420
|
+
import: 1
|
|
3421
|
+
};
|
|
3422
|
+
return priority[incoming] > priority[existing];
|
|
3423
|
+
}
|
|
3424
|
+
var init_literalIndex = () => {};
|
|
3425
|
+
|
|
2986
3426
|
// src/infrastructure/storage/index.ts
|
|
2987
3427
|
var init_storage = __esm(() => {
|
|
2988
3428
|
init_fileIndexStorage();
|
|
2989
3429
|
init_symbolicIndex();
|
|
3430
|
+
init_literalIndex();
|
|
2990
3431
|
});
|
|
2991
3432
|
|
|
2992
3433
|
// src/modules/language/typescript/index.ts
|
|
@@ -2999,9 +3440,9 @@ __export(exports_typescript, {
|
|
|
2999
3440
|
DEFAULT_TOP_K: () => DEFAULT_TOP_K2,
|
|
3000
3441
|
DEFAULT_MIN_SCORE: () => DEFAULT_MIN_SCORE2
|
|
3001
3442
|
});
|
|
3002
|
-
import * as
|
|
3443
|
+
import * as path10 from "path";
|
|
3003
3444
|
function isTypeScriptFile(filepath) {
|
|
3004
|
-
const ext =
|
|
3445
|
+
const ext = path10.extname(filepath).toLowerCase();
|
|
3005
3446
|
return TYPESCRIPT_EXTENSIONS.includes(ext);
|
|
3006
3447
|
}
|
|
3007
3448
|
function calculateChunkTypeBoost(chunk) {
|
|
@@ -3036,7 +3477,9 @@ class TypeScriptModule {
|
|
|
3036
3477
|
}
|
|
3037
3478
|
embeddingConfig = null;
|
|
3038
3479
|
symbolicIndex = null;
|
|
3480
|
+
literalIndex = null;
|
|
3039
3481
|
pendingSummaries = new Map;
|
|
3482
|
+
pendingLiterals = new Map;
|
|
3040
3483
|
rootDir = "";
|
|
3041
3484
|
logger = undefined;
|
|
3042
3485
|
async initialize(config) {
|
|
@@ -3050,6 +3493,7 @@ class TypeScriptModule {
|
|
|
3050
3493
|
}
|
|
3051
3494
|
configureEmbeddings(this.embeddingConfig);
|
|
3052
3495
|
this.pendingSummaries.clear();
|
|
3496
|
+
this.pendingLiterals.clear();
|
|
3053
3497
|
}
|
|
3054
3498
|
async indexFile(filepath, content, ctx) {
|
|
3055
3499
|
if (!isTypeScriptFile(filepath)) {
|
|
@@ -3109,6 +3553,17 @@ class TypeScriptModule {
|
|
|
3109
3553
|
}
|
|
3110
3554
|
};
|
|
3111
3555
|
this.pendingSummaries.set(filepath, fileSummary);
|
|
3556
|
+
for (const chunk of chunks) {
|
|
3557
|
+
const literals = extractLiterals(chunk);
|
|
3558
|
+
if (literals.length > 0) {
|
|
3559
|
+
const existing = this.pendingLiterals.get(chunk.id);
|
|
3560
|
+
if (existing) {
|
|
3561
|
+
existing.literals.push(...literals);
|
|
3562
|
+
} else {
|
|
3563
|
+
this.pendingLiterals.set(chunk.id, { filepath, literals });
|
|
3564
|
+
}
|
|
3565
|
+
}
|
|
3566
|
+
}
|
|
3112
3567
|
return {
|
|
3113
3568
|
filepath,
|
|
3114
3569
|
lastModified: stats.lastModified,
|
|
@@ -3126,7 +3581,14 @@ class TypeScriptModule {
|
|
|
3126
3581
|
}
|
|
3127
3582
|
this.symbolicIndex.buildBM25Index();
|
|
3128
3583
|
await this.symbolicIndex.save();
|
|
3584
|
+
this.literalIndex = new LiteralIndex(indexDir, this.id);
|
|
3585
|
+
await this.literalIndex.initialize();
|
|
3586
|
+
for (const [chunkId, { filepath, literals }] of this.pendingLiterals) {
|
|
3587
|
+
this.literalIndex.addLiterals(chunkId, filepath, literals);
|
|
3588
|
+
}
|
|
3589
|
+
await this.literalIndex.save();
|
|
3129
3590
|
this.pendingSummaries.clear();
|
|
3591
|
+
this.pendingLiterals.clear();
|
|
3130
3592
|
}
|
|
3131
3593
|
async search(query, ctx, options = {}) {
|
|
3132
3594
|
const {
|
|
@@ -3134,8 +3596,15 @@ class TypeScriptModule {
|
|
|
3134
3596
|
minScore = DEFAULT_MIN_SCORE2,
|
|
3135
3597
|
filePatterns
|
|
3136
3598
|
} = options;
|
|
3599
|
+
const { literals: queryLiterals, remainingQuery } = parseQueryLiterals(query);
|
|
3137
3600
|
const indexDir = getRaggrepDir(ctx.rootDir, ctx.config);
|
|
3138
3601
|
const symbolicIndex = new SymbolicIndex(indexDir, this.id);
|
|
3602
|
+
const literalIndex = new LiteralIndex(indexDir, this.id);
|
|
3603
|
+
let literalMatchMap = new Map;
|
|
3604
|
+
try {
|
|
3605
|
+
await literalIndex.initialize();
|
|
3606
|
+
literalMatchMap = literalIndex.buildMatchMap(queryLiterals);
|
|
3607
|
+
} catch {}
|
|
3139
3608
|
let allFiles;
|
|
3140
3609
|
try {
|
|
3141
3610
|
await symbolicIndex.initialize();
|
|
@@ -3155,7 +3624,8 @@ class TypeScriptModule {
|
|
|
3155
3624
|
});
|
|
3156
3625
|
});
|
|
3157
3626
|
}
|
|
3158
|
-
const
|
|
3627
|
+
const semanticQuery = remainingQuery.trim() || query;
|
|
3628
|
+
const queryEmbedding = await getEmbedding(semanticQuery);
|
|
3159
3629
|
const bm25Index = new BM25Index;
|
|
3160
3630
|
const allChunksData = [];
|
|
3161
3631
|
for (const filepath of filesToSearch) {
|
|
@@ -3189,14 +3659,14 @@ class TypeScriptModule {
|
|
|
3189
3659
|
const summary = symbolicIndex.getFileSummary(filepath);
|
|
3190
3660
|
if (summary?.pathContext) {
|
|
3191
3661
|
let boost = 0;
|
|
3192
|
-
const
|
|
3193
|
-
if (
|
|
3662
|
+
const pathCtx = summary.pathContext;
|
|
3663
|
+
if (pathCtx.domain && queryTerms.some((t) => pathCtx.domain.includes(t) || t.includes(pathCtx.domain))) {
|
|
3194
3664
|
boost += 0.1;
|
|
3195
3665
|
}
|
|
3196
|
-
if (
|
|
3666
|
+
if (pathCtx.layer && queryTerms.some((t) => pathCtx.layer.includes(t) || t.includes(pathCtx.layer))) {
|
|
3197
3667
|
boost += 0.05;
|
|
3198
3668
|
}
|
|
3199
|
-
const segmentMatch =
|
|
3669
|
+
const segmentMatch = pathCtx.segments.some((seg) => queryTerms.some((t) => seg.toLowerCase().includes(t) || t.includes(seg.toLowerCase())));
|
|
3200
3670
|
if (segmentMatch) {
|
|
3201
3671
|
boost += 0.05;
|
|
3202
3672
|
}
|
|
@@ -3204,6 +3674,7 @@ class TypeScriptModule {
|
|
|
3204
3674
|
}
|
|
3205
3675
|
}
|
|
3206
3676
|
const results = [];
|
|
3677
|
+
const processedChunkIds = new Set;
|
|
3207
3678
|
for (const { filepath, chunk, embedding } of allChunksData) {
|
|
3208
3679
|
const semanticScore = cosineSimilarity(queryEmbedding, embedding);
|
|
3209
3680
|
const bm25Score = bm25Scores.get(chunk.id) || 0;
|
|
@@ -3211,13 +3682,18 @@ class TypeScriptModule {
|
|
|
3211
3682
|
const fileTypeBoost = calculateFileTypeBoost(filepath, queryTerms);
|
|
3212
3683
|
const chunkTypeBoost = calculateChunkTypeBoost(chunk);
|
|
3213
3684
|
const exportBoost = calculateExportBoost(chunk);
|
|
3214
|
-
const
|
|
3215
|
-
const
|
|
3216
|
-
|
|
3685
|
+
const additiveBoost = pathBoost + fileTypeBoost + chunkTypeBoost + exportBoost;
|
|
3686
|
+
const baseScore = SEMANTIC_WEIGHT * semanticScore + BM25_WEIGHT * bm25Score;
|
|
3687
|
+
const literalMatches = literalMatchMap.get(chunk.id) || [];
|
|
3688
|
+
const literalContribution = calculateLiteralContribution(literalMatches, true);
|
|
3689
|
+
const boostedScore = applyLiteralBoost(baseScore, literalMatches, true);
|
|
3690
|
+
const finalScore = boostedScore + additiveBoost;
|
|
3691
|
+
processedChunkIds.add(chunk.id);
|
|
3692
|
+
if (finalScore >= minScore || bm25Score > 0.3 || literalMatches.length > 0) {
|
|
3217
3693
|
results.push({
|
|
3218
3694
|
filepath,
|
|
3219
3695
|
chunk,
|
|
3220
|
-
score:
|
|
3696
|
+
score: finalScore,
|
|
3221
3697
|
moduleId: this.id,
|
|
3222
3698
|
context: {
|
|
3223
3699
|
semanticScore,
|
|
@@ -3225,7 +3701,78 @@ class TypeScriptModule {
|
|
|
3225
3701
|
pathBoost,
|
|
3226
3702
|
fileTypeBoost,
|
|
3227
3703
|
chunkTypeBoost,
|
|
3228
|
-
exportBoost
|
|
3704
|
+
exportBoost,
|
|
3705
|
+
literalMultiplier: literalContribution.multiplier,
|
|
3706
|
+
literalMatchType: literalContribution.bestMatchType,
|
|
3707
|
+
literalConfidence: literalContribution.bestConfidence,
|
|
3708
|
+
literalMatchCount: literalContribution.matchCount
|
|
3709
|
+
}
|
|
3710
|
+
});
|
|
3711
|
+
}
|
|
3712
|
+
}
|
|
3713
|
+
const literalOnlyFiles = new Map;
|
|
3714
|
+
for (const [chunkId, matches] of literalMatchMap) {
|
|
3715
|
+
if (processedChunkIds.has(chunkId)) {
|
|
3716
|
+
continue;
|
|
3717
|
+
}
|
|
3718
|
+
const filepath = matches[0]?.filepath;
|
|
3719
|
+
if (!filepath)
|
|
3720
|
+
continue;
|
|
3721
|
+
const existing = literalOnlyFiles.get(filepath) || [];
|
|
3722
|
+
existing.push(...matches);
|
|
3723
|
+
literalOnlyFiles.set(filepath, existing);
|
|
3724
|
+
}
|
|
3725
|
+
for (const [filepath, matches] of literalOnlyFiles) {
|
|
3726
|
+
const fileIndex = await ctx.loadFileIndex(filepath);
|
|
3727
|
+
if (!fileIndex)
|
|
3728
|
+
continue;
|
|
3729
|
+
const moduleData = fileIndex.moduleData;
|
|
3730
|
+
const chunkMatches = new Map;
|
|
3731
|
+
for (const match of matches) {
|
|
3732
|
+
const existing = chunkMatches.get(match.chunkId) || [];
|
|
3733
|
+
existing.push(match);
|
|
3734
|
+
chunkMatches.set(match.chunkId, existing);
|
|
3735
|
+
}
|
|
3736
|
+
for (const [chunkId, chunkLiteralMatches] of chunkMatches) {
|
|
3737
|
+
if (processedChunkIds.has(chunkId))
|
|
3738
|
+
continue;
|
|
3739
|
+
const chunkIndex = fileIndex.chunks.findIndex((c) => c.id === chunkId);
|
|
3740
|
+
if (chunkIndex === -1)
|
|
3741
|
+
continue;
|
|
3742
|
+
const chunk = fileIndex.chunks[chunkIndex];
|
|
3743
|
+
const embedding = moduleData?.embeddings?.[chunkIndex];
|
|
3744
|
+
let semanticScore = 0;
|
|
3745
|
+
if (embedding) {
|
|
3746
|
+
semanticScore = cosineSimilarity(queryEmbedding, embedding);
|
|
3747
|
+
}
|
|
3748
|
+
const bm25Score = bm25Scores.get(chunkId) || 0;
|
|
3749
|
+
const pathBoost = pathBoosts.get(filepath) || 0;
|
|
3750
|
+
const fileTypeBoost = calculateFileTypeBoost(filepath, queryTerms);
|
|
3751
|
+
const chunkTypeBoost = calculateChunkTypeBoost(chunk);
|
|
3752
|
+
const exportBoost = calculateExportBoost(chunk);
|
|
3753
|
+
const additiveBoost = pathBoost + fileTypeBoost + chunkTypeBoost + exportBoost;
|
|
3754
|
+
const literalContribution = calculateLiteralContribution(chunkLiteralMatches, false);
|
|
3755
|
+
const baseScore = semanticScore > 0 ? SEMANTIC_WEIGHT * semanticScore + BM25_WEIGHT * bm25Score : LITERAL_SCORING_CONSTANTS.BASE_SCORE;
|
|
3756
|
+
const boostedScore = applyLiteralBoost(baseScore, chunkLiteralMatches, semanticScore > 0);
|
|
3757
|
+
const finalScore = boostedScore + additiveBoost;
|
|
3758
|
+
processedChunkIds.add(chunkId);
|
|
3759
|
+
results.push({
|
|
3760
|
+
filepath,
|
|
3761
|
+
chunk,
|
|
3762
|
+
score: finalScore,
|
|
3763
|
+
moduleId: this.id,
|
|
3764
|
+
context: {
|
|
3765
|
+
semanticScore,
|
|
3766
|
+
bm25Score,
|
|
3767
|
+
pathBoost,
|
|
3768
|
+
fileTypeBoost,
|
|
3769
|
+
chunkTypeBoost,
|
|
3770
|
+
exportBoost,
|
|
3771
|
+
literalMultiplier: literalContribution.multiplier,
|
|
3772
|
+
literalMatchType: literalContribution.bestMatchType,
|
|
3773
|
+
literalConfidence: literalContribution.bestConfidence,
|
|
3774
|
+
literalMatchCount: literalContribution.matchCount,
|
|
3775
|
+
literalOnly: true
|
|
3229
3776
|
}
|
|
3230
3777
|
});
|
|
3231
3778
|
}
|
|
@@ -3241,16 +3788,16 @@ class TypeScriptModule {
|
|
|
3241
3788
|
while ((match = importRegex.exec(content)) !== null) {
|
|
3242
3789
|
const importPath = match[1];
|
|
3243
3790
|
if (importPath.startsWith(".")) {
|
|
3244
|
-
const dir =
|
|
3245
|
-
const resolved =
|
|
3791
|
+
const dir = path10.dirname(filepath);
|
|
3792
|
+
const resolved = path10.normalize(path10.join(dir, importPath));
|
|
3246
3793
|
references.push(resolved);
|
|
3247
3794
|
}
|
|
3248
3795
|
}
|
|
3249
3796
|
while ((match = requireRegex.exec(content)) !== null) {
|
|
3250
3797
|
const importPath = match[1];
|
|
3251
3798
|
if (importPath.startsWith(".")) {
|
|
3252
|
-
const dir =
|
|
3253
|
-
const resolved =
|
|
3799
|
+
const dir = path10.dirname(filepath);
|
|
3800
|
+
const resolved = path10.normalize(path10.join(dir, importPath));
|
|
3254
3801
|
references.push(resolved);
|
|
3255
3802
|
}
|
|
3256
3803
|
}
|
|
@@ -3287,9 +3834,9 @@ __export(exports_json, {
|
|
|
3287
3834
|
DEFAULT_TOP_K: () => DEFAULT_TOP_K3,
|
|
3288
3835
|
DEFAULT_MIN_SCORE: () => DEFAULT_MIN_SCORE3
|
|
3289
3836
|
});
|
|
3290
|
-
import * as
|
|
3837
|
+
import * as path11 from "path";
|
|
3291
3838
|
function isJsonFile(filepath) {
|
|
3292
|
-
const ext =
|
|
3839
|
+
const ext = path11.extname(filepath).toLowerCase();
|
|
3293
3840
|
return JSON_EXTENSIONS.includes(ext);
|
|
3294
3841
|
}
|
|
3295
3842
|
function extractJsonKeys(obj, prefix = "") {
|
|
@@ -3370,7 +3917,7 @@ class JsonModule {
|
|
|
3370
3917
|
return null;
|
|
3371
3918
|
}
|
|
3372
3919
|
const chunkContents = textChunks.map((c) => {
|
|
3373
|
-
const filename =
|
|
3920
|
+
const filename = path11.basename(filepath);
|
|
3374
3921
|
return `${filename}: ${c.content}`;
|
|
3375
3922
|
});
|
|
3376
3923
|
const embeddings = await getEmbeddings(chunkContents);
|
|
@@ -3521,9 +4068,9 @@ __export(exports_markdown, {
|
|
|
3521
4068
|
DEFAULT_TOP_K: () => DEFAULT_TOP_K4,
|
|
3522
4069
|
DEFAULT_MIN_SCORE: () => DEFAULT_MIN_SCORE4
|
|
3523
4070
|
});
|
|
3524
|
-
import * as
|
|
4071
|
+
import * as path12 from "path";
|
|
3525
4072
|
function isMarkdownFile(filepath) {
|
|
3526
|
-
const ext =
|
|
4073
|
+
const ext = path12.extname(filepath).toLowerCase();
|
|
3527
4074
|
return MARKDOWN_EXTENSIONS.includes(ext);
|
|
3528
4075
|
}
|
|
3529
4076
|
function parseMarkdownSections(content) {
|
|
@@ -3650,7 +4197,7 @@ class MarkdownModule {
|
|
|
3650
4197
|
return null;
|
|
3651
4198
|
}
|
|
3652
4199
|
const chunkContents = sections.map((s) => {
|
|
3653
|
-
const filename =
|
|
4200
|
+
const filename = path12.basename(filepath);
|
|
3654
4201
|
const headingContext = s.heading ? `${s.heading}: ` : "";
|
|
3655
4202
|
return `${filename} ${headingContext}${s.content}`;
|
|
3656
4203
|
});
|
|
@@ -3837,15 +4384,15 @@ var init_registry = __esm(() => {
|
|
|
3837
4384
|
});
|
|
3838
4385
|
|
|
3839
4386
|
// src/infrastructure/introspection/projectDetector.ts
|
|
3840
|
-
import * as
|
|
3841
|
-
import * as
|
|
4387
|
+
import * as path13 from "path";
|
|
4388
|
+
import * as fs5 from "fs/promises";
|
|
3842
4389
|
async function scanForPackageJsons(rootDir, currentDir = "", depth = 0) {
|
|
3843
4390
|
if (depth > MAX_SCAN_DEPTH)
|
|
3844
4391
|
return [];
|
|
3845
4392
|
const results = [];
|
|
3846
|
-
const fullDir = currentDir ?
|
|
4393
|
+
const fullDir = currentDir ? path13.join(rootDir, currentDir) : rootDir;
|
|
3847
4394
|
try {
|
|
3848
|
-
const entries = await
|
|
4395
|
+
const entries = await fs5.readdir(fullDir, { withFileTypes: true });
|
|
3849
4396
|
const hasPackageJson = entries.some((e) => e.isFile() && e.name === "package.json");
|
|
3850
4397
|
if (hasPackageJson && currentDir) {
|
|
3851
4398
|
const info = await parsePackageJson(rootDir, currentDir);
|
|
@@ -3866,10 +4413,10 @@ async function scanForPackageJsons(rootDir, currentDir = "", depth = 0) {
|
|
|
3866
4413
|
}
|
|
3867
4414
|
async function parsePackageJson(rootDir, relativePath) {
|
|
3868
4415
|
try {
|
|
3869
|
-
const packageJsonPath =
|
|
3870
|
-
const content = await
|
|
4416
|
+
const packageJsonPath = path13.join(rootDir, relativePath, "package.json");
|
|
4417
|
+
const content = await fs5.readFile(packageJsonPath, "utf-8");
|
|
3871
4418
|
const pkg = JSON.parse(content);
|
|
3872
|
-
const name = pkg.name ||
|
|
4419
|
+
const name = pkg.name || path13.basename(relativePath);
|
|
3873
4420
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
3874
4421
|
let type = "unknown";
|
|
3875
4422
|
if (deps["next"] || deps["react"] || deps["vue"] || deps["svelte"]) {
|
|
@@ -3905,7 +4452,7 @@ async function detectProjectStructure(rootDir) {
|
|
|
3905
4452
|
const projectMap = new Map;
|
|
3906
4453
|
let isMonorepo = false;
|
|
3907
4454
|
try {
|
|
3908
|
-
const entries = await
|
|
4455
|
+
const entries = await fs5.readdir(rootDir, { withFileTypes: true });
|
|
3909
4456
|
const dirNames = entries.filter((e) => e.isDirectory()).map((e) => e.name);
|
|
3910
4457
|
const monorepoPatterns = ["apps", "packages", "libs", "services"];
|
|
3911
4458
|
const hasMonorepoStructure = monorepoPatterns.some((p) => dirNames.includes(p));
|
|
@@ -3914,9 +4461,9 @@ async function detectProjectStructure(rootDir) {
|
|
|
3914
4461
|
for (const pattern of monorepoPatterns) {
|
|
3915
4462
|
if (!dirNames.includes(pattern))
|
|
3916
4463
|
continue;
|
|
3917
|
-
const patternDir =
|
|
4464
|
+
const patternDir = path13.join(rootDir, pattern);
|
|
3918
4465
|
try {
|
|
3919
|
-
const subDirs = await
|
|
4466
|
+
const subDirs = await fs5.readdir(patternDir, { withFileTypes: true });
|
|
3920
4467
|
for (const subDir of subDirs) {
|
|
3921
4468
|
if (!subDir.isDirectory())
|
|
3922
4469
|
continue;
|
|
@@ -3945,8 +4492,8 @@ async function detectProjectStructure(rootDir) {
|
|
|
3945
4492
|
}
|
|
3946
4493
|
let rootType = "unknown";
|
|
3947
4494
|
try {
|
|
3948
|
-
const rootPkgPath =
|
|
3949
|
-
const rootPkg = JSON.parse(await
|
|
4495
|
+
const rootPkgPath = path13.join(rootDir, "package.json");
|
|
4496
|
+
const rootPkg = JSON.parse(await fs5.readFile(rootPkgPath, "utf-8"));
|
|
3950
4497
|
if (rootPkg.workspaces)
|
|
3951
4498
|
isMonorepo = true;
|
|
3952
4499
|
const deps = { ...rootPkg.dependencies, ...rootPkg.devDependencies };
|
|
@@ -3985,8 +4532,8 @@ var init_projectDetector = __esm(() => {
|
|
|
3985
4532
|
});
|
|
3986
4533
|
|
|
3987
4534
|
// src/infrastructure/introspection/IntrospectionIndex.ts
|
|
3988
|
-
import * as
|
|
3989
|
-
import * as
|
|
4535
|
+
import * as path14 from "path";
|
|
4536
|
+
import * as fs6 from "fs/promises";
|
|
3990
4537
|
|
|
3991
4538
|
class IntrospectionIndex {
|
|
3992
4539
|
rootDir;
|
|
@@ -3999,8 +4546,8 @@ class IntrospectionIndex {
|
|
|
3999
4546
|
async initialize() {
|
|
4000
4547
|
this.structure = await detectProjectStructure(this.rootDir);
|
|
4001
4548
|
try {
|
|
4002
|
-
const configPath =
|
|
4003
|
-
const configContent = await
|
|
4549
|
+
const configPath = path14.join(this.rootDir, ".raggrep", "config.json");
|
|
4550
|
+
const configContent = await fs6.readFile(configPath, "utf-8");
|
|
4004
4551
|
const config = JSON.parse(configContent);
|
|
4005
4552
|
this.config = config.introspection || {};
|
|
4006
4553
|
} catch {}
|
|
@@ -4039,28 +4586,28 @@ class IntrospectionIndex {
|
|
|
4039
4586
|
}
|
|
4040
4587
|
}
|
|
4041
4588
|
async save(config) {
|
|
4042
|
-
const introDir =
|
|
4043
|
-
await
|
|
4044
|
-
const projectPath =
|
|
4045
|
-
await
|
|
4589
|
+
const introDir = path14.join(getRaggrepDir(this.rootDir, config), "introspection");
|
|
4590
|
+
await fs6.mkdir(introDir, { recursive: true });
|
|
4591
|
+
const projectPath = path14.join(introDir, "_project.json");
|
|
4592
|
+
await fs6.writeFile(projectPath, JSON.stringify({
|
|
4046
4593
|
version: "1.0.0",
|
|
4047
4594
|
lastUpdated: new Date().toISOString(),
|
|
4048
4595
|
structure: this.structure
|
|
4049
4596
|
}, null, 2));
|
|
4050
4597
|
for (const [filepath, intro] of this.files) {
|
|
4051
|
-
const introFilePath =
|
|
4052
|
-
await
|
|
4053
|
-
await
|
|
4598
|
+
const introFilePath = path14.join(introDir, "files", filepath.replace(/\.[^.]+$/, ".json"));
|
|
4599
|
+
await fs6.mkdir(path14.dirname(introFilePath), { recursive: true });
|
|
4600
|
+
await fs6.writeFile(introFilePath, JSON.stringify(intro, null, 2));
|
|
4054
4601
|
}
|
|
4055
4602
|
}
|
|
4056
4603
|
async load(config) {
|
|
4057
|
-
const introDir =
|
|
4604
|
+
const introDir = path14.join(getRaggrepDir(this.rootDir, config), "introspection");
|
|
4058
4605
|
try {
|
|
4059
|
-
const projectPath =
|
|
4060
|
-
const projectContent = await
|
|
4606
|
+
const projectPath = path14.join(introDir, "_project.json");
|
|
4607
|
+
const projectContent = await fs6.readFile(projectPath, "utf-8");
|
|
4061
4608
|
const projectData = JSON.parse(projectContent);
|
|
4062
4609
|
this.structure = projectData.structure;
|
|
4063
|
-
await this.loadFilesRecursive(
|
|
4610
|
+
await this.loadFilesRecursive(path14.join(introDir, "files"), "");
|
|
4064
4611
|
} catch {
|
|
4065
4612
|
this.structure = null;
|
|
4066
4613
|
this.files.clear();
|
|
@@ -4068,14 +4615,14 @@ class IntrospectionIndex {
|
|
|
4068
4615
|
}
|
|
4069
4616
|
async loadFilesRecursive(basePath, prefix) {
|
|
4070
4617
|
try {
|
|
4071
|
-
const entries = await
|
|
4618
|
+
const entries = await fs6.readdir(basePath, { withFileTypes: true });
|
|
4072
4619
|
for (const entry of entries) {
|
|
4073
|
-
const entryPath =
|
|
4620
|
+
const entryPath = path14.join(basePath, entry.name);
|
|
4074
4621
|
const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
4075
4622
|
if (entry.isDirectory()) {
|
|
4076
4623
|
await this.loadFilesRecursive(entryPath, relativePath);
|
|
4077
4624
|
} else if (entry.name.endsWith(".json")) {
|
|
4078
|
-
const content = await
|
|
4625
|
+
const content = await fs6.readFile(entryPath, "utf-8");
|
|
4079
4626
|
const intro = JSON.parse(content);
|
|
4080
4627
|
this.files.set(intro.filepath, intro);
|
|
4081
4628
|
}
|
|
@@ -4101,7 +4648,7 @@ var init_introspection2 = __esm(() => {
|
|
|
4101
4648
|
|
|
4102
4649
|
// src/app/indexer/watcher.ts
|
|
4103
4650
|
import { watch } from "chokidar";
|
|
4104
|
-
import * as
|
|
4651
|
+
import * as path15 from "path";
|
|
4105
4652
|
async function watchDirectory(rootDir, options = {}) {
|
|
4106
4653
|
const {
|
|
4107
4654
|
debounceMs = DEFAULT_DEBOUNCE_MS,
|
|
@@ -4112,7 +4659,7 @@ async function watchDirectory(rootDir, options = {}) {
|
|
|
4112
4659
|
onFileChange,
|
|
4113
4660
|
onError
|
|
4114
4661
|
} = options;
|
|
4115
|
-
rootDir =
|
|
4662
|
+
rootDir = path15.resolve(rootDir);
|
|
4116
4663
|
const config = await loadConfig(rootDir);
|
|
4117
4664
|
const indexLocation = getIndexLocation(rootDir);
|
|
4118
4665
|
const validExtensions = new Set(config.extensions);
|
|
@@ -4122,7 +4669,7 @@ async function watchDirectory(rootDir, options = {}) {
|
|
|
4122
4669
|
"**/.git/**"
|
|
4123
4670
|
];
|
|
4124
4671
|
function shouldWatchFile(filepath) {
|
|
4125
|
-
const ext =
|
|
4672
|
+
const ext = path15.extname(filepath);
|
|
4126
4673
|
return validExtensions.has(ext);
|
|
4127
4674
|
}
|
|
4128
4675
|
let isRunning = true;
|
|
@@ -4204,7 +4751,7 @@ async function watchDirectory(rootDir, options = {}) {
|
|
|
4204
4751
|
function handleFileEvent(event, filepath) {
|
|
4205
4752
|
if (!isRunning)
|
|
4206
4753
|
return;
|
|
4207
|
-
const relativePath =
|
|
4754
|
+
const relativePath = path15.relative(rootDir, filepath);
|
|
4208
4755
|
if (!shouldWatchFile(filepath)) {
|
|
4209
4756
|
return;
|
|
4210
4757
|
}
|
|
@@ -4282,8 +4829,8 @@ __export(exports_indexer, {
|
|
|
4282
4829
|
cleanupIndex: () => cleanupIndex
|
|
4283
4830
|
});
|
|
4284
4831
|
import { glob } from "glob";
|
|
4285
|
-
import * as
|
|
4286
|
-
import * as
|
|
4832
|
+
import * as fs7 from "fs/promises";
|
|
4833
|
+
import * as path16 from "path";
|
|
4287
4834
|
import * as os3 from "os";
|
|
4288
4835
|
async function parallelMap(items, processor, concurrency) {
|
|
4289
4836
|
const results = new Array(items.length);
|
|
@@ -4326,7 +4873,7 @@ async function indexDirectory(rootDir, options = {}) {
|
|
|
4326
4873
|
const quiet = options.quiet ?? false;
|
|
4327
4874
|
const concurrency = options.concurrency ?? DEFAULT_CONCURRENCY;
|
|
4328
4875
|
const logger = options.logger ? options.logger : quiet ? createSilentLogger() : createLogger({ verbose });
|
|
4329
|
-
rootDir =
|
|
4876
|
+
rootDir = path16.resolve(rootDir);
|
|
4330
4877
|
const location = getIndexLocation(rootDir);
|
|
4331
4878
|
logger.info(`Indexing directory: ${rootDir}`);
|
|
4332
4879
|
logger.info(`Index location: ${location.indexDir}`);
|
|
@@ -4378,12 +4925,12 @@ async function indexDirectory(rootDir, options = {}) {
|
|
|
4378
4925
|
rootDir,
|
|
4379
4926
|
config,
|
|
4380
4927
|
readFile: async (filepath) => {
|
|
4381
|
-
const fullPath =
|
|
4382
|
-
return
|
|
4928
|
+
const fullPath = path16.isAbsolute(filepath) ? filepath : path16.join(rootDir, filepath);
|
|
4929
|
+
return fs7.readFile(fullPath, "utf-8");
|
|
4383
4930
|
},
|
|
4384
4931
|
getFileStats: async (filepath) => {
|
|
4385
|
-
const fullPath =
|
|
4386
|
-
const stats = await
|
|
4932
|
+
const fullPath = path16.isAbsolute(filepath) ? filepath : path16.join(rootDir, filepath);
|
|
4933
|
+
const stats = await fs7.stat(fullPath);
|
|
4387
4934
|
return { lastModified: stats.mtime.toISOString() };
|
|
4388
4935
|
}
|
|
4389
4936
|
};
|
|
@@ -4408,7 +4955,7 @@ async function isIndexVersionCompatible(rootDir) {
|
|
|
4408
4955
|
const config = await loadConfig(rootDir);
|
|
4409
4956
|
const globalManifestPath = getGlobalManifestPath(rootDir, config);
|
|
4410
4957
|
try {
|
|
4411
|
-
const content = await
|
|
4958
|
+
const content = await fs7.readFile(globalManifestPath, "utf-8");
|
|
4412
4959
|
const manifest = JSON.parse(content);
|
|
4413
4960
|
return manifest.version === INDEX_SCHEMA_VERSION;
|
|
4414
4961
|
} catch {
|
|
@@ -4418,11 +4965,11 @@ async function isIndexVersionCompatible(rootDir) {
|
|
|
4418
4965
|
async function deleteIndex(rootDir) {
|
|
4419
4966
|
const indexDir = getRaggrepDir(rootDir);
|
|
4420
4967
|
try {
|
|
4421
|
-
await
|
|
4968
|
+
await fs7.rm(indexDir, { recursive: true, force: true });
|
|
4422
4969
|
} catch {}
|
|
4423
4970
|
}
|
|
4424
4971
|
async function resetIndex(rootDir) {
|
|
4425
|
-
rootDir =
|
|
4972
|
+
rootDir = path16.resolve(rootDir);
|
|
4426
4973
|
const status = await getIndexStatus(rootDir);
|
|
4427
4974
|
if (!status.exists) {
|
|
4428
4975
|
throw new Error(`No index found for ${rootDir}`);
|
|
@@ -4437,7 +4984,7 @@ async function ensureIndexFresh(rootDir, options = {}) {
|
|
|
4437
4984
|
const verbose = options.verbose ?? false;
|
|
4438
4985
|
const quiet = options.quiet ?? false;
|
|
4439
4986
|
const logger = options.logger ? options.logger : quiet ? createSilentLogger() : createLogger({ verbose });
|
|
4440
|
-
rootDir =
|
|
4987
|
+
rootDir = path16.resolve(rootDir);
|
|
4441
4988
|
const status = await getIndexStatus(rootDir);
|
|
4442
4989
|
if (!status.exists) {
|
|
4443
4990
|
logger.info(`No index found. Creating index...
|
|
@@ -4464,7 +5011,7 @@ async function ensureIndexFresh(rootDir, options = {}) {
|
|
|
4464
5011
|
const introspection = new IntrospectionIndex(rootDir);
|
|
4465
5012
|
await introspection.initialize();
|
|
4466
5013
|
const currentFiles = await findFiles(rootDir, config);
|
|
4467
|
-
const currentFileSet = new Set(currentFiles.map((f) =>
|
|
5014
|
+
const currentFileSet = new Set(currentFiles.map((f) => path16.relative(rootDir, f)));
|
|
4468
5015
|
let totalIndexed = 0;
|
|
4469
5016
|
let totalRemoved = 0;
|
|
4470
5017
|
let totalUnchanged = 0;
|
|
@@ -4494,13 +5041,13 @@ async function ensureIndexFresh(rootDir, options = {}) {
|
|
|
4494
5041
|
}
|
|
4495
5042
|
for (const filepath of filesToRemove) {
|
|
4496
5043
|
logger.debug(` Removing stale: ${filepath}`);
|
|
4497
|
-
const indexFilePath =
|
|
5044
|
+
const indexFilePath = path16.join(indexPath, filepath.replace(/\.[^.]+$/, ".json"));
|
|
4498
5045
|
try {
|
|
4499
|
-
await
|
|
5046
|
+
await fs7.unlink(indexFilePath);
|
|
4500
5047
|
} catch {}
|
|
4501
|
-
const symbolicFilePath =
|
|
5048
|
+
const symbolicFilePath = path16.join(indexPath, "symbolic", filepath.replace(/\.[^.]+$/, ".json"));
|
|
4502
5049
|
try {
|
|
4503
|
-
await
|
|
5050
|
+
await fs7.unlink(symbolicFilePath);
|
|
4504
5051
|
} catch {}
|
|
4505
5052
|
delete manifest.files[filepath];
|
|
4506
5053
|
totalRemoved++;
|
|
@@ -4509,12 +5056,12 @@ async function ensureIndexFresh(rootDir, options = {}) {
|
|
|
4509
5056
|
rootDir,
|
|
4510
5057
|
config,
|
|
4511
5058
|
readFile: async (filepath) => {
|
|
4512
|
-
const fullPath =
|
|
4513
|
-
return
|
|
5059
|
+
const fullPath = path16.isAbsolute(filepath) ? filepath : path16.join(rootDir, filepath);
|
|
5060
|
+
return fs7.readFile(fullPath, "utf-8");
|
|
4514
5061
|
},
|
|
4515
5062
|
getFileStats: async (filepath) => {
|
|
4516
|
-
const fullPath =
|
|
4517
|
-
const stats = await
|
|
5063
|
+
const fullPath = path16.isAbsolute(filepath) ? filepath : path16.join(rootDir, filepath);
|
|
5064
|
+
const stats = await fs7.stat(fullPath);
|
|
4518
5065
|
return { lastModified: stats.mtime.toISOString() };
|
|
4519
5066
|
},
|
|
4520
5067
|
getIntrospection: (filepath) => introspection.getFile(filepath)
|
|
@@ -4522,10 +5069,10 @@ async function ensureIndexFresh(rootDir, options = {}) {
|
|
|
4522
5069
|
const totalFiles = currentFiles.length;
|
|
4523
5070
|
for (let i = 0;i < currentFiles.length; i++) {
|
|
4524
5071
|
const filepath = currentFiles[i];
|
|
4525
|
-
const relativePath =
|
|
5072
|
+
const relativePath = path16.relative(rootDir, filepath);
|
|
4526
5073
|
const progress = `[${i + 1}/${totalFiles}]`;
|
|
4527
5074
|
try {
|
|
4528
|
-
const stats = await
|
|
5075
|
+
const stats = await fs7.stat(filepath);
|
|
4529
5076
|
const lastModified = stats.mtime.toISOString();
|
|
4530
5077
|
const existingEntry = manifest.files[relativePath];
|
|
4531
5078
|
if (existingEntry && existingEntry.lastModified === lastModified) {
|
|
@@ -4533,7 +5080,7 @@ async function ensureIndexFresh(rootDir, options = {}) {
|
|
|
4533
5080
|
continue;
|
|
4534
5081
|
}
|
|
4535
5082
|
logger.progress(` ${progress} Indexing: ${relativePath}`);
|
|
4536
|
-
const content = await
|
|
5083
|
+
const content = await fs7.readFile(filepath, "utf-8");
|
|
4537
5084
|
introspection.addFile(relativePath, content);
|
|
4538
5085
|
const fileIndex = await module.indexFile(relativePath, content, ctx);
|
|
4539
5086
|
if (fileIndex) {
|
|
@@ -4582,7 +5129,7 @@ async function indexWithModule(rootDir, files, module, config, verbose, introspe
|
|
|
4582
5129
|
};
|
|
4583
5130
|
const manifest = await loadModuleManifest(rootDir, module.id, config);
|
|
4584
5131
|
const indexPath = getModuleIndexPath(rootDir, module.id, config);
|
|
4585
|
-
const currentFileSet = new Set(files.map((f) =>
|
|
5132
|
+
const currentFileSet = new Set(files.map((f) => path16.relative(rootDir, f)));
|
|
4586
5133
|
const filesToRemove = [];
|
|
4587
5134
|
for (const filepath of Object.keys(manifest.files)) {
|
|
4588
5135
|
if (!currentFileSet.has(filepath)) {
|
|
@@ -4593,13 +5140,13 @@ async function indexWithModule(rootDir, files, module, config, verbose, introspe
|
|
|
4593
5140
|
logger.info(` Removing ${filesToRemove.length} stale entries...`);
|
|
4594
5141
|
for (const filepath of filesToRemove) {
|
|
4595
5142
|
logger.debug(` Removing: ${filepath}`);
|
|
4596
|
-
const indexFilePath =
|
|
5143
|
+
const indexFilePath = path16.join(indexPath, filepath.replace(/\.[^.]+$/, ".json"));
|
|
4597
5144
|
try {
|
|
4598
|
-
await
|
|
5145
|
+
await fs7.unlink(indexFilePath);
|
|
4599
5146
|
} catch {}
|
|
4600
|
-
const symbolicFilePath =
|
|
5147
|
+
const symbolicFilePath = path16.join(indexPath, "symbolic", filepath.replace(/\.[^.]+$/, ".json"));
|
|
4601
5148
|
try {
|
|
4602
|
-
await
|
|
5149
|
+
await fs7.unlink(symbolicFilePath);
|
|
4603
5150
|
} catch {}
|
|
4604
5151
|
delete manifest.files[filepath];
|
|
4605
5152
|
}
|
|
@@ -4609,12 +5156,12 @@ async function indexWithModule(rootDir, files, module, config, verbose, introspe
|
|
|
4609
5156
|
rootDir,
|
|
4610
5157
|
config,
|
|
4611
5158
|
readFile: async (filepath) => {
|
|
4612
|
-
const fullPath =
|
|
4613
|
-
return
|
|
5159
|
+
const fullPath = path16.isAbsolute(filepath) ? filepath : path16.join(rootDir, filepath);
|
|
5160
|
+
return fs7.readFile(fullPath, "utf-8");
|
|
4614
5161
|
},
|
|
4615
5162
|
getFileStats: async (filepath) => {
|
|
4616
|
-
const fullPath =
|
|
4617
|
-
const stats = await
|
|
5163
|
+
const fullPath = path16.isAbsolute(filepath) ? filepath : path16.join(rootDir, filepath);
|
|
5164
|
+
const stats = await fs7.stat(fullPath);
|
|
4618
5165
|
return { lastModified: stats.mtime.toISOString() };
|
|
4619
5166
|
},
|
|
4620
5167
|
getIntrospection: (filepath) => introspection.getFile(filepath)
|
|
@@ -4622,9 +5169,9 @@ async function indexWithModule(rootDir, files, module, config, verbose, introspe
|
|
|
4622
5169
|
const totalFiles = files.length;
|
|
4623
5170
|
let completedCount = 0;
|
|
4624
5171
|
const processFile = async (filepath, _index) => {
|
|
4625
|
-
const relativePath =
|
|
5172
|
+
const relativePath = path16.relative(rootDir, filepath);
|
|
4626
5173
|
try {
|
|
4627
|
-
const stats = await
|
|
5174
|
+
const stats = await fs7.stat(filepath);
|
|
4628
5175
|
const lastModified = stats.mtime.toISOString();
|
|
4629
5176
|
const existingEntry = manifest.files[relativePath];
|
|
4630
5177
|
if (existingEntry && existingEntry.lastModified === lastModified) {
|
|
@@ -4632,7 +5179,7 @@ async function indexWithModule(rootDir, files, module, config, verbose, introspe
|
|
|
4632
5179
|
logger.debug(` [${completedCount}/${totalFiles}] Skipped ${relativePath} (unchanged)`);
|
|
4633
5180
|
return { relativePath, status: "skipped" };
|
|
4634
5181
|
}
|
|
4635
|
-
const content = await
|
|
5182
|
+
const content = await fs7.readFile(filepath, "utf-8");
|
|
4636
5183
|
introspection.addFile(relativePath, content);
|
|
4637
5184
|
completedCount++;
|
|
4638
5185
|
logger.progress(` [${completedCount}/${totalFiles}] Processing: ${relativePath}`);
|
|
@@ -4700,7 +5247,7 @@ async function findFiles(rootDir, config) {
|
|
|
4700
5247
|
async function loadModuleManifest(rootDir, moduleId, config) {
|
|
4701
5248
|
const manifestPath = getModuleManifestPath(rootDir, moduleId, config);
|
|
4702
5249
|
try {
|
|
4703
|
-
const content = await
|
|
5250
|
+
const content = await fs7.readFile(manifestPath, "utf-8");
|
|
4704
5251
|
return JSON.parse(content);
|
|
4705
5252
|
} catch {
|
|
4706
5253
|
return {
|
|
@@ -4713,14 +5260,14 @@ async function loadModuleManifest(rootDir, moduleId, config) {
|
|
|
4713
5260
|
}
|
|
4714
5261
|
async function writeModuleManifest(rootDir, moduleId, manifest, config) {
|
|
4715
5262
|
const manifestPath = getModuleManifestPath(rootDir, moduleId, config);
|
|
4716
|
-
await
|
|
4717
|
-
await
|
|
5263
|
+
await fs7.mkdir(path16.dirname(manifestPath), { recursive: true });
|
|
5264
|
+
await fs7.writeFile(manifestPath, JSON.stringify(manifest, null, 2));
|
|
4718
5265
|
}
|
|
4719
5266
|
async function writeFileIndex(rootDir, moduleId, filepath, fileIndex, config) {
|
|
4720
5267
|
const indexPath = getModuleIndexPath(rootDir, moduleId, config);
|
|
4721
|
-
const indexFilePath =
|
|
4722
|
-
await
|
|
4723
|
-
await
|
|
5268
|
+
const indexFilePath = path16.join(indexPath, filepath.replace(/\.[^.]+$/, ".json"));
|
|
5269
|
+
await fs7.mkdir(path16.dirname(indexFilePath), { recursive: true });
|
|
5270
|
+
await fs7.writeFile(indexFilePath, JSON.stringify(fileIndex, null, 2));
|
|
4724
5271
|
}
|
|
4725
5272
|
async function updateGlobalManifest(rootDir, modules, config) {
|
|
4726
5273
|
const manifestPath = getGlobalManifestPath(rootDir, config);
|
|
@@ -4729,13 +5276,13 @@ async function updateGlobalManifest(rootDir, modules, config) {
|
|
|
4729
5276
|
lastUpdated: new Date().toISOString(),
|
|
4730
5277
|
modules: modules.map((m) => m.id)
|
|
4731
5278
|
};
|
|
4732
|
-
await
|
|
4733
|
-
await
|
|
5279
|
+
await fs7.mkdir(path16.dirname(manifestPath), { recursive: true });
|
|
5280
|
+
await fs7.writeFile(manifestPath, JSON.stringify(manifest, null, 2));
|
|
4734
5281
|
}
|
|
4735
5282
|
async function cleanupIndex(rootDir, options = {}) {
|
|
4736
5283
|
const verbose = options.verbose ?? false;
|
|
4737
5284
|
const logger = options.logger ?? createLogger({ verbose });
|
|
4738
|
-
rootDir =
|
|
5285
|
+
rootDir = path16.resolve(rootDir);
|
|
4739
5286
|
logger.info(`Cleaning up index in: ${rootDir}`);
|
|
4740
5287
|
const config = await loadConfig(rootDir);
|
|
4741
5288
|
await registerBuiltInModules();
|
|
@@ -4765,9 +5312,9 @@ async function cleanupModuleIndex(rootDir, moduleId, config, logger) {
|
|
|
4765
5312
|
const filesToRemove = [];
|
|
4766
5313
|
const updatedFiles = {};
|
|
4767
5314
|
for (const [filepath, entry] of Object.entries(manifest.files)) {
|
|
4768
|
-
const fullPath =
|
|
5315
|
+
const fullPath = path16.join(rootDir, filepath);
|
|
4769
5316
|
try {
|
|
4770
|
-
await
|
|
5317
|
+
await fs7.access(fullPath);
|
|
4771
5318
|
updatedFiles[filepath] = entry;
|
|
4772
5319
|
result.kept++;
|
|
4773
5320
|
} catch {
|
|
@@ -4777,9 +5324,9 @@ async function cleanupModuleIndex(rootDir, moduleId, config, logger) {
|
|
|
4777
5324
|
}
|
|
4778
5325
|
}
|
|
4779
5326
|
for (const filepath of filesToRemove) {
|
|
4780
|
-
const indexFilePath =
|
|
5327
|
+
const indexFilePath = path16.join(indexPath, filepath.replace(/\.[^.]+$/, ".json"));
|
|
4781
5328
|
try {
|
|
4782
|
-
await
|
|
5329
|
+
await fs7.unlink(indexFilePath);
|
|
4783
5330
|
} catch {}
|
|
4784
5331
|
}
|
|
4785
5332
|
manifest.files = updatedFiles;
|
|
@@ -4790,16 +5337,16 @@ async function cleanupModuleIndex(rootDir, moduleId, config, logger) {
|
|
|
4790
5337
|
}
|
|
4791
5338
|
async function cleanupEmptyDirectories(dir) {
|
|
4792
5339
|
try {
|
|
4793
|
-
const entries = await
|
|
5340
|
+
const entries = await fs7.readdir(dir, { withFileTypes: true });
|
|
4794
5341
|
for (const entry of entries) {
|
|
4795
5342
|
if (entry.isDirectory()) {
|
|
4796
|
-
const subDir =
|
|
5343
|
+
const subDir = path16.join(dir, entry.name);
|
|
4797
5344
|
await cleanupEmptyDirectories(subDir);
|
|
4798
5345
|
}
|
|
4799
5346
|
}
|
|
4800
|
-
const remainingEntries = await
|
|
5347
|
+
const remainingEntries = await fs7.readdir(dir);
|
|
4801
5348
|
if (remainingEntries.length === 0) {
|
|
4802
|
-
await
|
|
5349
|
+
await fs7.rmdir(dir);
|
|
4803
5350
|
return true;
|
|
4804
5351
|
}
|
|
4805
5352
|
return false;
|
|
@@ -4808,7 +5355,7 @@ async function cleanupEmptyDirectories(dir) {
|
|
|
4808
5355
|
}
|
|
4809
5356
|
}
|
|
4810
5357
|
async function getIndexStatus(rootDir) {
|
|
4811
|
-
rootDir =
|
|
5358
|
+
rootDir = path16.resolve(rootDir);
|
|
4812
5359
|
const config = await loadConfig(rootDir);
|
|
4813
5360
|
const location = getIndexLocation(rootDir);
|
|
4814
5361
|
const indexDir = location.indexDir;
|
|
@@ -4820,13 +5367,13 @@ async function getIndexStatus(rootDir) {
|
|
|
4820
5367
|
totalFiles: 0
|
|
4821
5368
|
};
|
|
4822
5369
|
try {
|
|
4823
|
-
await
|
|
5370
|
+
await fs7.access(indexDir);
|
|
4824
5371
|
} catch {
|
|
4825
5372
|
return status;
|
|
4826
5373
|
}
|
|
4827
5374
|
try {
|
|
4828
5375
|
const globalManifestPath = getGlobalManifestPath(rootDir, config);
|
|
4829
|
-
const content = await
|
|
5376
|
+
const content = await fs7.readFile(globalManifestPath, "utf-8");
|
|
4830
5377
|
const globalManifest = JSON.parse(content);
|
|
4831
5378
|
status.exists = true;
|
|
4832
5379
|
status.lastUpdated = globalManifest.lastUpdated;
|
|
@@ -4844,7 +5391,7 @@ async function getIndexStatus(rootDir) {
|
|
|
4844
5391
|
}
|
|
4845
5392
|
} catch {
|
|
4846
5393
|
try {
|
|
4847
|
-
const entries = await
|
|
5394
|
+
const entries = await fs7.readdir(path16.join(indexDir, "index"));
|
|
4848
5395
|
if (entries.length > 0) {
|
|
4849
5396
|
status.exists = true;
|
|
4850
5397
|
for (const entry of entries) {
|
|
@@ -4885,10 +5432,10 @@ __export(exports_search, {
|
|
|
4885
5432
|
search: () => search,
|
|
4886
5433
|
formatSearchResults: () => formatSearchResults
|
|
4887
5434
|
});
|
|
4888
|
-
import * as
|
|
4889
|
-
import * as
|
|
5435
|
+
import * as fs8 from "fs/promises";
|
|
5436
|
+
import * as path17 from "path";
|
|
4890
5437
|
async function search(rootDir, query, options = {}) {
|
|
4891
|
-
rootDir =
|
|
5438
|
+
rootDir = path17.resolve(rootDir);
|
|
4892
5439
|
const ensureFresh = options.ensureFresh ?? DEFAULT_SEARCH_OPTIONS.ensureFresh;
|
|
4893
5440
|
if (ensureFresh) {
|
|
4894
5441
|
await ensureIndexFresh(rootDir, { quiet: true });
|
|
@@ -4941,9 +5488,9 @@ function createSearchContext(rootDir, moduleId, config) {
|
|
|
4941
5488
|
config,
|
|
4942
5489
|
loadFileIndex: async (filepath) => {
|
|
4943
5490
|
const hasExtension = /\.[^./]+$/.test(filepath);
|
|
4944
|
-
const indexFilePath = hasExtension ?
|
|
5491
|
+
const indexFilePath = hasExtension ? path17.join(indexPath, filepath.replace(/\.[^.]+$/, ".json")) : path17.join(indexPath, filepath + ".json");
|
|
4945
5492
|
try {
|
|
4946
|
-
const content = await
|
|
5493
|
+
const content = await fs8.readFile(indexFilePath, "utf-8");
|
|
4947
5494
|
return JSON.parse(content);
|
|
4948
5495
|
} catch {
|
|
4949
5496
|
return null;
|
|
@@ -4953,7 +5500,7 @@ function createSearchContext(rootDir, moduleId, config) {
|
|
|
4953
5500
|
const files = [];
|
|
4954
5501
|
await traverseDirectory(indexPath, files, indexPath);
|
|
4955
5502
|
return files.filter((f) => f.endsWith(".json") && !f.endsWith("manifest.json")).map((f) => {
|
|
4956
|
-
const relative4 =
|
|
5503
|
+
const relative4 = path17.relative(indexPath, f);
|
|
4957
5504
|
return relative4.replace(/\.json$/, "");
|
|
4958
5505
|
});
|
|
4959
5506
|
}
|
|
@@ -4961,9 +5508,9 @@ function createSearchContext(rootDir, moduleId, config) {
|
|
|
4961
5508
|
}
|
|
4962
5509
|
async function traverseDirectory(dir, files, basePath) {
|
|
4963
5510
|
try {
|
|
4964
|
-
const entries = await
|
|
5511
|
+
const entries = await fs8.readdir(dir, { withFileTypes: true });
|
|
4965
5512
|
for (const entry of entries) {
|
|
4966
|
-
const fullPath =
|
|
5513
|
+
const fullPath = path17.join(dir, entry.name);
|
|
4967
5514
|
if (entry.isDirectory()) {
|
|
4968
5515
|
await traverseDirectory(fullPath, files, basePath);
|
|
4969
5516
|
} else if (entry.isFile()) {
|
|
@@ -4975,7 +5522,7 @@ async function traverseDirectory(dir, files, basePath) {
|
|
|
4975
5522
|
async function loadGlobalManifest(rootDir, config) {
|
|
4976
5523
|
const manifestPath = getGlobalManifestPath(rootDir, config);
|
|
4977
5524
|
try {
|
|
4978
|
-
const content = await
|
|
5525
|
+
const content = await fs8.readFile(manifestPath, "utf-8");
|
|
4979
5526
|
return JSON.parse(content);
|
|
4980
5527
|
} catch {
|
|
4981
5528
|
return null;
|
|
@@ -5041,7 +5588,7 @@ init_logger();
|
|
|
5041
5588
|
// package.json
|
|
5042
5589
|
var package_default = {
|
|
5043
5590
|
name: "raggrep",
|
|
5044
|
-
version: "0.
|
|
5591
|
+
version: "0.7.0",
|
|
5045
5592
|
description: "Local filesystem-based RAG system for codebases - semantic search using local embeddings",
|
|
5046
5593
|
type: "module",
|
|
5047
5594
|
main: "./dist/index.js",
|
|
@@ -5502,4 +6049,4 @@ Run 'raggrep <command> --help' for more information.
|
|
|
5502
6049
|
}
|
|
5503
6050
|
main();
|
|
5504
6051
|
|
|
5505
|
-
//# debugId=
|
|
6052
|
+
//# debugId=4DE86C1D7DC4E21964756E2164756E21
|