repoburg 1.0.55 → 1.0.57

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.
Files changed (186) hide show
  1. package/backend/.env +1 -0
  2. package/backend/coverage/clover.xml +2409 -2355
  3. package/backend/coverage/coverage-final.json +99 -96
  4. package/backend/coverage/lcov-report/index.html +356 -341
  5. package/backend/coverage/lcov-report/src/action-execution/action-execution.module.ts.html +12 -12
  6. package/backend/coverage/lcov-report/src/action-execution/action-execution.service.ts.html +140 -62
  7. package/backend/coverage/lcov-report/src/action-execution/index.html +28 -28
  8. package/backend/coverage/lcov-report/src/ai-actions/ai-action-batch.service.ts.html +188 -188
  9. package/backend/coverage/lcov-report/src/ai-actions/ai-action-creation.service.ts.html +284 -236
  10. package/backend/coverage/lcov-report/src/ai-actions/ai-actions.controller.ts.html +109 -109
  11. package/backend/coverage/lcov-report/src/ai-actions/ai-actions.module.ts.html +28 -28
  12. package/backend/coverage/lcov-report/src/ai-actions/ai-actions.service.ts.html +193 -193
  13. package/backend/coverage/lcov-report/src/ai-actions/index.html +61 -61
  14. package/backend/coverage/lcov-report/src/app.controller.ts.html +24 -24
  15. package/backend/coverage/lcov-report/src/app.module.ts.html +68 -65
  16. package/backend/coverage/lcov-report/src/app.service.ts.html +46 -13
  17. package/backend/coverage/lcov-report/src/application-state/application-state.controller.ts.html +87 -33
  18. package/backend/coverage/lcov-report/src/application-state/application-state.module.ts.html +18 -18
  19. package/backend/coverage/lcov-report/src/application-state/application-state.service.ts.html +113 -68
  20. package/backend/coverage/lcov-report/src/application-state/dto/index.html +42 -27
  21. package/backend/coverage/lcov-report/src/application-state/dto/set-auto-context-fetch-enabled.dto.ts.html +12 -12
  22. package/backend/coverage/lcov-report/src/application-state/dto/set-orchestration-timeout.dto.ts.html +103 -0
  23. package/backend/coverage/lcov-report/src/application-state/dto/set-theme.dto.ts.html +12 -12
  24. package/backend/coverage/lcov-report/src/application-state/dto/set-websocket-enabled.dto.ts.html +12 -12
  25. package/backend/coverage/lcov-report/src/application-state/index.html +37 -37
  26. package/backend/coverage/lcov-report/src/context-generation/context-generation.module.ts.html +16 -16
  27. package/backend/coverage/lcov-report/src/context-generation/context-generation.service.ts.html +222 -222
  28. package/backend/coverage/lcov-report/src/context-generation/index.html +28 -28
  29. package/backend/coverage/lcov-report/src/context-snippets/context-snippets.controller.ts.html +31 -31
  30. package/backend/coverage/lcov-report/src/context-snippets/context-snippets.module.ts.html +20 -20
  31. package/backend/coverage/lcov-report/src/context-snippets/context-snippets.service.ts.html +26 -26
  32. package/backend/coverage/lcov-report/src/context-snippets/dto/context-snippet.dto.ts.html +28 -28
  33. package/backend/coverage/lcov-report/src/context-snippets/dto/index.html +13 -13
  34. package/backend/coverage/lcov-report/src/context-snippets/index.html +31 -31
  35. package/backend/coverage/lcov-report/src/context-templates/context-templates.controller.ts.html +45 -45
  36. package/backend/coverage/lcov-report/src/context-templates/context-templates.module.ts.html +20 -20
  37. package/backend/coverage/lcov-report/src/context-templates/context-templates.service.ts.html +87 -84
  38. package/backend/coverage/lcov-report/src/context-templates/dto/context-template.dto.ts.html +48 -48
  39. package/backend/coverage/lcov-report/src/context-templates/dto/index.html +13 -13
  40. package/backend/coverage/lcov-report/src/context-templates/index.html +36 -36
  41. package/backend/coverage/lcov-report/src/core-entities/ai-action.entity.ts.html +48 -48
  42. package/backend/coverage/lcov-report/src/core-entities/application-state.entity.ts.html +14 -14
  43. package/backend/coverage/lcov-report/src/core-entities/base.entity.ts.html +22 -22
  44. package/backend/coverage/lcov-report/src/core-entities/context-snippet.entity.ts.html +18 -18
  45. package/backend/coverage/lcov-report/src/core-entities/context-template.entity.ts.html +52 -52
  46. package/backend/coverage/lcov-report/src/core-entities/custom-snippet.entity.ts.html +20 -20
  47. package/backend/coverage/lcov-report/src/core-entities/execution-log.entity.ts.html +26 -26
  48. package/backend/coverage/lcov-report/src/core-entities/index.html +112 -112
  49. package/backend/coverage/lcov-report/src/core-entities/index.ts.html +28 -28
  50. package/backend/coverage/lcov-report/src/core-entities/project.entity.ts.html +24 -24
  51. package/backend/coverage/lcov-report/src/core-entities/session-input.entity.ts.html +59 -50
  52. package/backend/coverage/lcov-report/src/core-entities/session.entity.ts.html +56 -56
  53. package/backend/coverage/lcov-report/src/core-entities/system-prompt.entity.ts.html +28 -28
  54. package/backend/coverage/lcov-report/src/custom-snippets/custom-snippets.controller.ts.html +30 -30
  55. package/backend/coverage/lcov-report/src/custom-snippets/custom-snippets.module.ts.html +18 -18
  56. package/backend/coverage/lcov-report/src/custom-snippets/custom-snippets.service.ts.html +20 -20
  57. package/backend/coverage/lcov-report/src/custom-snippets/dto/custom-snippet.dto.ts.html +28 -28
  58. package/backend/coverage/lcov-report/src/custom-snippets/dto/index.html +13 -13
  59. package/backend/coverage/lcov-report/src/custom-snippets/index.html +32 -32
  60. package/backend/coverage/lcov-report/src/events/events.gateway.ts.html +46 -46
  61. package/backend/coverage/lcov-report/src/events/events.module.ts.html +12 -12
  62. package/backend/coverage/lcov-report/src/events/index.html +28 -28
  63. package/backend/coverage/lcov-report/src/execution-logs/dto/execution-log.dto.ts.html +1 -1
  64. package/backend/coverage/lcov-report/src/execution-logs/dto/index.html +1 -1
  65. package/backend/coverage/lcov-report/src/execution-logs/execution-logs.controller.ts.html +18 -18
  66. package/backend/coverage/lcov-report/src/execution-logs/execution-logs.module.ts.html +18 -18
  67. package/backend/coverage/lcov-report/src/execution-logs/execution-logs.service.ts.html +32 -32
  68. package/backend/coverage/lcov-report/src/execution-logs/index.html +33 -33
  69. package/backend/coverage/lcov-report/src/http-exception.filter.ts.html +55 -55
  70. package/backend/coverage/lcov-report/src/index.html +44 -44
  71. package/backend/coverage/lcov-report/src/llm-response-parser/dto/ai-action.dto.ts.html +67 -67
  72. package/backend/coverage/lcov-report/src/llm-response-parser/dto/index.html +21 -21
  73. package/backend/coverage/lcov-report/src/llm-response-parser/errors/index.html +17 -17
  74. package/backend/coverage/lcov-report/src/llm-response-parser/errors/parsing.error.ts.html +19 -19
  75. package/backend/coverage/lcov-report/src/llm-response-parser/index.html +35 -35
  76. package/backend/coverage/lcov-report/src/llm-response-parser/llm-response-parser.module.ts.html +12 -12
  77. package/backend/coverage/lcov-report/src/llm-response-parser/llm-response-parser.service.ts.html +208 -208
  78. package/backend/coverage/lcov-report/src/llm-response-parser/parsing.constants.ts.html +38 -38
  79. package/backend/coverage/lcov-report/src/llm-responses/dto/index.html +21 -21
  80. package/backend/coverage/lcov-report/src/llm-responses/dto/submit-llm-response.dto.ts.html +28 -28
  81. package/backend/coverage/lcov-report/src/llm-responses/index.html +38 -38
  82. package/backend/coverage/lcov-report/src/llm-responses/llm-responses.controller.ts.html +24 -24
  83. package/backend/coverage/lcov-report/src/llm-responses/llm-responses.module.ts.html +38 -35
  84. package/backend/coverage/lcov-report/src/llm-responses/llm-responses.service.ts.html +107 -86
  85. package/backend/coverage/lcov-report/src/main.ts.html +1 -1
  86. package/backend/coverage/lcov-report/src/orchestration/dto/index.html +13 -13
  87. package/backend/coverage/lcov-report/src/orchestration/dto/orchestration.dto.ts.html +30 -45
  88. package/backend/coverage/lcov-report/src/orchestration/index.html +74 -74
  89. package/backend/coverage/lcov-report/src/orchestration/orchestration-fs.service.ts.html +245 -128
  90. package/backend/coverage/lcov-report/src/orchestration/orchestration-parser.service.ts.html +32 -200
  91. package/backend/coverage/lcov-report/src/orchestration/orchestration.controller.ts.html +72 -102
  92. package/backend/coverage/lcov-report/src/orchestration/orchestration.module.ts.html +35 -38
  93. package/backend/coverage/lcov-report/src/orchestration/orchestration.service.ts.html +317 -425
  94. package/backend/coverage/lcov-report/src/orchestration/orchestration.types.ts.html +41 -35
  95. package/backend/coverage/lcov-report/src/projects/dto/index.html +13 -13
  96. package/backend/coverage/lcov-report/src/projects/dto/project.dto.ts.html +20 -20
  97. package/backend/coverage/lcov-report/src/projects/index.html +32 -32
  98. package/backend/coverage/lcov-report/src/projects/projects.controller.ts.html +28 -28
  99. package/backend/coverage/lcov-report/src/projects/projects.module.ts.html +18 -18
  100. package/backend/coverage/lcov-report/src/projects/projects.service.ts.html +20 -20
  101. package/backend/coverage/lcov-report/src/seeding/context-template-seeding.service.ts.html +22 -22
  102. package/backend/coverage/lcov-report/src/seeding/custom-snippet-seeding.service.ts.html +21 -21
  103. package/backend/coverage/lcov-report/src/seeding/data/context-templates/default-followup_ad-hoc-focused-context.ts.html +1 -1
  104. package/backend/coverage/lcov-report/src/seeding/data/context-templates/default-initial_condensed-project-context.ts.html +1 -1
  105. package/backend/coverage/lcov-report/src/seeding/data/context-templates/default-initial_full-project-context.ts.html +1 -1
  106. package/backend/coverage/lcov-report/src/seeding/data/context-templates/index.html +1 -1
  107. package/backend/coverage/lcov-report/src/seeding/data/context-templates/pm-context.ts.html +1 -1
  108. package/backend/coverage/lcov-report/src/seeding/data/context-templates/pr-description.ts.html +1 -1
  109. package/backend/coverage/lcov-report/src/seeding/data/context-templates/sample_focused-tree.ts.html +1 -1
  110. package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/default_rglob.ts.html +1 -1
  111. package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/git-diff.ts.html +1 -1
  112. package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/index.html +1 -1
  113. package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/rg-exclude.ts.html +1 -1
  114. package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/rg-search-glob.ts.html +1 -1
  115. package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/rg-search.ts.html +1 -1
  116. package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/run-command.ts.html +1 -1
  117. package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/tree.ts.html +1 -1
  118. package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/usr-adhoc-incl.ts.html +1 -1
  119. package/backend/coverage/lcov-report/src/seeding/data/custom-snippets/usr-input-incl.ts.html +1 -1
  120. package/backend/coverage/lcov-report/src/seeding/data/system-prompts/codebase-explorer.ts.html +1 -1
  121. package/backend/coverage/lcov-report/src/seeding/data/system-prompts/default_multi-file-action-generator-with-requester.ts.html +8 -2
  122. package/backend/coverage/lcov-report/src/seeding/data/system-prompts/index.html +3 -3
  123. package/backend/coverage/lcov-report/src/seeding/data/system-prompts/packup.ts.html +1 -1
  124. package/backend/coverage/lcov-report/src/seeding/data/system-prompts/refactor-split.ts.html +244 -0
  125. package/backend/coverage/lcov-report/src/seeding/index.html +47 -47
  126. package/backend/coverage/lcov-report/src/seeding/seeding.module.ts.html +24 -24
  127. package/backend/coverage/lcov-report/src/seeding/seeding.service.ts.html +27 -27
  128. package/backend/coverage/lcov-report/src/seeding/system-prompt-seeding.service.ts.html +21 -21
  129. package/backend/coverage/lcov-report/src/session-followup/index.html +28 -28
  130. package/backend/coverage/lcov-report/src/session-followup/session-followup.module.ts.html +22 -22
  131. package/backend/coverage/lcov-report/src/session-followup/session-followup.service.ts.html +44 -41
  132. package/backend/coverage/lcov-report/src/session-inputs/dto/index.html +13 -13
  133. package/backend/coverage/lcov-report/src/session-inputs/dto/session-input.dto.ts.html +40 -28
  134. package/backend/coverage/lcov-report/src/session-inputs/index.html +50 -50
  135. package/backend/coverage/lcov-report/src/session-inputs/session-input-context.service.ts.html +168 -156
  136. package/backend/coverage/lcov-report/src/session-inputs/session-inputs.controller.ts.html +36 -36
  137. package/backend/coverage/lcov-report/src/session-inputs/session-inputs.module.ts.html +40 -37
  138. package/backend/coverage/lcov-report/src/session-inputs/session-inputs.service.ts.html +242 -236
  139. package/backend/coverage/lcov-report/src/session-transfer/index.html +22 -22
  140. package/backend/coverage/lcov-report/src/session-transfer/session-transfer.module.ts.html +16 -16
  141. package/backend/coverage/lcov-report/src/session-transfer/session-transfer.service.ts.html +30 -30
  142. package/backend/coverage/lcov-report/src/sessions/dto/index.html +21 -21
  143. package/backend/coverage/lcov-report/src/sessions/dto/session.dto.ts.html +54 -54
  144. package/backend/coverage/lcov-report/src/sessions/index.html +39 -39
  145. package/backend/coverage/lcov-report/src/sessions/sessions.controller.ts.html +55 -55
  146. package/backend/coverage/lcov-report/src/sessions/sessions.module.ts.html +30 -30
  147. package/backend/coverage/lcov-report/src/sessions/sessions.service.ts.html +120 -120
  148. package/backend/coverage/lcov-report/src/system-prompts/dto/index.html +19 -19
  149. package/backend/coverage/lcov-report/src/system-prompts/dto/system-prompt.dto.ts.html +38 -29
  150. package/backend/coverage/lcov-report/src/system-prompts/index.html +37 -37
  151. package/backend/coverage/lcov-report/src/system-prompts/system-prompts.controller.ts.html +34 -34
  152. package/backend/coverage/lcov-report/src/system-prompts/system-prompts.module.ts.html +20 -20
  153. package/backend/coverage/lcov-report/src/system-prompts/system-prompts.service.ts.html +62 -62
  154. package/backend/coverage/lcov-report/src/timeout.interceptor.ts.html +1 -1
  155. package/backend/coverage/lcov-report/src/utils/fuzzy-search.ts.html +310 -0
  156. package/backend/coverage/lcov-report/src/utils/index.html +131 -0
  157. package/backend/coverage/lcov-report/src/utils/index.ts.html +88 -0
  158. package/backend/coverage/lcov-report/src/workspace/dto/index.html +13 -13
  159. package/backend/coverage/lcov-report/src/workspace/dto/search-workspace.dto.ts.html +24 -24
  160. package/backend/coverage/lcov-report/src/workspace/index.html +37 -37
  161. package/backend/coverage/lcov-report/src/workspace/workspace.controller.ts.html +26 -26
  162. package/backend/coverage/lcov-report/src/workspace/workspace.module.ts.html +16 -16
  163. package/backend/coverage/lcov-report/src/workspace/workspace.service.ts.html +259 -214
  164. package/backend/coverage/lcov.info +3284 -3186
  165. package/backend/dist/action-execution/action-execution.service.d.ts +2 -0
  166. package/backend/dist/action-execution/action-execution.service.js +31 -13
  167. package/backend/dist/action-execution/action-execution.service.js.map +1 -1
  168. package/backend/dist/context-generation/context-generation.service.d.ts +2 -2
  169. package/backend/dist/context-generation/context-generation.service.js.map +1 -1
  170. package/backend/dist/orchestration/orchestration.service.js +1 -0
  171. package/backend/dist/orchestration/orchestration.service.js.map +1 -1
  172. package/backend/dist/session-inputs/dto/session-input.dto.d.ts +1 -0
  173. package/backend/dist/session-inputs/dto/session-input.dto.js +5 -0
  174. package/backend/dist/session-inputs/dto/session-input.dto.js.map +1 -1
  175. package/backend/dist/session-inputs/session-input-context.service.js +4 -5
  176. package/backend/dist/session-inputs/session-input-context.service.js.map +1 -1
  177. package/backend/dist/session-inputs/session-inputs.service.js +2 -1
  178. package/backend/dist/session-inputs/session-inputs.service.js.map +1 -1
  179. package/backend/dist/tsconfig.build.tsbuildinfo +1 -1
  180. package/backend/dist/utils/fuzzy-search.js +13 -4
  181. package/backend/dist/utils/fuzzy-search.js.map +1 -1
  182. package/backend/dist/workspace/workspace.service.d.ts +1 -0
  183. package/backend/dist/workspace/workspace.service.js +14 -3
  184. package/backend/dist/workspace/workspace.service.js.map +1 -1
  185. package/package.json +1 -1
  186. package/orchestration-test.txt +0 -3
