(
query: string,
limit: number,
filters?: SearchFilters
)
| 1098 | } |
| 1099 | |
| 1100 | private async keywordSearch( |
| 1101 | query: string, |
| 1102 | limit: number, |
| 1103 | filters?: SearchFilters |
| 1104 | ): Promise<{ chunk: CodeChunk; score: number }[]> { |
| 1105 | if (!this.fuseIndex || this.chunks.length === 0) { |
| 1106 | return []; |
| 1107 | } |
| 1108 | |
| 1109 | let fuseResults = this.fuseIndex.search(query); |
| 1110 | |
| 1111 | if (filters) { |
| 1112 | fuseResults = fuseResults.filter((r) => { |
| 1113 | const chunk = r.item; |
| 1114 | |
| 1115 | if (filters.componentType && chunk.componentType !== filters.componentType) { |
| 1116 | return false; |
| 1117 | } |
| 1118 | if (filters.layer && chunk.layer !== filters.layer) { |
| 1119 | return false; |
| 1120 | } |
| 1121 | if (filters.framework && chunk.framework !== filters.framework) { |
| 1122 | return false; |
| 1123 | } |
| 1124 | if (filters.language && chunk.language !== filters.language) { |
| 1125 | return false; |
| 1126 | } |
| 1127 | if (filters.tags && filters.tags.length > 0) { |
| 1128 | const chunkTags = chunk.tags || []; |
| 1129 | if (!filters.tags.some((tag) => chunkTags.includes(tag))) { |
| 1130 | return false; |
| 1131 | } |
| 1132 | } |
| 1133 | |
| 1134 | return true; |
| 1135 | }); |
| 1136 | } |
| 1137 | |
| 1138 | return fuseResults.slice(0, limit).map((r) => { |
| 1139 | const chunk = r.item; |
| 1140 | let score = 1 - (r.score || 0); |
| 1141 | |
| 1142 | // Boost exact matches on class name or file path |
| 1143 | const queryLower = query.toLowerCase(); |
| 1144 | const fileName = path.basename(chunk.filePath).toLowerCase(); |
| 1145 | const relativePathLower = chunk.relativePath.toLowerCase(); |
| 1146 | const componentName = chunk.metadata?.componentName?.toLowerCase() || ''; |
| 1147 | |
| 1148 | // Exact class name match |
| 1149 | if (componentName && queryLower === componentName) { |
| 1150 | score = Math.min(1.0, score + 0.3); |
| 1151 | } |
| 1152 | |
| 1153 | // Exact file name match |
| 1154 | if ( |
| 1155 | fileName === queryLower || |
| 1156 | fileName.replace(/\.ts$/, '') === queryLower.replace(/\.ts$/, '') |
| 1157 | ) { |
no test coverage detected