@@ -23,30 +23,30 @@
23
23
  <div class='clearfix'>
24
24
 
25
25
  <div class='fl pad1y space-right2'>
26
- <span class="strong">0% </span>
26
+ <span class="strong">100% </span>
27
27
  <span class="quiet">Statements</span>
28
- <span class='fraction'>0/82</span>
28
+ <span class='fraction'>101/101</span>
29
29
  </div>
30
30
 
31
31
 
32
32
  <div class='fl pad1y space-right2'>
33
- <span class="strong">0% </span>
33
+ <span class="strong">95.45% </span>
34
34
  <span class="quiet">Branches</span>
35
- <span class='fraction'>0/27</span>
35
+ <span class='fraction'>21/22</span>
36
36
  </div>
37
37
 
38
38
 
39
39
  <div class='fl pad1y space-right2'>
40
- <span class="strong">0% </span>
40
+ <span class="strong">100% </span>
41
41
  <span class="quiet">Functions</span>
42
- <span class='fraction'>0/15</span>
42
+ <span class='fraction'>19/19</span>
43
43
  </div>
44
44
 
45
45
 
46
46
  <div class='fl pad1y space-right2'>
47
- <span class="strong">0% </span>
47
+ <span class="strong">100% </span>
48
48
  <span class="quiet">Lines</span>
49
- <span class='fraction'>0/75</span>
49
+ <span class='fraction'>95/95</span>
50
50
  </div>
51
51
 
52
52
 
@@ -61,7 +61,7 @@
61
61
  </div>
62
62
  </template>
63
63
  </div>
64
- <div class='status-line low'></div>
64
+ <div class='status-line high'></div>
65
65
  <pre><table class="coverage">
66
66
  <tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
67
67
  <a name='L2'></a><a href='#L2'>2</a>
@@ -268,15 +268,31 @@
268
268
  <a name='L203'></a><a href='#L203'>203</a>
269
269
  <a name='L204'></a><a href='#L204'>204</a>
270
270
  <a name='L205'></a><a href='#L205'>205</a>
271
- <a name='L206'></a><a href='#L206'>206</a></td><td class="line-coverage quiet"><span class="cline-any cline-no">&nbsp;</span>
272
- <span class="cline-any cline-no">&nbsp;</span>
273
- <span class="cline-any cline-no">&nbsp;</span>
271
+ <a name='L206'></a><a href='#L206'>206</a>
272
+ <a name='L207'></a><a href='#L207'>207</a>
273
+ <a name='L208'></a><a href='#L208'>208</a>
274
+ <a name='L209'></a><a href='#L209'>209</a>
275
+ <a name='L210'></a><a href='#L210'>210</a>
276
+ <a name='L211'></a><a href='#L211'>211</a>
277
+ <a name='L212'></a><a href='#L212'>212</a>
278
+ <a name='L213'></a><a href='#L213'>213</a>
279
+ <a name='L214'></a><a href='#L214'>214</a>
280
+ <a name='L215'></a><a href='#L215'>215</a>
281
+ <a name='L216'></a><a href='#L216'>216</a>
282
+ <a name='L217'></a><a href='#L217'>217</a>
283
+ <a name='L218'></a><a href='#L218'>218</a>
284
+ <a name='L219'></a><a href='#L219'>219</a>
285
+ <a name='L220'></a><a href='#L220'>220</a>
286
+ <a name='L221'></a><a href='#L221'>221</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">7x</span>
287
+ <span class="cline-any cline-yes">7x</span>
274
288
  <span class="cline-any cline-neutral">&nbsp;</span>
275
289
  <span class="cline-any cline-neutral">&nbsp;</span>
276
290
  <span class="cline-any cline-neutral">&nbsp;</span>
277
291
  <span class="cline-any cline-neutral">&nbsp;</span>
278
- <span class="cline-any cline-no">&nbsp;</span>
279
- <span class="cline-any cline-no">&nbsp;</span>
292
+ <span class="cline-any cline-yes">7x</span>
293
+ <span class="cline-any cline-yes">7x</span>
294
+ <span class="cline-any cline-yes">7x</span>
295
+ <span class="cline-any cline-yes">7x</span>
280
296
  <span class="cline-any cline-neutral">&nbsp;</span>
281
297
  <span class="cline-any cline-neutral">&nbsp;</span>
282
298
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -284,204 +300,219 @@
284
300
  <span class="cline-any cline-neutral">&nbsp;</span>
285
301
  <span class="cline-any cline-neutral">&nbsp;</span>
286
302
  <span class="cline-any cline-neutral">&nbsp;</span>
287
- <span class="cline-any cline-no">&nbsp;</span>
288
- <span class="cline-any cline-no">&nbsp;</span>
289
- <span class="cline-any cline-no">&nbsp;</span>
303
+ <span class="cline-any cline-yes">7x</span>
304
+ <span class="cline-any cline-yes">22x</span>
305
+ <span class="cline-any cline-yes">22x</span>
290
306
  <span class="cline-any cline-neutral">&nbsp;</span>
291
307
  <span class="cline-any cline-neutral">&nbsp;</span>
292
308
  <span class="cline-any cline-neutral">&nbsp;</span>
293
- <span class="cline-any cline-no">&nbsp;</span>
294
- <span class="cline-any cline-no">&nbsp;</span>
295
- <span class="cline-any cline-no">&nbsp;</span>
309
+ <span class="cline-any cline-yes">22x</span>
310
+ <span class="cline-any cline-yes">22x</span>
311
+ <span class="cline-any cline-yes">22x</span>
296
312
  <span class="cline-any cline-neutral">&nbsp;</span>
297
313
  <span class="cline-any cline-neutral">&nbsp;</span>
298
- <span class="cline-any cline-no">&nbsp;</span>
314
+ <span class="cline-any cline-yes">22x</span>
299
315
  <span class="cline-any cline-neutral">&nbsp;</span>
300
316
  <span class="cline-any cline-neutral">&nbsp;</span>
301
317
  <span class="cline-any cline-neutral">&nbsp;</span>
302
- <span class="cline-any cline-no">&nbsp;</span>
303
- <span class="cline-any cline-no">&nbsp;</span>
304
- <span class="cline-any cline-no">&nbsp;</span>
305
318
  <span class="cline-any cline-neutral">&nbsp;</span>
306
319
  <span class="cline-any cline-neutral">&nbsp;</span>
307
320
  <span class="cline-any cline-neutral">&nbsp;</span>
308
- <span class="cline-any cline-no">&nbsp;</span>
321
+ <span class="cline-any cline-yes">13x</span>
322
+ <span class="cline-any cline-yes">13x</span>
323
+ <span class="cline-any cline-yes">13x</span>
324
+ <span class="cline-any cline-yes">2x</span>
325
+ <span class="cline-any cline-yes">2x</span>
326
+ <span class="cline-any cline-yes">2x</span>
327
+ <span class="cline-any cline-yes">2x</span>
309
328
  <span class="cline-any cline-neutral">&nbsp;</span>
310
- <span class="cline-any cline-no">&nbsp;</span>
311
- <span class="cline-any cline-no">&nbsp;</span>
312
- <span class="cline-any cline-no">&nbsp;</span>
329
+ <span class="cline-any cline-yes">11x</span>
313
330
  <span class="cline-any cline-neutral">&nbsp;</span>
314
331
  <span class="cline-any cline-neutral">&nbsp;</span>
315
332
  <span class="cline-any cline-neutral">&nbsp;</span>
316
- <span class="cline-any cline-no">&nbsp;</span>
317
333
  <span class="cline-any cline-neutral">&nbsp;</span>
318
334
  <span class="cline-any cline-neutral">&nbsp;</span>
335
+ <span class="cline-any cline-yes">13x</span>
319
336
  <span class="cline-any cline-neutral">&nbsp;</span>
320
337
  <span class="cline-any cline-neutral">&nbsp;</span>
338
+ <span class="cline-any cline-yes">13x</span>
321
339
  <span class="cline-any cline-neutral">&nbsp;</span>
340
+ <span class="cline-any cline-yes">13x</span>
341
+ <span class="cline-any cline-yes">13x</span>
342
+ <span class="cline-any cline-yes">13x</span>
322
343
  <span class="cline-any cline-neutral">&nbsp;</span>
323
- <span class="cline-any cline-no">&nbsp;</span>
324
- <span class="cline-any cline-no">&nbsp;</span>
325
344
  <span class="cline-any cline-neutral">&nbsp;</span>
326
- <span class="cline-any cline-no">&nbsp;</span>
327
- <span class="cline-any cline-no">&nbsp;</span>
328
- <span class="cline-any cline-no">&nbsp;</span>
329
- <span class="cline-any cline-no">&nbsp;</span>
330
345
  <span class="cline-any cline-neutral">&nbsp;</span>
331
- <span class="cline-any cline-no">&nbsp;</span>
332
346
  <span class="cline-any cline-neutral">&nbsp;</span>
347
+ <span class="cline-any cline-yes">11x</span>
333
348
  <span class="cline-any cline-neutral">&nbsp;</span>
334
349
  <span class="cline-any cline-neutral">&nbsp;</span>
335
- <span class="cline-any cline-no">&nbsp;</span>
350
+ <span class="cline-any cline-yes">2x</span>
351
+ <span class="cline-any cline-yes">1x</span>
352
+ <span class="cline-any cline-yes">1x</span>
336
353
  <span class="cline-any cline-neutral">&nbsp;</span>
354
+ <span class="cline-any cline-yes">1x</span>
337
355
  <span class="cline-any cline-neutral">&nbsp;</span>
338
356
  <span class="cline-any cline-neutral">&nbsp;</span>
339
357
  <span class="cline-any cline-neutral">&nbsp;</span>
358
+ <span class="cline-any cline-yes">1x</span>
340
359
  <span class="cline-any cline-neutral">&nbsp;</span>
341
360
  <span class="cline-any cline-neutral">&nbsp;</span>
342
- <span class="cline-any cline-no">&nbsp;</span>
343
- <span class="cline-any cline-no">&nbsp;</span>
344
361
  <span class="cline-any cline-neutral">&nbsp;</span>
345
362
  <span class="cline-any cline-neutral">&nbsp;</span>
346
363
  <span class="cline-any cline-neutral">&nbsp;</span>
347
364
  <span class="cline-any cline-neutral">&nbsp;</span>
348
- <span class="cline-any cline-no">&nbsp;</span>
349
- <span class="cline-any cline-no">&nbsp;</span>
365
+ <span class="cline-any cline-yes">4x</span>
366
+ <span class="cline-any cline-yes">4x</span>
367
+ <span class="cline-any cline-yes">1x</span>
350
368
  <span class="cline-any cline-neutral">&nbsp;</span>
351
369
  <span class="cline-any cline-neutral">&nbsp;</span>
352
- <span class="cline-any cline-no">&nbsp;</span>
353
- <span class="cline-any cline-no">&nbsp;</span>
354
- <span class="cline-any cline-no">&nbsp;</span>
355
370
  <span class="cline-any cline-neutral">&nbsp;</span>
371
+ <span class="cline-any cline-yes">3x</span>
356
372
  <span class="cline-any cline-neutral">&nbsp;</span>
373
+ <span class="cline-any cline-yes">3x</span>
374
+ <span class="cline-any cline-yes">1x</span>
375
+ <span class="cline-any cline-yes">1x</span>
357
376
  <span class="cline-any cline-neutral">&nbsp;</span>
358
377
  <span class="cline-any cline-neutral">&nbsp;</span>
359
378
  <span class="cline-any cline-neutral">&nbsp;</span>
379
+ <span class="cline-any cline-yes">2x</span>
360
380
  <span class="cline-any cline-neutral">&nbsp;</span>
361
381
  <span class="cline-any cline-neutral">&nbsp;</span>
362
382
  <span class="cline-any cline-neutral">&nbsp;</span>
363
- <span class="cline-any cline-no">&nbsp;</span>
364
383
  <span class="cline-any cline-neutral">&nbsp;</span>
365
384
  <span class="cline-any cline-neutral">&nbsp;</span>
366
385
  <span class="cline-any cline-neutral">&nbsp;</span>
386
+ <span class="cline-any cline-yes">4x</span>
387
+ <span class="cline-any cline-yes">4x</span>
367
388
  <span class="cline-any cline-neutral">&nbsp;</span>
389
+ <span class="cline-any cline-yes">4x</span>
390
+ <span class="cline-any cline-yes">4x</span>
391
+ <span class="cline-any cline-yes">4x</span>
392
+ <span class="cline-any cline-yes">2x</span>
368
393
  <span class="cline-any cline-neutral">&nbsp;</span>
394
+ <span class="cline-any cline-yes">3x</span>
369
395
  <span class="cline-any cline-neutral">&nbsp;</span>
370
- <span class="cline-any cline-no">&nbsp;</span>
371
396
  <span class="cline-any cline-neutral">&nbsp;</span>
372
397
  <span class="cline-any cline-neutral">&nbsp;</span>
398
+ <span class="cline-any cline-yes">4x</span>
373
399
  <span class="cline-any cline-neutral">&nbsp;</span>
374
400
  <span class="cline-any cline-neutral">&nbsp;</span>
375
401
  <span class="cline-any cline-neutral">&nbsp;</span>
376
- <span class="cline-any cline-no">&nbsp;</span>
377
402
  <span class="cline-any cline-neutral">&nbsp;</span>
378
- <span class="cline-any cline-no">&nbsp;</span>
379
403
  <span class="cline-any cline-neutral">&nbsp;</span>
380
404
  <span class="cline-any cline-neutral">&nbsp;</span>
405
+ <span class="cline-any cline-yes">20x</span>
406
+ <span class="cline-any cline-yes">20x</span>
381
407
  <span class="cline-any cline-neutral">&nbsp;</span>
382
- <span class="cline-any cline-no">&nbsp;</span>
383
- <span class="cline-any cline-no">&nbsp;</span>
384
408
  <span class="cline-any cline-neutral">&nbsp;</span>
385
- <span class="cline-any cline-no">&nbsp;</span>
386
409
  <span class="cline-any cline-neutral">&nbsp;</span>
387
- <span class="cline-any cline-no">&nbsp;</span>
388
- <span class="cline-any cline-no">&nbsp;</span>
389
410
  <span class="cline-any cline-neutral">&nbsp;</span>
411
+ <span class="cline-any cline-yes">7x</span>
412
+ <span class="cline-any cline-yes">7x</span>
390
413
  <span class="cline-any cline-neutral">&nbsp;</span>
391
414
  <span class="cline-any cline-neutral">&nbsp;</span>
415
+ <span class="cline-any cline-yes">13x</span>
392
416
  <span class="cline-any cline-neutral">&nbsp;</span>
393
- <span class="cline-any cline-no">&nbsp;</span>
394
- <span class="cline-any cline-no">&nbsp;</span>
395
- <span class="cline-any cline-no">&nbsp;</span>
396
417
  <span class="cline-any cline-neutral">&nbsp;</span>
418
+ <span class="cline-any cline-yes">13x</span>
419
+ <span class="cline-any cline-yes">13x</span>
397
420
  <span class="cline-any cline-neutral">&nbsp;</span>
421
+ <span class="cline-any cline-yes">12x</span>
422
+ <span class="cline-any cline-yes">12x</span>
423
+ <span class="cline-any cline-yes">23x</span>
424
+ <span class="cline-any cline-yes">23x</span>
425
+ <span class="cline-any cline-yes">12x</span>
398
426
  <span class="cline-any cline-neutral">&nbsp;</span>
399
427
  <span class="cline-any cline-neutral">&nbsp;</span>
428
+ <span class="cline-any cline-yes">12x</span>
400
429
  <span class="cline-any cline-neutral">&nbsp;</span>
430
+ <span class="cline-any cline-yes">12x</span>
401
431
  <span class="cline-any cline-neutral">&nbsp;</span>
402
432
  <span class="cline-any cline-neutral">&nbsp;</span>
403
433
  <span class="cline-any cline-neutral">&nbsp;</span>
404
- <span class="cline-any cline-no">&nbsp;</span>
434
+ <span class="cline-any cline-yes">12x</span>
435
+ <span class="cline-any cline-yes">12x</span>
405
436
  <span class="cline-any cline-neutral">&nbsp;</span>
406
- <span class="cline-any cline-no">&nbsp;</span>
437
+ <span class="cline-any cline-yes">12x</span>
407
438
  <span class="cline-any cline-neutral">&nbsp;</span>
439
+ <span class="cline-any cline-yes">1x</span>
440
+ <span class="cline-any cline-yes">1x</span>
408
441
  <span class="cline-any cline-neutral">&nbsp;</span>
409
442
  <span class="cline-any cline-neutral">&nbsp;</span>
410
443
  <span class="cline-any cline-neutral">&nbsp;</span>
411
444
  <span class="cline-any cline-neutral">&nbsp;</span>
445
+ <span class="cline-any cline-yes">17x</span>
446
+ <span class="cline-any cline-yes">17x</span>
447
+ <span class="cline-any cline-yes">17x</span>
412
448
  <span class="cline-any cline-neutral">&nbsp;</span>
413
449
  <span class="cline-any cline-neutral">&nbsp;</span>
414
450
  <span class="cline-any cline-neutral">&nbsp;</span>
415
- <span class="cline-any cline-no">&nbsp;</span>
416
451
  <span class="cline-any cline-neutral">&nbsp;</span>
417
452
  <span class="cline-any cline-neutral">&nbsp;</span>
418
453
  <span class="cline-any cline-neutral">&nbsp;</span>
419
454
  <span class="cline-any cline-neutral">&nbsp;</span>
420
455
  <span class="cline-any cline-neutral">&nbsp;</span>
421
- <span class="cline-any cline-no">&nbsp;</span>
456
+ <span class="cline-any cline-yes">6x</span>
422
457
  <span class="cline-any cline-neutral">&nbsp;</span>
423
- <span class="cline-any cline-no">&nbsp;</span>
458
+ <span class="cline-any cline-yes">6x</span>
424
459
  <span class="cline-any cline-neutral">&nbsp;</span>
460
+ <span class="cline-any cline-yes">6x</span>
461
+ <span class="cline-any cline-yes">6x</span>
462
+ <span class="cline-any cline-yes">4x</span>
463
+ <span class="cline-any cline-yes">12x</span>
464
+ <span class="cline-any cline-yes">4x</span>
425
465
  <span class="cline-any cline-neutral">&nbsp;</span>
466
+ <span class="cline-any cline-yes">2x</span>
467
+ <span class="cline-any cline-yes">3x</span>
468
+ <span class="cline-any cline-yes">1x</span>
469
+ <span class="cline-any cline-yes">1x</span>
426
470
  <span class="cline-any cline-neutral">&nbsp;</span>
427
471
  <span class="cline-any cline-neutral">&nbsp;</span>
472
+ <span class="cline-any cline-yes">20x</span>
473
+ <span class="cline-any cline-yes">6x</span>
474
+ <span class="cline-any cline-yes">6x</span>
428
475
  <span class="cline-any cline-neutral">&nbsp;</span>
429
- <span class="cline-any cline-no">&nbsp;</span>
430
476
  <span class="cline-any cline-neutral">&nbsp;</span>
431
- <span class="cline-any cline-no">&nbsp;</span>
432
- <span class="cline-any cline-no">&nbsp;</span>
477
+ <span class="cline-any cline-yes">6x</span>
478
+ <span class="cline-any cline-yes">20x</span>
433
479
  <span class="cline-any cline-neutral">&nbsp;</span>
480
+ <span class="cline-any cline-yes">7x</span>
434
481
  <span class="cline-any cline-neutral">&nbsp;</span>
435
482
  <span class="cline-any cline-neutral">&nbsp;</span>
436
- <span class="cline-any cline-no">&nbsp;</span>
437
- <span class="cline-any cline-no">&nbsp;</span>
438
- <span class="cline-any cline-no">&nbsp;</span>
439
- <span class="cline-any cline-no">&nbsp;</span>
440
- <span class="cline-any cline-no">&nbsp;</span>
441
- <span class="cline-any cline-no">&nbsp;</span>
442
- <span class="cline-any cline-no">&nbsp;</span>
443
- <span class="cline-any cline-no">&nbsp;</span>
483
+ <span class="cline-any cline-yes">6x</span>
484
+ <span class="cline-any cline-yes">6x</span>
485
+ <span class="cline-any cline-yes">6x</span>
486
+ <span class="cline-any cline-yes">6x</span>
444
487
  <span class="cline-any cline-neutral">&nbsp;</span>
488
+ <span class="cline-any cline-yes">6x</span>
445
489
  <span class="cline-any cline-neutral">&nbsp;</span>
446
490
  <span class="cline-any cline-neutral">&nbsp;</span>
447
- <span class="cline-any cline-no">&nbsp;</span>
448
- <span class="cline-any cline-no">&nbsp;</span>
449
- <span class="cline-any cline-no">&nbsp;</span>
450
- <span class="cline-any cline-no">&nbsp;</span>
451
491
  <span class="cline-any cline-neutral">&nbsp;</span>
492
+ <span class="cline-any cline-yes">6x</span>
452
493
  <span class="cline-any cline-neutral">&nbsp;</span>
453
- <span class="cline-any cline-no">&nbsp;</span>
454
- <span class="cline-any cline-no">&nbsp;</span>
455
- <span class="cline-any cline-no">&nbsp;</span>
456
- <span class="cline-any cline-no">&nbsp;</span>
457
494
  <span class="cline-any cline-neutral">&nbsp;</span>
458
- <span class="cline-any cline-no">&nbsp;</span>
459
495
  <span class="cline-any cline-neutral">&nbsp;</span>
460
496
  <span class="cline-any cline-neutral">&nbsp;</span>
461
497
  <span class="cline-any cline-neutral">&nbsp;</span>
462
- <span class="cline-any cline-no">&nbsp;</span>
463
498
  <span class="cline-any cline-neutral">&nbsp;</span>
464
499
  <span class="cline-any cline-neutral">&nbsp;</span>
465
500
  <span class="cline-any cline-neutral">&nbsp;</span>
501
+ <span class="cline-any cline-yes">1x</span>
466
502
  <span class="cline-any cline-neutral">&nbsp;</span>
503
+ <span class="cline-any cline-yes">1x</span>
467
504
  <span class="cline-any cline-neutral">&nbsp;</span>
468
505
  <span class="cline-any cline-neutral">&nbsp;</span>
469
- <span class="cline-any cline-neutral">&nbsp;</span>
470
- <span class="cline-any cline-neutral">&nbsp;</span>
471
- <span class="cline-any cline-no">&nbsp;</span>
472
- <span class="cline-any cline-neutral">&nbsp;</span>
473
- <span class="cline-any cline-no">&nbsp;</span>
474
- <span class="cline-any cline-neutral">&nbsp;</span>
475
- <span class="cline-any cline-neutral">&nbsp;</span>
476
- <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js"><span class="cstat-no" title="statement not covered" >import { Injectable, Logger, BadRequestException } from '@nestjs/common';</span>
477
- <span class="cstat-no" title="statement not covered" >import { glob } from 'glob';</span>
478
- <span class="cstat-no" title="statement not covered" >import { ContextGenerationService } from '../context-generation/context-generation.service';</span>
506
+ <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import { Injectable, Logger, BadRequestException } from '@nestjs/common';
507
+ import { ContextGenerationService } from '../context-generation/context-generation.service';
479
508
  import {
480
509
  SearchWorkspaceResponseDto,
481
510
  SearchResultItemDto,
482
511
  } from './dto/search-workspace.dto';
483
- <span class="cstat-no" title="statement not covered" >import * as fs from 'fs/promises';</span>
484
- <span class="cstat-no" title="statement not covered" >import * as path from 'path';</span>
512
+ import * as fs from 'fs/promises';
513
+ import * as path from 'path';
514
+ import { fuzzySearch } from '../utils';
515
+ import { exec, ExecOptions } from 'child_process';
485
516
  &nbsp;
486
517
  interface FileTree {
487
518
  files: string[];
@@ -489,182 +520,196 @@ interface FileTree {
489
520
  }
490
521
  &nbsp;
491
522
  @Injectable()
492
- export class <span class="cstat-no" title="statement not covered" ><span class="cstat-no" title="statement not covered" >WorkspaceService<span class="cstat-no" title="statement not covered" > </span>{</span></span>
493
- private readonly <span class="cstat-no" title="statement not covered" >logger = new Logger(WorkspaceService.name);</span>
494
- private <span class="cstat-no" title="statement not covered" >projectRoot: string =</span>
523
+ export class WorkspaceService {
524
+ private readonly logger = new Logger(WorkspaceService.name);
525
+ private projectRoot: string =
495
526
  process.env.REPOBURG_PROJECT_PATH || process.cwd();
496
527
  &nbsp;
497
528
  // Cache for file tree
498
- private <span class="cstat-no" title="statement not covered" >fileTreeCache: FileTree | null = null;</span>
499
- private <span class="cstat-no" title="statement not covered" >fileTreeCacheTimestamp: number | null = null;</span>
500
- private readonly <span class="cstat-no" title="statement not covered" >CACHE_TTL_MS = 5 * 60 * 1000; </span>// 5 minutes
529
+ private fileTreeCache: FileTree | null = null;
530
+ private fileTreeCacheTimestamp: number | null = null;
531
+ private readonly CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes
501
532
  &nbsp;
502
- <span class="fstat-no" title="function not covered" > constructor(</span>
503
- private readonly <span class="cstat-no" title="statement not covered" >contextGenerationService: C</span>ontextGenerationService,
533
+ constructor(
534
+ private readonly contextGenerationService: ContextGenerationService,
504
535
  ) {}
505
536
  &nbsp;
506
- private <span class="fstat-no" title="function not covered" >resolveAndValidatePath(</span>unsafePath: string): string {
507
- const normalizedPath = <span class="cstat-no" title="statement not covered" >path.normalize(unsafePath);</span>
508
- <span class="cstat-no" title="statement not covered" > <span class="missing-if-branch" title="if path not taken" >I</span>if (path.isAbsolute(normalizedPath)) {</span>
509
- <span class="cstat-no" title="statement not covered" > throw new BadRequestException(</span>
537
+ private execAsync(
538
+ command: string,
539
+ options: ExecOptions,
540
+ ): Promise&lt;{ stdout: string; stderr: string }&gt; {
541
+ return new Promise((resolve, reject) =&gt; {
542
+ exec(command, options, (error, stdout, stderr) =&gt; {
543
+ if (error) {
544
+ error['stdout'] = stdout;
545
+ error['stderr'] = stderr;
546
+ reject(error);
547
+ return;
548
+ }
549
+ resolve({ stdout, stderr });
550
+ });
551
+ });
552
+ }
553
+ &nbsp;
554
+ private async getFilesFromRg(): Promise&lt;string[]&gt; {
555
+ const rgCommand = await this.contextGenerationService.getCommandPath('rg');
556
+ // --files: uses gitignore, .ignore, etc. by default.
557
+ // --hidden: ensures hidden files (dotfiles) are included, unless ignored.
558
+ const command = `${rgCommand} --files --hidden --glob '!.git'`;
559
+ &nbsp;
560
+ try {
561
+ this.logger.log(`Executing for file list: ${command}`);
562
+ const { stdout } = await this.execAsync(command, {
563
+ cwd: this.projectRoot,
564
+ maxBuffer: 256 * 1024 * 1024, // 256MB
565
+ timeout: 10000, // 10s
566
+ });
567
+ return stdout.trim().split('\n').filter(Boolean);
568
+ } catch (error) {
569
+ // rg exits with code 1 if no files are found with --files, which is not an error for us.
570
+ if (error.code === 1 &amp;&amp; error.stdout === '' &amp;&amp; error.stderr === '') {
571
+ this.logger.log('rg --files returned no files.');
572
+ return [];
573
+ }
574
+ this.logger.error(
575
+ `Failed to get file list from rg: ${error.message}`,
576
+ error.stack,
577
+ );
578
+ throw new Error(
579
+ `Could not retrieve file list from RipGrep. Is 'rg' installed and in your PATH?`,
580
+ );
581
+ }
582
+ }
583
+ &nbsp;
584
+ private resolveAndValidatePath(unsafePath: string): string {
585
+ const normalizedPath = path.normalize(unsafePath);
586
+ if (path.isAbsolute(normalizedPath)) {
587
+ throw new BadRequestException(
510
588
  `Absolute paths are not allowed: ${unsafePath}`,
511
589
  );
512
590
  }
513
- const resolvedPath = <span class="cstat-no" title="statement not covered" >path.resolve(this.projectRoot, normalizedPath);</span>
591
+ const resolvedPath = path.resolve(this.projectRoot, normalizedPath);
514
592
  &nbsp;
515
- <span class="cstat-no" title="statement not covered" > <span class="missing-if-branch" title="if path not taken" >I</span>if (!resolvedPath.startsWith(this.projectRoot)) {</span>
516
- <span class="cstat-no" title="statement not covered" > this.logger.warn(`Path traversal attempt detected: ${unsafePath}`);</span>
517
- <span class="cstat-no" title="statement not covered" > throw new BadRequestException(</span>
593
+ if (!resolvedPath.startsWith(this.projectRoot)) {
594
+ this.logger.warn(`Path traversal attempt detected: ${unsafePath}`);
595
+ throw new BadRequestException(
518
596
  `Path traversal is not allowed. Access denied for path: ${unsafePath}`,
519
597
  );
520
598
  }
521
- <span class="cstat-no" title="statement not covered" > return resolvedPath;</span>
599
+ return resolvedPath;
522
600
  }
523
601
  &nbsp;
524
- <span class="fstat-no" title="function not covered" > async </span>validatePaths(paths: {
602
+ async validatePaths(paths: {
525
603
  files?: string[];
526
604
  folders?: string[];
527
605
  }): Promise&lt;{ valid: boolean; invalidPaths: string[] }&gt; {
528
- const invalidPaths: string[] = <span class="cstat-no" title="statement not covered" >[];</span>
529
- const allPaths = <span class="cstat-no" title="statement not covered" >[...(paths.files || []), ...(paths.folders || [])];</span>
606
+ const invalidPaths: string[] = [];
607
+ const allPaths = [...(paths.files || <span class="branch-1 cbranch-no" title="branch not covered" >[])</span>, ...(paths.folders || [])];
530
608
  &nbsp;
531
- <span class="cstat-no" title="statement not covered" > for (const p of allPaths) {</span>
532
- <span class="cstat-no" title="statement not covered" > try {</span>
533
- const safePath = <span class="cstat-no" title="statement not covered" >this.resolveAndValidatePath(p);</span>
534
- <span class="cstat-no" title="statement not covered" > await fs.access(safePath);</span>
609
+ for (const p of allPaths) {
610
+ try {
611
+ const safePath = this.resolveAndValidatePath(p);
612
+ await fs.access(safePath);
535
613
  } catch (e) {
536
- <span class="cstat-no" title="statement not covered" > invalidPaths.push(p);</span>
614
+ invalidPaths.push(p);
537
615
  }
538
616
  }
539
617
  &nbsp;
540
- <span class="cstat-no" title="statement not covered" > return {</span>
618
+ return {
541
619
  valid: invalidPaths.length === 0,
542
620
  invalidPaths,
543
621
  };
544
622
  }
545
623
  &nbsp;
546
- <span class="fstat-no" title="function not covered" > async </span>getFileTree(): Promise&lt;FileTree&gt; {
547
- const now = <span class="cstat-no" title="statement not covered" >Date.now();</span>
548
- <span class="cstat-no" title="statement not covered" > <span class="missing-if-branch" title="if path not taken" >I</span>if (</span>
624
+ async getFileTree(): Promise&lt;FileTree&gt; {
625
+ const now = Date.now();
626
+ if (
549
627
  this.fileTreeCache &amp;&amp;
550
628
  this.fileTreeCacheTimestamp &amp;&amp;
551
629
  now - this.fileTreeCacheTimestamp &lt; this.CACHE_TTL_MS
552
630
  ) {
553
- <span class="cstat-no" title="statement not covered" > this.logger.log('Returning file tree from cache.');</span>
554
- <span class="cstat-no" title="statement not covered" > return this.fileTreeCache;</span>
631
+ this.logger.log('Returning file tree from cache.');
632
+ return this.fileTreeCache;
555
633
  }
556
634
  &nbsp;
557
- <span class="cstat-no" title="statement not covered" > this.logger.log(`Scanning project root for file tree: ${this.projectRoot}`);</span>
558
- <span class="cstat-no" title="statement not covered" > try {</span>
559
- const ignorePatterns = <span class="cstat-no" title="statement not covered" >[</span>
560
- '**/node_modules/**',
561
- '**/.git/**',
562
- '**/dist/**',
563
- '**/coverage/**',
564
- '**/.next/**',
565
- '**/data.json',
566
- ];
567
- &nbsp;
568
- const files = <span class="cstat-no" title="statement not covered" >await glob('**/*', {</span>
569
- cwd: this.projectRoot,
570
- nodir: true,
571
- ignore: ignorePatterns,
572
- dot: true,
573
- });
635
+ this.logger.log(
636
+ `Scanning project root for file tree with rg: ${this.projectRoot}`,
637
+ );
638
+ try {
639
+ const files = await this.getFilesFromRg();
574
640
  &nbsp;
575
- const allDirs = <span class="cstat-no" title="statement not covered" >await glob('**/', {</span>
576
- cwd: this.projectRoot,
577
- ignore: ignorePatterns,
578
- dot: true,
641
+ const folderSet = new Set&lt;string&gt;();
642
+ files.forEach((file) =&gt; {
643
+ const parts = file.split(path.sep);
644
+ for (let i = 1; i &lt; parts.length; i++) {
645
+ folderSet.add(parts.slice(0, i).join(path.sep));
646
+ }
579
647
  });
648
+ const folders = Array.from(folderSet);
580
649
  &nbsp;
581
- const folders = <span class="cstat-no" title="statement not covered" >allDirs.map(<span class="fstat-no" title="function not covered" >(d</span>) =&gt; <span class="cstat-no" title="statement not covered" >d.replace(/\/$/, ''))</span>.filter(<span class="fstat-no" title="function not covered" >(d</span>) =&gt; <span class="cstat-no" title="statement not covered" >d)</span>;</span>
582
- &nbsp;
583
- <span class="cstat-no" title="statement not covered" > this.logger.log(</span>
650
+ this.logger.log(
584
651
  `Found ${files.length} files and ${folders.length} folders.`,
585
652
  );
586
653
  &nbsp;
587
- <span class="cstat-no" title="statement not covered" > this.fileTreeCache = { files, folders };</span>
588
- <span class="cstat-no" title="statement not covered" > this.fileTreeCacheTimestamp = now;</span>
654
+ this.fileTreeCache = { files, folders };
655
+ this.fileTreeCacheTimestamp = now;
589
656
  &nbsp;
590
- <span class="cstat-no" title="statement not covered" > return this.fileTreeCache;</span>
657
+ return this.fileTreeCache;
591
658
  } catch (error) {
592
- <span class="cstat-no" title="statement not covered" > this.logger.error('Failed to get file tree:', error);</span>
593
- <span class="cstat-no" title="statement not covered" > throw error;</span>
659
+ this.logger.error('Failed to get file tree:', error);
660
+ throw error;
594
661
  }
595
662
  }
596
663
  &nbsp;
597
- <span class="fstat-no" title="function not covered" > async </span>invalidateFileTreeCache(): Promise&lt;void&gt; {
598
- <span class="cstat-no" title="statement not covered" > this.logger.log('Invalidating file tree cache.');</span>
599
- <span class="cstat-no" title="statement not covered" > this.fileTreeCache = null;</span>
600
- <span class="cstat-no" title="statement not covered" > this.fileTreeCacheTimestamp = null;</span>
664
+ async invalidateFileTreeCache(): Promise&lt;void&gt; {
665
+ this.logger.log('Invalidating file tree cache.');
666
+ this.fileTreeCache = null;
667
+ this.fileTreeCacheTimestamp = null;
601
668
  }
602
669
  &nbsp;
603
- <span class="fstat-no" title="function not covered" > async </span>search(
670
+ async search(
604
671
  query: string,
605
672
  type: 'files' | 'folders' | 'all',
606
673
  page: number,
607
674
  limit: number,
608
675
  ): Promise&lt;SearchWorkspaceResponseDto&gt; {
609
- <span class="cstat-no" title="statement not covered" > this.logger.log(`Searching for "${query}" (type: ${type})`);</span>
676
+ this.logger.log(`Searching for "${query}" (type: ${type})`);
610
677
  &nbsp;
611
- const ignorePatterns = <span class="cstat-no" title="statement not covered" >[</span>
612
- '**/node_modules/**',
613
- '**/.git/**',
614
- '**/dist/**',
615
- '**/coverage/**',
616
- '**/.next/**',
617
- '**/data.json',
618
- ];
678
+ const { files, folders } = await this.getFileTree();
619
679
  &nbsp;
620
- const globOptions = <span class="cstat-no" title="statement not covered" >{</span>
621
- cwd: this.projectRoot,
622
- ignore: ignorePatterns,
623
- dot: true,
624
- };
625
- &nbsp;
626
- const globPattern = <span class="cstat-no" title="statement not covered" >`**/*${query}*`;</span>
627
- &nbsp;
628
- const allMatches = <span class="cstat-no" title="statement not covered" >await glob(globPattern, {</span>
629
- ...globOptions,
630
- mark: true,
631
- nocase: true,
632
- }); // `mark: true` adds a trailing `/` to directories
633
- &nbsp;
634
- let results: SearchResultItemDto[] = <span class="cstat-no" title="statement not covered" >[];</span>
635
- &nbsp;
636
- <span class="cstat-no" title="statement not covered" > if (type === 'all') {</span>
637
- <span class="cstat-no" title="statement not covered" > results = allMatches.map(<span class="fstat-no" title="function not covered" >(p</span>) =&gt; (<span class="cstat-no" title="statement not covered" >{</span></span>
638
- type: p.endsWith('/') ? 'folder' : 'file',
639
- path: p.endsWith('/') ? p.slice(0, -1) : p,
640
- }));
641
- } else <span class="cstat-no" title="statement not covered" >if (type === 'files') {</span>
642
- <span class="cstat-no" title="statement not covered" > results = allMatches</span>
643
- .filter(<span class="fstat-no" title="function not covered" >(p</span>) =&gt; <span class="cstat-no" title="statement not covered" >!p.endsWith('/'))</span>
644
- .map(<span class="fstat-no" title="function not covered" >(p</span>) =&gt; (<span class="cstat-no" title="statement not covered" >{ type: 'file', path: p })</span>);
645
- } else <span class="cstat-no" title="statement not covered" ><span class="missing-if-branch" title="if path not taken" >I</span>if (type === 'folders') {</span>
646
- <span class="cstat-no" title="statement not covered" > results = allMatches</span>
647
- .filter(<span class="fstat-no" title="function not covered" >(p</span>) =&gt; <span class="cstat-no" title="statement not covered" >p.endsWith('/'))</span>
648
- .map(<span class="fstat-no" title="function not covered" >(p</span>) =&gt; (<span class="cstat-no" title="statement not covered" >{ type: 'folder', path: p.slice(0, -1) })</span>);
680
+ let searchPool: { path: string; type: 'file' | 'folder' }[] = [];
681
+ if (type === 'all') {
682
+ searchPool = [
683
+ ...files.map((p) =&gt; ({ path: p, type: 'file' as const })),
684
+ ...folders.map((p) =&gt; ({ path: p, type: 'folder' as const })),
685
+ ];
686
+ } else if (type === 'files') {
687
+ searchPool = files.map((p) =&gt; ({ path: p, type: 'file' as const }));
688
+ } else if (type === 'folders') {
689
+ searchPool = folders.map((p) =&gt; ({ path: p, type: 'folder' as const }));
649
690
  }
650
691
  &nbsp;
651
- // Sort folders first, then alphabetically
652
- <span class="cstat-no" title="statement not covered" > results.sort(<span class="fstat-no" title="function not covered" >(a</span>, b) =&gt; {</span>
653
- <span class="cstat-no" title="statement not covered" > <span class="missing-if-branch" title="if path not taken" >I</span>if (a.type === 'folder' &amp;&amp; b.type === 'file') <span class="cstat-no" title="statement not covered" >return -1;</span></span>
654
- <span class="cstat-no" title="statement not covered" > <span class="missing-if-branch" title="if path not taken" >I</span>if (a.type === 'file' &amp;&amp; b.type === 'folder') <span class="cstat-no" title="statement not covered" >return 1;</span></span>
655
- <span class="cstat-no" title="statement not covered" > return a.path.localeCompare(b.path);</span>
656
- });
692
+ const searchPoolStrings = searchPool.map((item) =&gt; item.path);
693
+ const matchedPaths = fuzzySearch(query, searchPoolStrings);
694
+ const matchedPathSet = new Set(matchedPaths);
695
+ &nbsp;
696
+ // Filter the original pool to keep type information, and sort by fuzzy search result order
697
+ const results: SearchResultItemDto[] = searchPool
698
+ .filter((item) =&gt; matchedPathSet.has(item.path))
699
+ .sort(
700
+ (a, b) =&gt; matchedPaths.indexOf(a.path) - matchedPaths.indexOf(b.path),
701
+ );
657
702
  &nbsp;
658
- const total = <span class="cstat-no" title="statement not covered" >results.length;</span>
659
- const startIndex = <span class="cstat-no" title="statement not covered" >(page - 1) * limit;</span>
660
- const endIndex = <span class="cstat-no" title="statement not covered" >page * limit;</span>
661
- const paginatedResults = <span class="cstat-no" title="statement not covered" >results.slice(startIndex, endIndex);</span>
703
+ const total = results.length;
704
+ const startIndex = (page - 1) * limit;
705
+ const endIndex = page * limit;
706
+ const paginatedResults = results.slice(startIndex, endIndex);
662
707
  &nbsp;
663
- <span class="cstat-no" title="statement not covered" > this.logger.log(</span>
664
- `Search for "${query}" (type: ${type}) with glob found ${total} total results. Returning page ${page} with ${paginatedResults.length} items.`,
708
+ this.logger.log(
709
+ `Search for "${query}" (type: ${type}) found ${total} total results. Returning page ${page} with ${paginatedResults.length} items.`,
665
710
  );
666
711
  &nbsp;
667
- <span class="cstat-no" title="statement not covered" > return {</span>
712
+ return {
668
713
  results: paginatedResults,
669
714
  total,
670
715
  page,
@@ -672,10 +717,10 @@ export class <span class="cstat-no" title="statement not covered" ><span class="
672
717
  };
673
718
  }
674
719
  &nbsp;
675
- <span class="fstat-no" title="function not covered" > async </span>getFileContent(filePath: string): Promise&lt;string&gt; {
676
- <span class="cstat-no" title="statement not covered" > this.logger.log(`Reading content for file: ${filePath}`);</span>
720
+ async getFileContent(filePath: string): Promise&lt;string&gt; {
721
+ this.logger.log(`Reading content for file: ${filePath}`);
677
722
  // Use the fetchFileContent method from ContextGenerationService to ensure path safety and get raw content.
678
- <span class="cstat-no" title="statement not covered" > return this.contextGenerationService.fetchFileContent(filePath);</span>
723
+ return this.contextGenerationService.fetchFileContent(filePath);
679
724
  }
680
725
  }
681
726
  &nbsp;</pre></td></tr></table></pre>
@@ -685,7 +730,7 @@ export class <span class="cstat-no" title="statement not covered" ><span class="
685
730
  <div class='footer quiet pad2 space-top1 center small'>
686
731
  Code coverage generated by
687
732
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
688
- at 2025-07-30T23:37:05.373Z
733
+ at 2025-09-12T19:21:55.945Z
689
734
  </div>
690
735
  <script src="../../prettify.js"></script>
691
736
  <script>