codesift-mcp 0.1.0 → 0.2.1

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 (299) hide show
  1. package/LICENSE +66 -21
  2. package/README.md +402 -56
  3. package/dist/cli/args.d.ts +2 -0
  4. package/dist/cli/args.d.ts.map +1 -1
  5. package/dist/cli/args.js +11 -0
  6. package/dist/cli/args.js.map +1 -1
  7. package/dist/cli/commands.d.ts.map +1 -1
  8. package/dist/cli/commands.js +177 -67
  9. package/dist/cli/commands.js.map +1 -1
  10. package/dist/cli/help.d.ts +1 -1
  11. package/dist/cli/help.d.ts.map +1 -1
  12. package/dist/cli/help.js +157 -0
  13. package/dist/cli/help.js.map +1 -1
  14. package/dist/cli/hooks.d.ts +3 -0
  15. package/dist/cli/hooks.d.ts.map +1 -0
  16. package/dist/cli/hooks.js +163 -0
  17. package/dist/cli/hooks.js.map +1 -0
  18. package/dist/cli/setup.d.ts +25 -0
  19. package/dist/cli/setup.d.ts.map +1 -0
  20. package/dist/cli/setup.js +400 -0
  21. package/dist/cli/setup.js.map +1 -0
  22. package/dist/config.d.ts +2 -0
  23. package/dist/config.d.ts.map +1 -1
  24. package/dist/config.js +2 -0
  25. package/dist/config.js.map +1 -1
  26. package/dist/formatters-shortening.d.ts +7 -0
  27. package/dist/formatters-shortening.d.ts.map +1 -0
  28. package/dist/formatters-shortening.js +68 -0
  29. package/dist/formatters-shortening.js.map +1 -0
  30. package/dist/formatters.d.ts +314 -0
  31. package/dist/formatters.d.ts.map +1 -0
  32. package/dist/formatters.js +396 -0
  33. package/dist/formatters.js.map +1 -0
  34. package/dist/instructions.d.ts +6 -0
  35. package/dist/instructions.d.ts.map +1 -0
  36. package/dist/instructions.js +72 -0
  37. package/dist/instructions.js.map +1 -0
  38. package/dist/lsp/lsp-client.d.ts +21 -0
  39. package/dist/lsp/lsp-client.d.ts.map +1 -0
  40. package/dist/lsp/lsp-client.js +122 -0
  41. package/dist/lsp/lsp-client.js.map +1 -0
  42. package/dist/lsp/lsp-manager.d.ts +12 -0
  43. package/dist/lsp/lsp-manager.d.ts.map +1 -0
  44. package/dist/lsp/lsp-manager.js +82 -0
  45. package/dist/lsp/lsp-manager.js.map +1 -0
  46. package/dist/lsp/lsp-servers.d.ts +13 -0
  47. package/dist/lsp/lsp-servers.d.ts.map +1 -0
  48. package/dist/lsp/lsp-servers.js +57 -0
  49. package/dist/lsp/lsp-servers.js.map +1 -0
  50. package/dist/lsp/lsp-tools.d.ts +67 -0
  51. package/dist/lsp/lsp-tools.d.ts.map +1 -0
  52. package/dist/lsp/lsp-tools.js +359 -0
  53. package/dist/lsp/lsp-tools.js.map +1 -0
  54. package/dist/parser/extractors/_shared.d.ts +11 -0
  55. package/dist/parser/extractors/_shared.d.ts.map +1 -0
  56. package/dist/parser/extractors/_shared.js +38 -0
  57. package/dist/parser/extractors/_shared.js.map +1 -0
  58. package/dist/parser/extractors/astro.d.ts +15 -0
  59. package/dist/parser/extractors/astro.d.ts.map +1 -0
  60. package/dist/parser/extractors/astro.js +104 -0
  61. package/dist/parser/extractors/astro.js.map +1 -0
  62. package/dist/parser/extractors/conversation.d.ts +16 -0
  63. package/dist/parser/extractors/conversation.d.ts.map +1 -0
  64. package/dist/parser/extractors/conversation.js +196 -0
  65. package/dist/parser/extractors/conversation.js.map +1 -0
  66. package/dist/parser/extractors/go.d.ts.map +1 -1
  67. package/dist/parser/extractors/go.js +22 -45
  68. package/dist/parser/extractors/go.js.map +1 -1
  69. package/dist/parser/extractors/python.d.ts +1 -1
  70. package/dist/parser/extractors/python.d.ts.map +1 -1
  71. package/dist/parser/extractors/python.js +19 -50
  72. package/dist/parser/extractors/python.js.map +1 -1
  73. package/dist/parser/extractors/rust.d.ts +1 -1
  74. package/dist/parser/extractors/rust.d.ts.map +1 -1
  75. package/dist/parser/extractors/rust.js +7 -34
  76. package/dist/parser/extractors/rust.js.map +1 -1
  77. package/dist/parser/extractors/typescript.d.ts +1 -1
  78. package/dist/parser/extractors/typescript.d.ts.map +1 -1
  79. package/dist/parser/extractors/typescript.js +99 -68
  80. package/dist/parser/extractors/typescript.js.map +1 -1
  81. package/dist/parser/parser-manager.d.ts.map +1 -1
  82. package/dist/parser/parser-manager.js +12 -2
  83. package/dist/parser/parser-manager.js.map +1 -1
  84. package/dist/parser/symbol-extractor.d.ts +2 -0
  85. package/dist/parser/symbol-extractor.d.ts.map +1 -1
  86. package/dist/parser/symbol-extractor.js +2 -0
  87. package/dist/parser/symbol-extractor.js.map +1 -1
  88. package/dist/register-tools.d.ts +127 -0
  89. package/dist/register-tools.d.ts.map +1 -0
  90. package/dist/register-tools.js +1453 -0
  91. package/dist/register-tools.js.map +1 -0
  92. package/dist/retrieval/codebase-retrieval.d.ts +4 -26
  93. package/dist/retrieval/codebase-retrieval.d.ts.map +1 -1
  94. package/dist/retrieval/codebase-retrieval.js +105 -403
  95. package/dist/retrieval/codebase-retrieval.js.map +1 -1
  96. package/dist/retrieval/retrieval-constants.d.ts +27 -0
  97. package/dist/retrieval/retrieval-constants.d.ts.map +1 -0
  98. package/dist/retrieval/retrieval-constants.js +27 -0
  99. package/dist/retrieval/retrieval-constants.js.map +1 -0
  100. package/dist/retrieval/retrieval-schemas.d.ts +107 -0
  101. package/dist/retrieval/retrieval-schemas.d.ts.map +1 -0
  102. package/dist/retrieval/retrieval-schemas.js +102 -0
  103. package/dist/retrieval/retrieval-schemas.js.map +1 -0
  104. package/dist/retrieval/retrieval-utils.d.ts +40 -0
  105. package/dist/retrieval/retrieval-utils.d.ts.map +1 -0
  106. package/dist/retrieval/retrieval-utils.js +139 -0
  107. package/dist/retrieval/retrieval-utils.js.map +1 -0
  108. package/dist/retrieval/semantic-handlers.d.ts +8 -0
  109. package/dist/retrieval/semantic-handlers.d.ts.map +1 -0
  110. package/dist/retrieval/semantic-handlers.js +152 -0
  111. package/dist/retrieval/semantic-handlers.js.map +1 -0
  112. package/dist/search/bm25.d.ts +6 -1
  113. package/dist/search/bm25.d.ts.map +1 -1
  114. package/dist/search/bm25.js +95 -32
  115. package/dist/search/bm25.js.map +1 -1
  116. package/dist/search/chunker.d.ts +10 -0
  117. package/dist/search/chunker.d.ts.map +1 -1
  118. package/dist/search/chunker.js +63 -11
  119. package/dist/search/chunker.js.map +1 -1
  120. package/dist/search/reranker.d.ts +15 -0
  121. package/dist/search/reranker.d.ts.map +1 -0
  122. package/dist/search/reranker.js +126 -0
  123. package/dist/search/reranker.js.map +1 -0
  124. package/dist/search/semantic.d.ts +1 -1
  125. package/dist/search/semantic.d.ts.map +1 -1
  126. package/dist/search/semantic.js +40 -45
  127. package/dist/search/semantic.js.map +1 -1
  128. package/dist/server-helpers.d.ts +29 -0
  129. package/dist/server-helpers.d.ts.map +1 -0
  130. package/dist/server-helpers.js +312 -0
  131. package/dist/server-helpers.js.map +1 -0
  132. package/dist/server.d.ts +1 -1
  133. package/dist/server.d.ts.map +1 -1
  134. package/dist/server.js +11 -271
  135. package/dist/server.js.map +1 -1
  136. package/dist/storage/_shared.d.ts +9 -0
  137. package/dist/storage/_shared.d.ts.map +1 -0
  138. package/dist/storage/_shared.js +26 -0
  139. package/dist/storage/_shared.js.map +1 -0
  140. package/dist/storage/chunk-store.d.ts.map +1 -1
  141. package/dist/storage/chunk-store.js +23 -63
  142. package/dist/storage/chunk-store.js.map +1 -1
  143. package/dist/storage/embedding-store.d.ts +6 -3
  144. package/dist/storage/embedding-store.d.ts.map +1 -1
  145. package/dist/storage/embedding-store.js +54 -30
  146. package/dist/storage/embedding-store.js.map +1 -1
  147. package/dist/storage/graph-store.d.ts +48 -0
  148. package/dist/storage/graph-store.d.ts.map +1 -0
  149. package/dist/storage/graph-store.js +52 -0
  150. package/dist/storage/graph-store.js.map +1 -0
  151. package/dist/storage/index-store.d.ts +5 -0
  152. package/dist/storage/index-store.d.ts.map +1 -1
  153. package/dist/storage/index-store.js +28 -16
  154. package/dist/storage/index-store.js.map +1 -1
  155. package/dist/storage/registry.d.ts +4 -0
  156. package/dist/storage/registry.d.ts.map +1 -1
  157. package/dist/storage/registry.js +16 -16
  158. package/dist/storage/registry.js.map +1 -1
  159. package/dist/storage/usage-stats.d.ts +6 -0
  160. package/dist/storage/usage-stats.d.ts.map +1 -1
  161. package/dist/storage/usage-stats.js +59 -11
  162. package/dist/storage/usage-stats.js.map +1 -1
  163. package/dist/storage/usage-tracker.d.ts +3 -0
  164. package/dist/storage/usage-tracker.d.ts.map +1 -1
  165. package/dist/storage/usage-tracker.js +50 -132
  166. package/dist/storage/usage-tracker.js.map +1 -1
  167. package/dist/storage/watcher.d.ts +2 -1
  168. package/dist/storage/watcher.d.ts.map +1 -1
  169. package/dist/storage/watcher.js +16 -16
  170. package/dist/storage/watcher.js.map +1 -1
  171. package/dist/tools/ast-query-tools.d.ts +29 -0
  172. package/dist/tools/ast-query-tools.d.ts.map +1 -0
  173. package/dist/tools/ast-query-tools.js +110 -0
  174. package/dist/tools/ast-query-tools.js.map +1 -0
  175. package/dist/tools/boundary-tools.d.ts +31 -0
  176. package/dist/tools/boundary-tools.d.ts.map +1 -0
  177. package/dist/tools/boundary-tools.js +62 -0
  178. package/dist/tools/boundary-tools.js.map +1 -0
  179. package/dist/tools/clone-tools.d.ts +35 -0
  180. package/dist/tools/clone-tools.d.ts.map +1 -0
  181. package/dist/tools/clone-tools.js +181 -0
  182. package/dist/tools/clone-tools.js.map +1 -0
  183. package/dist/tools/community-tools.d.ts +23 -0
  184. package/dist/tools/community-tools.d.ts.map +1 -0
  185. package/dist/tools/community-tools.js +297 -0
  186. package/dist/tools/community-tools.js.map +1 -0
  187. package/dist/tools/complexity-tools.d.ts +34 -0
  188. package/dist/tools/complexity-tools.d.ts.map +1 -0
  189. package/dist/tools/complexity-tools.js +135 -0
  190. package/dist/tools/complexity-tools.js.map +1 -0
  191. package/dist/tools/context-tools.d.ts +44 -3
  192. package/dist/tools/context-tools.d.ts.map +1 -1
  193. package/dist/tools/context-tools.js +329 -99
  194. package/dist/tools/context-tools.js.map +1 -1
  195. package/dist/tools/conversation-tools.d.ts +107 -0
  196. package/dist/tools/conversation-tools.d.ts.map +1 -0
  197. package/dist/tools/conversation-tools.js +419 -0
  198. package/dist/tools/conversation-tools.js.map +1 -0
  199. package/dist/tools/coordinator-tools.d.ts +73 -0
  200. package/dist/tools/coordinator-tools.d.ts.map +1 -0
  201. package/dist/tools/coordinator-tools.js +153 -0
  202. package/dist/tools/coordinator-tools.js.map +1 -0
  203. package/dist/tools/cross-repo-tools.d.ts +43 -0
  204. package/dist/tools/cross-repo-tools.d.ts.map +1 -0
  205. package/dist/tools/cross-repo-tools.js +55 -0
  206. package/dist/tools/cross-repo-tools.js.map +1 -0
  207. package/dist/tools/diff-tools.d.ts +4 -1
  208. package/dist/tools/diff-tools.d.ts.map +1 -1
  209. package/dist/tools/diff-tools.js +23 -5
  210. package/dist/tools/diff-tools.js.map +1 -1
  211. package/dist/tools/frequency-tools.d.ts +46 -0
  212. package/dist/tools/frequency-tools.d.ts.map +1 -0
  213. package/dist/tools/frequency-tools.js +184 -0
  214. package/dist/tools/frequency-tools.js.map +1 -0
  215. package/dist/tools/generate-tools.d.ts.map +1 -1
  216. package/dist/tools/generate-tools.js +13 -2
  217. package/dist/tools/generate-tools.js.map +1 -1
  218. package/dist/tools/graph-tools.d.ts +44 -11
  219. package/dist/tools/graph-tools.d.ts.map +1 -1
  220. package/dist/tools/graph-tools.js +147 -104
  221. package/dist/tools/graph-tools.js.map +1 -1
  222. package/dist/tools/hotspot-tools.d.ts +24 -0
  223. package/dist/tools/hotspot-tools.d.ts.map +1 -0
  224. package/dist/tools/hotspot-tools.js +122 -0
  225. package/dist/tools/hotspot-tools.js.map +1 -0
  226. package/dist/tools/impact-tools.d.ts +13 -0
  227. package/dist/tools/impact-tools.d.ts.map +1 -0
  228. package/dist/tools/impact-tools.js +238 -0
  229. package/dist/tools/impact-tools.js.map +1 -0
  230. package/dist/tools/index-tools.d.ts +44 -3
  231. package/dist/tools/index-tools.d.ts.map +1 -1
  232. package/dist/tools/index-tools.js +530 -222
  233. package/dist/tools/index-tools.js.map +1 -1
  234. package/dist/tools/memory-tools.d.ts +35 -0
  235. package/dist/tools/memory-tools.d.ts.map +1 -0
  236. package/dist/tools/memory-tools.js +229 -0
  237. package/dist/tools/memory-tools.js.map +1 -0
  238. package/dist/tools/outline-tools.d.ts +24 -13
  239. package/dist/tools/outline-tools.d.ts.map +1 -1
  240. package/dist/tools/outline-tools.js +113 -87
  241. package/dist/tools/outline-tools.js.map +1 -1
  242. package/dist/tools/pattern-tools.d.ts +32 -0
  243. package/dist/tools/pattern-tools.d.ts.map +1 -0
  244. package/dist/tools/pattern-tools.js +116 -0
  245. package/dist/tools/pattern-tools.js.map +1 -0
  246. package/dist/tools/report-tools.d.ts +5 -0
  247. package/dist/tools/report-tools.d.ts.map +1 -0
  248. package/dist/tools/report-tools.js +167 -0
  249. package/dist/tools/report-tools.js.map +1 -0
  250. package/dist/tools/review-diff-tools.d.ts +148 -0
  251. package/dist/tools/review-diff-tools.d.ts.map +1 -0
  252. package/dist/tools/review-diff-tools.js +852 -0
  253. package/dist/tools/review-diff-tools.js.map +1 -0
  254. package/dist/tools/route-tools.d.ts +32 -0
  255. package/dist/tools/route-tools.d.ts.map +1 -0
  256. package/dist/tools/route-tools.js +276 -0
  257. package/dist/tools/route-tools.js.map +1 -0
  258. package/dist/tools/search-ranker.d.ts +5 -0
  259. package/dist/tools/search-ranker.d.ts.map +1 -0
  260. package/dist/tools/search-ranker.js +142 -0
  261. package/dist/tools/search-ranker.js.map +1 -0
  262. package/dist/tools/search-tools.d.ts +24 -1
  263. package/dist/tools/search-tools.d.ts.map +1 -1
  264. package/dist/tools/search-tools.js +459 -225
  265. package/dist/tools/search-tools.js.map +1 -1
  266. package/dist/tools/secret-tools.d.ts +104 -0
  267. package/dist/tools/secret-tools.d.ts.map +1 -0
  268. package/dist/tools/secret-tools.js +410 -0
  269. package/dist/tools/secret-tools.js.map +1 -0
  270. package/dist/tools/symbol-tools.d.ts +90 -2
  271. package/dist/tools/symbol-tools.d.ts.map +1 -1
  272. package/dist/tools/symbol-tools.js +576 -42
  273. package/dist/tools/symbol-tools.js.map +1 -1
  274. package/dist/types.d.ts +34 -1
  275. package/dist/types.d.ts.map +1 -1
  276. package/dist/utils/framework-detect.d.ts +5 -0
  277. package/dist/utils/framework-detect.d.ts.map +1 -0
  278. package/dist/utils/framework-detect.js +36 -0
  279. package/dist/utils/framework-detect.js.map +1 -0
  280. package/dist/utils/glob.d.ts +19 -0
  281. package/dist/utils/glob.d.ts.map +1 -0
  282. package/dist/utils/glob.js +74 -0
  283. package/dist/utils/glob.js.map +1 -0
  284. package/dist/utils/import-graph.d.ts +29 -0
  285. package/dist/utils/import-graph.d.ts.map +1 -0
  286. package/dist/utils/import-graph.js +125 -0
  287. package/dist/utils/import-graph.js.map +1 -0
  288. package/dist/utils/test-file.d.ts.map +1 -1
  289. package/dist/utils/test-file.js +1 -0
  290. package/dist/utils/test-file.js.map +1 -1
  291. package/dist/utils/walk.d.ts +45 -0
  292. package/dist/utils/walk.d.ts.map +1 -0
  293. package/dist/utils/walk.js +87 -0
  294. package/dist/utils/walk.js.map +1 -0
  295. package/package.json +12 -5
  296. package/rules/codesift.md +187 -0
  297. package/rules/codesift.mdc +192 -0
  298. package/rules/codex.md +187 -0
  299. package/rules/gemini.md +187 -0
@@ -0,0 +1,62 @@
1
+ import { getCodeIndex } from "./index-tools.js";
2
+ import { collectImportEdges } from "../utils/import-graph.js";
3
+ /**
4
+ * Check architecture boundary rules against the import graph.
5
+ *
6
+ * Rules use path substring matching:
7
+ * { from: "src/domain", cannot_import: ["src/infrastructure", "src/api"] }
8
+ * { from: "src/api", can_only_import: ["src/domain", "src/application"] }
9
+ *
10
+ * `cannot_import` — files matching `from` must NOT import files matching any listed pattern.
11
+ * `can_only_import` — files matching `from` may ONLY import files matching one of the listed patterns.
12
+ */
13
+ export async function checkBoundaries(repo, rules, options) {
14
+ if (!rules.length) {
15
+ return { violations: [], edges_checked: 0, rules_applied: 0, passed: true };
16
+ }
17
+ const index = await getCodeIndex(repo);
18
+ if (!index)
19
+ throw new Error(`Repository not found: ${repo}`);
20
+ const edges = await collectImportEdges(index);
21
+ const violations = [];
22
+ let edgesChecked = 0;
23
+ for (const edge of edges) {
24
+ if (options?.file_pattern && !edge.from.includes(options.file_pattern))
25
+ continue;
26
+ edgesChecked++;
27
+ for (const rule of rules) {
28
+ if (!edge.from.includes(rule.from))
29
+ continue;
30
+ if (rule.cannot_import) {
31
+ for (const forbidden of rule.cannot_import) {
32
+ if (edge.to.includes(forbidden)) {
33
+ violations.push({
34
+ file: edge.from,
35
+ imports: edge.to,
36
+ rule_from: rule.from,
37
+ reason: `"${rule.from}" cannot import "${forbidden}"`,
38
+ });
39
+ }
40
+ }
41
+ }
42
+ if (rule.can_only_import) {
43
+ const allowed = rule.can_only_import.some((pattern) => edge.to.includes(pattern));
44
+ if (!allowed) {
45
+ violations.push({
46
+ file: edge.from,
47
+ imports: edge.to,
48
+ rule_from: rule.from,
49
+ reason: `"${rule.from}" can only import [${rule.can_only_import.join(", ")}]`,
50
+ });
51
+ }
52
+ }
53
+ }
54
+ }
55
+ return {
56
+ violations,
57
+ edges_checked: edgesChecked,
58
+ rules_applied: rules.length,
59
+ passed: violations.length === 0,
60
+ };
61
+ }
62
+ //# sourceMappingURL=boundary-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boundary-tools.js","sourceRoot":"","sources":["../../src/tools/boundary-tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAsB9D;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,IAAY,EACZ,KAAqB,EACrB,OAA+C;IAE/C,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QAClB,OAAO,EAAE,UAAU,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IAC9E,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;IACvC,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,IAAI,EAAE,CAAC,CAAC;IAE7D,MAAM,KAAK,GAAG,MAAM,kBAAkB,CAAC,KAAK,CAAC,CAAC;IAE9C,MAAM,UAAU,GAAwB,EAAE,CAAC;IAC3C,IAAI,YAAY,GAAG,CAAC,CAAC;IAErB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,OAAO,EAAE,YAAY,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,YAAY,CAAC;YAAE,SAAS;QACjF,YAAY,EAAE,CAAC;QAEf,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;gBAAE,SAAS;YAE7C,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;gBACvB,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;oBAC3C,IAAI,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;wBAChC,UAAU,CAAC,IAAI,CAAC;4BACd,IAAI,EAAE,IAAI,CAAC,IAAI;4BACf,OAAO,EAAE,IAAI,CAAC,EAAE;4BAChB,SAAS,EAAE,IAAI,CAAC,IAAI;4BACpB,MAAM,EAAE,IAAI,IAAI,CAAC,IAAI,oBAAoB,SAAS,GAAG;yBACtD,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;YACH,CAAC;YAED,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;gBACzB,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;gBAClF,IAAI,CAAC,OAAO,EAAE,CAAC;oBACb,UAAU,CAAC,IAAI,CAAC;wBACd,IAAI,EAAE,IAAI,CAAC,IAAI;wBACf,OAAO,EAAE,IAAI,CAAC,EAAE;wBAChB,SAAS,EAAE,IAAI,CAAC,IAAI;wBACpB,MAAM,EAAE,IAAI,IAAI,CAAC,IAAI,sBAAsB,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;qBAC9E,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO;QACL,UAAU;QACV,aAAa,EAAE,YAAY;QAC3B,aAAa,EAAE,KAAK,CAAC,MAAM;QAC3B,MAAM,EAAE,UAAU,CAAC,MAAM,KAAK,CAAC;KAChC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,35 @@
1
+ import type { SymbolKind } from "../types.js";
2
+ export interface CodeClone {
3
+ symbol_a: {
4
+ name: string;
5
+ kind: SymbolKind;
6
+ file: string;
7
+ start_line: number;
8
+ end_line: number;
9
+ };
10
+ symbol_b: {
11
+ name: string;
12
+ kind: SymbolKind;
13
+ file: string;
14
+ start_line: number;
15
+ end_line: number;
16
+ };
17
+ similarity: number;
18
+ shared_lines: number;
19
+ }
20
+ export interface CloneResult {
21
+ clones: CodeClone[];
22
+ scanned_symbols: number;
23
+ threshold: number;
24
+ }
25
+ /**
26
+ * Find code clones: pairs of symbols with similar normalized source.
27
+ * Uses hash-based bucketing for O(n) average case instead of O(n²) all-pairs.
28
+ */
29
+ export declare function findClones(repo: string, options?: {
30
+ file_pattern?: string | undefined;
31
+ min_similarity?: number | undefined;
32
+ min_lines?: number | undefined;
33
+ include_tests?: boolean | undefined;
34
+ }): Promise<CloneResult>;
35
+ //# sourceMappingURL=clone-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clone-tools.d.ts","sourceRoot":"","sources":["../../src/tools/clone-tools.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAQ9C,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,UAAU,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IACjG,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,UAAU,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IACjG,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;CACnB;AA2LD;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;IACR,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,aAAa,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACrC,GACA,OAAO,CAAC,WAAW,CAAC,CAuBtB"}
@@ -0,0 +1,181 @@
1
+ import { getCodeIndex } from "./index-tools.js";
2
+ import { isTestFileStrict as isTestFile } from "../utils/test-file.js";
3
+ const MIN_CLONE_LINES = 10;
4
+ const MAX_CLONES = 50;
5
+ const DEFAULT_MIN_SIMILARITY = 0.7;
6
+ /** Max line-count ratio for near-match comparison (30% tolerance) */
7
+ const MAX_LINE_RATIO = 1.3;
8
+ const ANALYZABLE_KINDS = new Set([
9
+ "function", "method", "class",
10
+ ]);
11
+ /**
12
+ * Normalize source for comparison: strip whitespace, comments, string literals.
13
+ * Returns array of normalized non-empty lines.
14
+ */
15
+ function normalizeSource(source) {
16
+ return source
17
+ .split("\n")
18
+ .map((line) => {
19
+ let l = line.trim();
20
+ // Strip single-line comments
21
+ const commentIdx = l.indexOf("//");
22
+ if (commentIdx >= 0)
23
+ l = l.slice(0, commentIdx).trim();
24
+ // Normalize whitespace
25
+ l = l.replace(/\s+/g, " ");
26
+ return l;
27
+ })
28
+ .filter((l) => l.length > 0 && l !== "{" && l !== "}" && l !== ");");
29
+ }
30
+ /**
31
+ * Simple fingerprint: hash of normalized lines joined.
32
+ * Uses djb2 for speed (not crypto).
33
+ */
34
+ function hashLines(lines) {
35
+ let hash = 5381;
36
+ for (const line of lines) {
37
+ for (let i = 0; i < line.length; i++) {
38
+ hash = ((hash << 5) + hash + line.charCodeAt(i)) | 0;
39
+ }
40
+ }
41
+ return hash;
42
+ }
43
+ /**
44
+ * Compute line-level similarity between two normalized sources.
45
+ * Uses set intersection of lines (bag-of-lines similarity).
46
+ */
47
+ function computeSimilarity(linesA, linesB) {
48
+ const setA = new Set(linesA);
49
+ const setB = new Set(linesB);
50
+ let shared = 0;
51
+ for (const line of setA) {
52
+ if (setB.has(line))
53
+ shared++;
54
+ }
55
+ const total = Math.max(setA.size, setB.size);
56
+ return {
57
+ similarity: total > 0 ? Math.round((shared / total) * 100) / 100 : 0,
58
+ sharedLines: shared,
59
+ };
60
+ }
61
+ /** Build a CodeClone from two entries and their similarity result */
62
+ function buildClone(a, b, similarity, sharedLines) {
63
+ return {
64
+ symbol_a: { name: a.name, kind: a.kind, file: a.file, start_line: a.start_line, end_line: a.end_line },
65
+ symbol_b: { name: b.name, kind: b.kind, file: b.file, start_line: b.start_line, end_line: b.end_line },
66
+ similarity,
67
+ shared_lines: sharedLines,
68
+ };
69
+ }
70
+ /** Filter, normalize, and hash symbols into clone-comparable entries */
71
+ function prepareEntries(symbols, minLines, includeTests, filePattern) {
72
+ const entries = [];
73
+ for (const sym of symbols) {
74
+ if (!ANALYZABLE_KINDS.has(sym.kind))
75
+ continue;
76
+ if (!sym.source)
77
+ continue;
78
+ if (!includeTests && isTestFile(sym.file))
79
+ continue;
80
+ if (filePattern && !sym.file.includes(filePattern))
81
+ continue;
82
+ const lines = normalizeSource(sym.source);
83
+ if (lines.length < minLines)
84
+ continue;
85
+ entries.push({
86
+ name: sym.name,
87
+ kind: sym.kind,
88
+ file: sym.file,
89
+ start_line: sym.start_line,
90
+ end_line: sym.end_line,
91
+ lines,
92
+ hash: hashLines(lines),
93
+ });
94
+ }
95
+ return entries;
96
+ }
97
+ /** Phase 1: Find exact hash matches via O(n) bucketing */
98
+ function findExactMatches(entries, minSimilarity, minLines, maxClones) {
99
+ const clones = [];
100
+ const hashBuckets = new Map();
101
+ for (const entry of entries) {
102
+ const bucket = hashBuckets.get(entry.hash);
103
+ if (bucket)
104
+ bucket.push(entry);
105
+ else
106
+ hashBuckets.set(entry.hash, [entry]);
107
+ }
108
+ for (const bucket of hashBuckets.values()) {
109
+ if (bucket.length < 2)
110
+ continue;
111
+ for (let i = 0; i < bucket.length; i++) {
112
+ for (let j = i + 1; j < bucket.length; j++) {
113
+ if (clones.length >= maxClones)
114
+ break;
115
+ const a = bucket[i];
116
+ const b = bucket[j];
117
+ if (a.file === b.file && a.start_line === b.start_line)
118
+ continue;
119
+ const { similarity, sharedLines } = computeSimilarity(a.lines, b.lines);
120
+ if (similarity >= minSimilarity && sharedLines >= minLines) {
121
+ clones.push(buildClone(a, b, similarity, sharedLines));
122
+ }
123
+ }
124
+ }
125
+ }
126
+ return clones;
127
+ }
128
+ /** Phase 2: Find near-matches by comparing entries with similar line counts */
129
+ function findNearMatches(entries, existingClones, minSimilarity, minLines, maxClones) {
130
+ const clones = [];
131
+ const remaining = maxClones - existingClones.length;
132
+ if (remaining <= 0)
133
+ return clones;
134
+ const sorted = [...entries].sort((a, b) => a.lines.length - b.lines.length);
135
+ for (let i = 0; i < sorted.length && clones.length < remaining; i++) {
136
+ for (let j = i + 1; j < sorted.length && clones.length < remaining; j++) {
137
+ const a = sorted[i];
138
+ const b = sorted[j];
139
+ if (b.lines.length > a.lines.length * MAX_LINE_RATIO)
140
+ break;
141
+ if (a.hash === b.hash)
142
+ continue;
143
+ if (a.file === b.file && a.start_line === b.start_line)
144
+ continue;
145
+ const alreadyFound = existingClones.some((c) => (c.symbol_a.file === a.file && c.symbol_a.start_line === a.start_line &&
146
+ c.symbol_b.file === b.file && c.symbol_b.start_line === b.start_line));
147
+ if (alreadyFound)
148
+ continue;
149
+ const { similarity, sharedLines } = computeSimilarity(a.lines, b.lines);
150
+ if (similarity >= minSimilarity && sharedLines >= minLines) {
151
+ clones.push(buildClone(a, b, similarity, sharedLines));
152
+ }
153
+ }
154
+ }
155
+ return clones;
156
+ }
157
+ /**
158
+ * Find code clones: pairs of symbols with similar normalized source.
159
+ * Uses hash-based bucketing for O(n) average case instead of O(n²) all-pairs.
160
+ */
161
+ export async function findClones(repo, options) {
162
+ const index = await getCodeIndex(repo);
163
+ if (!index) {
164
+ throw new Error(`Repository "${repo}" not found. Index it first with index_folder.`);
165
+ }
166
+ const minSimilarity = options?.min_similarity ?? DEFAULT_MIN_SIMILARITY;
167
+ const minLines = options?.min_lines ?? MIN_CLONE_LINES;
168
+ const includeTests = options?.include_tests ?? false;
169
+ const filePattern = options?.file_pattern;
170
+ const entries = prepareEntries(index.symbols, minLines, includeTests, filePattern);
171
+ const exactClones = findExactMatches(entries, minSimilarity, minLines, MAX_CLONES);
172
+ const nearClones = findNearMatches(entries, exactClones, minSimilarity, minLines, MAX_CLONES);
173
+ const allClones = [...exactClones, ...nearClones];
174
+ allClones.sort((a, b) => b.similarity - a.similarity);
175
+ return {
176
+ clones: allClones.slice(0, MAX_CLONES),
177
+ scanned_symbols: entries.length,
178
+ threshold: minSimilarity,
179
+ };
180
+ }
181
+ //# sourceMappingURL=clone-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clone-tools.js","sourceRoot":"","sources":["../../src/tools/clone-tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ export interface Community {
2
+ id: number;
3
+ name: string;
4
+ files: string[];
5
+ symbol_count: number;
6
+ internal_edges: number;
7
+ external_edges: number;
8
+ cohesion: number;
9
+ }
10
+ export interface CommunityResult {
11
+ communities: Community[];
12
+ modularity: number;
13
+ total_files: number;
14
+ algorithm: "louvain";
15
+ resolution: number;
16
+ }
17
+ /**
18
+ * Detect code communities using Louvain algorithm on the import graph.
19
+ */
20
+ export declare function detectCommunities(repo: string, focus?: string, resolution?: number, outputFormat?: "json" | "mermaid"): Promise<CommunityResult | {
21
+ mermaid: string;
22
+ }>;
23
+ //# sourceMappingURL=community-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"community-tools.d.ts","sourceRoot":"","sources":["../../src/tools/community-tools.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,SAAS,EAAE,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,SAAS,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB;AA2ND;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,MAAM,EACnB,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,GAChC,OAAO,CAAC,eAAe,GAAG;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CA6FhD"}
@@ -0,0 +1,297 @@
1
+ /**
2
+ * Louvain community detection — discover code clusters from the import graph.
3
+ */
4
+ import { getCodeIndex } from "./index-tools.js";
5
+ import { collectImportEdges } from "../utils/import-graph.js";
6
+ /**
7
+ * Louvain method for community detection on an undirected weighted graph.
8
+ * Returns mapping: node → community ID.
9
+ */
10
+ function louvain(nodes, adj, resolution) {
11
+ const community = new Map();
12
+ const nodeSet = new Set(nodes);
13
+ // Init: each node in its own community
14
+ let nextId = 0;
15
+ for (const node of nodes) {
16
+ community.set(node, nextId++);
17
+ }
18
+ // Total edge weight
19
+ let totalWeight = 0;
20
+ for (const [, neighbors] of adj) {
21
+ for (const [, w] of neighbors)
22
+ totalWeight += w;
23
+ }
24
+ totalWeight /= 2; // Each edge counted twice
25
+ if (totalWeight === 0)
26
+ return community;
27
+ // Degree (sum of edge weights per node)
28
+ const degree = new Map();
29
+ for (const node of nodes) {
30
+ let d = 0;
31
+ const neighbors = adj.get(node);
32
+ if (neighbors)
33
+ for (const [, w] of neighbors)
34
+ d += w;
35
+ degree.set(node, d);
36
+ }
37
+ // Phase 1: Local moves
38
+ const MAX_PASSES = 20;
39
+ for (let pass = 0; pass < MAX_PASSES; pass++) {
40
+ let improved = false;
41
+ for (const node of nodes) {
42
+ if (!nodeSet.has(node))
43
+ continue;
44
+ const currentComm = community.get(node);
45
+ const ki = degree.get(node) ?? 0;
46
+ const neighbors = adj.get(node);
47
+ if (!neighbors)
48
+ continue;
49
+ // Calculate weight to each neighboring community
50
+ const commWeights = new Map();
51
+ for (const [neighbor, w] of neighbors) {
52
+ const nc = community.get(neighbor);
53
+ commWeights.set(nc, (commWeights.get(nc) ?? 0) + w);
54
+ }
55
+ // Sum of degrees in current community (excluding this node)
56
+ let sigmaCurrentWithout = 0;
57
+ for (const [n, c] of community) {
58
+ if (c === currentComm && n !== node)
59
+ sigmaCurrentWithout += degree.get(n) ?? 0;
60
+ }
61
+ const weightToCurrentComm = commWeights.get(currentComm) ?? 0;
62
+ const removeCost = weightToCurrentComm - resolution * ki * sigmaCurrentWithout / (2 * totalWeight);
63
+ let bestComm = currentComm;
64
+ let bestGain = 0;
65
+ for (const [targetComm, weightToTarget] of commWeights) {
66
+ if (targetComm === currentComm)
67
+ continue;
68
+ let sigmaTarget = 0;
69
+ for (const [n, c] of community) {
70
+ if (c === targetComm)
71
+ sigmaTarget += degree.get(n) ?? 0;
72
+ }
73
+ const gain = (weightToTarget - resolution * ki * sigmaTarget / (2 * totalWeight)) - removeCost;
74
+ if (gain > bestGain) {
75
+ bestGain = gain;
76
+ bestComm = targetComm;
77
+ }
78
+ }
79
+ if (bestComm !== currentComm) {
80
+ community.set(node, bestComm);
81
+ improved = true;
82
+ }
83
+ }
84
+ if (!improved)
85
+ break;
86
+ }
87
+ // Renumber communities to be contiguous (0, 1, 2, ...)
88
+ const commMap = new Map();
89
+ let nextComm = 0;
90
+ for (const [, c] of community) {
91
+ if (!commMap.has(c))
92
+ commMap.set(c, nextComm++);
93
+ }
94
+ for (const [node, c] of community) {
95
+ community.set(node, commMap.get(c));
96
+ }
97
+ return community;
98
+ }
99
+ /**
100
+ * Calculate modularity Q for a partition.
101
+ */
102
+ function calculateModularity(community, adj) {
103
+ let totalWeight = 0;
104
+ for (const [, neighbors] of adj) {
105
+ for (const [, w] of neighbors)
106
+ totalWeight += w;
107
+ }
108
+ totalWeight /= 2;
109
+ if (totalWeight === 0)
110
+ return 0;
111
+ const degree = new Map();
112
+ for (const [node, neighbors] of adj) {
113
+ let d = 0;
114
+ for (const [, w] of neighbors)
115
+ d += w;
116
+ degree.set(node, d);
117
+ }
118
+ let Q = 0;
119
+ for (const [i, neighbors] of adj) {
120
+ for (const [j, Aij] of neighbors) {
121
+ if (community.get(i) !== community.get(j))
122
+ continue;
123
+ const ki = degree.get(i) ?? 0;
124
+ const kj = degree.get(j) ?? 0;
125
+ Q += Aij - (ki * kj) / (2 * totalWeight);
126
+ }
127
+ }
128
+ return Q / (2 * totalWeight);
129
+ }
130
+ /**
131
+ * Auto-name a community from the most specific common path prefix.
132
+ * Falls back to most frequent directory if no unique prefix.
133
+ */
134
+ function nameCommunity(files, id) {
135
+ if (files.length === 0)
136
+ return `community-${id}`;
137
+ if (files.length === 1) {
138
+ const dir = files[0].split("/").slice(0, -1).join("/");
139
+ return dir || files[0];
140
+ }
141
+ // Find deepest common prefix
142
+ const parts = files.map((f) => f.split("/"));
143
+ const minLen = Math.min(...parts.map((p) => p.length));
144
+ let common = 0;
145
+ for (let i = 0; i < minLen - 1; i++) {
146
+ if (parts.every((p) => p[i] === parts[0][i]))
147
+ common = i + 1;
148
+ else
149
+ break;
150
+ }
151
+ // If common prefix is too short (just "src"), use most frequent subdirectory
152
+ if (common <= 1 && minLen > 2) {
153
+ const dirCounts = new Map();
154
+ for (const p of parts) {
155
+ const dir = p.slice(0, Math.min(3, p.length - 1)).join("/");
156
+ dirCounts.set(dir, (dirCounts.get(dir) ?? 0) + 1);
157
+ }
158
+ const topDir = [...dirCounts.entries()].sort((a, b) => b[1] - a[1])[0];
159
+ if (topDir)
160
+ return topDir[0];
161
+ }
162
+ return common > 0
163
+ ? parts[0].slice(0, common).join("/")
164
+ : `community-${id}`;
165
+ }
166
+ const MAX_MERMAID_COMMUNITIES = 15;
167
+ const MAX_MERMAID_FILES_PER = 5;
168
+ function communityToMermaid(result, edges) {
169
+ const lines = ["graph LR"];
170
+ const comms = result.communities.slice(0, MAX_MERMAID_COMMUNITIES);
171
+ const fileToCommunity = new Map();
172
+ for (const c of comms) {
173
+ for (const f of c.files) {
174
+ if (!f.startsWith("..."))
175
+ fileToCommunity.set(f, c.id);
176
+ }
177
+ }
178
+ for (const c of comms) {
179
+ const safeId = `c${c.id}`;
180
+ const label = `${c.name} (${c.files.length} files)`;
181
+ lines.push(` subgraph ${safeId}["${label}"]`);
182
+ const showFiles = c.files.filter((f) => !f.startsWith("...")).slice(0, MAX_MERMAID_FILES_PER);
183
+ for (const f of showFiles) {
184
+ const short = f.split("/").pop()?.replace(/\.\w+$/, "") ?? f;
185
+ const nodeId = (safeId + "_" + short).replace(/[^a-zA-Z0-9_]/g, "_");
186
+ lines.push(` ${nodeId}["${short}"]`);
187
+ }
188
+ lines.push(" end");
189
+ }
190
+ const crossEdges = new Set();
191
+ for (const edge of edges) {
192
+ const fromC = fileToCommunity.get(edge.from);
193
+ const toC = fileToCommunity.get(edge.to);
194
+ if (fromC !== undefined && toC !== undefined && fromC !== toC) {
195
+ const key = fromC < toC ? `c${fromC}-->c${toC}` : `c${toC}-->c${fromC}`;
196
+ if (!crossEdges.has(key)) {
197
+ crossEdges.add(key);
198
+ lines.push(` c${Math.min(fromC, toC)} --> c${Math.max(fromC, toC)}`);
199
+ }
200
+ }
201
+ }
202
+ return lines.join("\n");
203
+ }
204
+ /**
205
+ * Detect code communities using Louvain algorithm on the import graph.
206
+ */
207
+ export async function detectCommunities(repo, focus, resolution, outputFormat) {
208
+ const index = await getCodeIndex(repo);
209
+ if (!index)
210
+ throw new Error(`Repository "${repo}" not found.`);
211
+ // Filter files by focus; cap without focus to prevent 66K tok responses
212
+ const MAX_UNFOCUSED_FILES = 500;
213
+ const MAX_COMMUNITIES = 20;
214
+ let files = focus
215
+ ? index.files.filter((f) => f.path.includes(focus))
216
+ : index.files;
217
+ if (!focus && files.length > MAX_UNFOCUSED_FILES) {
218
+ // Keep files with most symbols (most architecturally relevant)
219
+ files = [...files].sort((a, b) => b.symbol_count - a.symbol_count).slice(0, MAX_UNFOCUSED_FILES);
220
+ }
221
+ const fileSet = new Set(files.map((f) => f.path));
222
+ const edges = await collectImportEdges(index, fileSet);
223
+ // Build weighted undirected adjacency
224
+ const adj = new Map();
225
+ for (const node of fileSet)
226
+ adj.set(node, new Map());
227
+ for (const edge of edges) {
228
+ if (!fileSet.has(edge.from) || !fileSet.has(edge.to))
229
+ continue;
230
+ const fromAdj = adj.get(edge.from);
231
+ fromAdj.set(edge.to, (fromAdj.get(edge.to) ?? 0) + 1);
232
+ const toAdj = adj.get(edge.to);
233
+ toAdj.set(edge.from, (toAdj.get(edge.from) ?? 0) + 1);
234
+ }
235
+ const res = resolution ?? 1.0;
236
+ const communityMap = louvain([...fileSet], adj, res);
237
+ const modularity = calculateModularity(communityMap, adj);
238
+ // Group files by community
239
+ const groups = new Map();
240
+ for (const [file, comm] of communityMap) {
241
+ let list = groups.get(comm);
242
+ if (!list) {
243
+ list = [];
244
+ groups.set(comm, list);
245
+ }
246
+ list.push(file);
247
+ }
248
+ // Symbol count per file
249
+ const symCountByFile = new Map();
250
+ for (const f of index.files)
251
+ symCountByFile.set(f.path, f.symbol_count);
252
+ // Build community objects
253
+ const communities = [];
254
+ for (const [id, communityFiles] of [...groups.entries()].sort((a, b) => b[1].length - a[1].length)) {
255
+ const fileSetComm = new Set(communityFiles);
256
+ let internal = 0;
257
+ let external = 0;
258
+ for (const edge of edges) {
259
+ const fromIn = fileSetComm.has(edge.from);
260
+ const toIn = fileSetComm.has(edge.to);
261
+ if (fromIn && toIn)
262
+ internal++;
263
+ else if (fromIn || toIn)
264
+ external++;
265
+ }
266
+ const MAX_FILES_PER_COMMUNITY = 20;
267
+ const sortedFiles = communityFiles.sort();
268
+ communities.push({
269
+ id,
270
+ name: nameCommunity(communityFiles, id),
271
+ files: sortedFiles.length > MAX_FILES_PER_COMMUNITY
272
+ ? [...sortedFiles.slice(0, MAX_FILES_PER_COMMUNITY), `... +${sortedFiles.length - MAX_FILES_PER_COMMUNITY} more`]
273
+ : sortedFiles,
274
+ symbol_count: communityFiles.reduce((sum, f) => sum + (symCountByFile.get(f) ?? 0), 0),
275
+ internal_edges: internal,
276
+ external_edges: external,
277
+ cohesion: internal + external > 0 ? internal / (internal + external) : 0,
278
+ });
279
+ }
280
+ // Cap communities output
281
+ const cappedCommunities = communities.slice(0, MAX_COMMUNITIES);
282
+ const result = {
283
+ communities: cappedCommunities,
284
+ modularity: Math.round(modularity * 1000) / 1000,
285
+ total_files: files.length,
286
+ ...(communities.length > MAX_COMMUNITIES
287
+ ? { truncated: true, total_communities: communities.length }
288
+ : {}),
289
+ algorithm: "louvain",
290
+ resolution: res,
291
+ };
292
+ if (outputFormat === "mermaid") {
293
+ return { mermaid: communityToMermaid(result, edges) };
294
+ }
295
+ return result;
296
+ }
297
+ //# sourceMappingURL=community-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"community-tools.js","sourceRoot":"","sources":["../../src/tools/community-tools.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAqB9D;;;GAGG;AACH,SAAS,OAAO,CACd,KAAe,EACf,GAAqC,EACrC,UAAkB;IAElB,MAAM,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC5C,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;IAE/B,uCAAuC;IACvC,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAChC,CAAC;IAED,oBAAoB;IACpB,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,KAAK,MAAM,CAAC,EAAE,SAAS,CAAC,IAAI,GAAG,EAAE,CAAC;QAChC,KAAK,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,SAAS;YAAE,WAAW,IAAI,CAAC,CAAC;IAClD,CAAC;IACD,WAAW,IAAI,CAAC,CAAC,CAAC,0BAA0B;IAC5C,IAAI,WAAW,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAExC,wCAAwC;IACxC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,GAAG,CAAC,CAAC;QACV,MAAM,SAAS,GAAG,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAChC,IAAI,SAAS;YAAE,KAAK,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,SAAS;gBAAE,CAAC,IAAI,CAAC,CAAC;QACrD,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACtB,CAAC;IAED,uBAAuB;IACvB,MAAM,UAAU,GAAG,EAAE,CAAC;IACtB,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,UAAU,EAAE,IAAI,EAAE,EAAE,CAAC;QAC7C,IAAI,QAAQ,GAAG,KAAK,CAAC;QAErB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,SAAS;YAEjC,MAAM,WAAW,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAE,CAAC;YACzC,MAAM,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACjC,MAAM,SAAS,GAAG,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAChC,IAAI,CAAC,SAAS;gBAAE,SAAS;YAEzB,iDAAiD;YACjD,MAAM,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAC;YAC9C,KAAK,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,IAAI,SAAS,EAAE,CAAC;gBACtC,MAAM,EAAE,GAAG,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAE,CAAC;gBACpC,WAAW,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YACtD,CAAC;YAED,4DAA4D;YAC5D,IAAI,mBAAmB,GAAG,CAAC,CAAC;YAC5B,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,SAAS,EAAE,CAAC;gBAC/B,IAAI,CAAC,KAAK,WAAW,IAAI,CAAC,KAAK,IAAI;oBAAE,mBAAmB,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YACjF,CAAC;YAED,MAAM,mBAAmB,GAAG,WAAW,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;YAC9D,MAAM,UAAU,GAAG,mBAAmB,GAAG,UAAU,GAAG,EAAE,GAAG,mBAAmB,GAAG,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC;YAEnG,IAAI,QAAQ,GAAG,WAAW,CAAC;YAC3B,IAAI,QAAQ,GAAG,CAAC,CAAC;YAEjB,KAAK,MAAM,CAAC,UAAU,EAAE,cAAc,CAAC,IAAI,WAAW,EAAE,CAAC;gBACvD,IAAI,UAAU,KAAK,WAAW;oBAAE,SAAS;gBAEzC,IAAI,WAAW,GAAG,CAAC,CAAC;gBACpB,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,SAAS,EAAE,CAAC;oBAC/B,IAAI,CAAC,KAAK,UAAU;wBAAE,WAAW,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;gBAC1D,CAAC;gBAED,MAAM,IAAI,GAAG,CAAC,cAAc,GAAG,UAAU,GAAG,EAAE,GAAG,WAAW,GAAG,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,GAAG,UAAU,CAAC;gBAC/F,IAAI,IAAI,GAAG,QAAQ,EAAE,CAAC;oBACpB,QAAQ,GAAG,IAAI,CAAC;oBAChB,QAAQ,GAAG,UAAU,CAAC;gBACxB,CAAC;YACH,CAAC;YAED,IAAI,QAAQ,KAAK,WAAW,EAAE,CAAC;gBAC7B,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;gBAC9B,QAAQ,GAAG,IAAI,CAAC;YAClB,CAAC;QACH,CAAC;QAED,IAAI,CAAC,QAAQ;YAAE,MAAM;IACvB,CAAC;IAED,uDAAuD;IACvD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC1C,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,KAAK,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,SAAS,EAAE,CAAC;QAC9B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;YAAE,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;IAClD,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,SAAS,EAAE,CAAC;QAClC,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAE,CAAC,CAAC;IACvC,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;GAEG;AACH,SAAS,mBAAmB,CAC1B,SAA8B,EAC9B,GAAqC;IAErC,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,KAAK,MAAM,CAAC,EAAE,SAAS,CAAC,IAAI,GAAG,EAAE,CAAC;QAChC,KAAK,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,SAAS;YAAE,WAAW,IAAI,CAAC,CAAC;IAClD,CAAC;IACD,WAAW,IAAI,CAAC,CAAC;IACjB,IAAI,WAAW,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAEhC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,KAAK,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,GAAG,EAAE,CAAC;QACpC,IAAI,CAAC,GAAG,CAAC,CAAC;QACV,KAAK,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,SAAS;YAAE,CAAC,IAAI,CAAC,CAAC;QACtC,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACtB,CAAC;IAED,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,KAAK,MAAM,CAAC,CAAC,EAAE,SAAS,CAAC,IAAI,GAAG,EAAE,CAAC;QACjC,KAAK,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,SAAS,EAAE,CAAC;YACjC,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;gBAAE,SAAS;YACpD,MAAM,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAC9B,MAAM,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAC9B,CAAC,IAAI,GAAG,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC;AAC/B,CAAC;AAED;;;GAGG;AACH,SAAS,aAAa,CAAC,KAAe,EAAE,EAAU;IAChD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,aAAa,EAAE,EAAE,CAAC;IACjD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACxD,OAAO,GAAG,IAAI,KAAK,CAAC,CAAC,CAAE,CAAC;IAC1B,CAAC;IAED,6BAA6B;IAC7B,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IACvD,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACpC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAC;YAAE,MAAM,GAAG,CAAC,GAAG,CAAC,CAAC;;YACzD,MAAM;IACb,CAAC;IAED,6EAA6E;IAC7E,IAAI,MAAM,IAAI,CAAC,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9B,MAAM,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAC;QAC5C,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,MAAM,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC5D,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACpD,CAAC;QACD,MAAM,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACvE,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;IAC/B,CAAC;IAED,OAAO,MAAM,GAAG,CAAC;QACf,CAAC,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;QACtC,CAAC,CAAC,aAAa,EAAE,EAAE,CAAC;AACxB,CAAC;AAED,MAAM,uBAAuB,GAAG,EAAE,CAAC;AACnC,MAAM,qBAAqB,GAAG,CAAC,CAAC;AAEhC,SAAS,kBAAkB,CAAC,MAAuB,EAAE,KAAmB;IACtE,MAAM,KAAK,GAAa,CAAC,UAAU,CAAC,CAAC;IACrC,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,uBAAuB,CAAC,CAAC;IAEnE,MAAM,eAAe,GAAG,IAAI,GAAG,EAAkB,CAAC;IAClD,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;YACxB,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC;gBAAE,eAAe,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;IAED,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC;QAC1B,MAAM,KAAK,GAAG,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,KAAK,CAAC,MAAM,SAAS,CAAC;QACpD,KAAK,CAAC,IAAI,CAAC,gBAAgB,MAAM,KAAK,KAAK,IAAI,CAAC,CAAC;QACjD,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,qBAAqB,CAAC,CAAC;QAC9F,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;YAC1B,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;YAC7D,MAAM,MAAM,GAAG,CAAC,MAAM,GAAG,GAAG,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,gBAAgB,EAAE,GAAG,CAAC,CAAC;YACrE,KAAK,CAAC,IAAI,CAAC,WAAW,MAAM,KAAK,KAAK,IAAI,CAAC,CAAC;QAC9C,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACxB,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,GAAG,EAAU,CAAC;IACrC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7C,MAAM,GAAG,GAAG,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACzC,IAAI,KAAK,KAAK,SAAS,IAAI,GAAG,KAAK,SAAS,IAAI,KAAK,KAAK,GAAG,EAAE,CAAC;YAC9D,MAAM,GAAG,GAAG,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,OAAO,KAAK,EAAE,CAAC;YACxE,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBACzB,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBACpB,KAAK,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,SAAS,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;YAC1E,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,IAAY,EACZ,KAAc,EACd,UAAmB,EACnB,YAAiC;IAEjC,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;IACvC,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,eAAe,IAAI,cAAc,CAAC,CAAC;IAE/D,wEAAwE;IACxE,MAAM,mBAAmB,GAAG,GAAG,CAAC;IAChC,MAAM,eAAe,GAAG,EAAE,CAAC;IAC3B,IAAI,KAAK,GAAG,KAAK;QACf,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACnD,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC;IAEhB,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,mBAAmB,EAAE,CAAC;QACjD,+DAA+D;QAC/D,KAAK,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,mBAAmB,CAAC,CAAC;IACnG,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAClD,MAAM,KAAK,GAAG,MAAM,kBAAkB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAEvD,sCAAsC;IACtC,MAAM,GAAG,GAAG,IAAI,GAAG,EAA+B,CAAC;IACnD,KAAK,MAAM,IAAI,IAAI,OAAO;QAAE,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;IACrD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAAE,SAAS;QAC/D,MAAM,OAAO,GAAG,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAE,CAAC;QACpC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACtD,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAE,CAAC;QAChC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACxD,CAAC;IAED,MAAM,GAAG,GAAG,UAAU,IAAI,GAAG,CAAC;IAC9B,MAAM,YAAY,GAAG,OAAO,CAAC,CAAC,GAAG,OAAO,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IACrD,MAAM,UAAU,GAAG,mBAAmB,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;IAE1D,2BAA2B;IAC3B,MAAM,MAAM,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC3C,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,YAAY,EAAE,CAAC;QACxC,IAAI,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC5B,IAAI,CAAC,IAAI,EAAE,CAAC;YAAC,IAAI,GAAG,EAAE,CAAC;YAAC,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAAC,CAAC;QACjD,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClB,CAAC;IAED,wBAAwB;IACxB,MAAM,cAAc,GAAG,IAAI,GAAG,EAAkB,CAAC;IACjD,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,KAAK;QAAE,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC;IAExE,0BAA0B;IAC1B,MAAM,WAAW,GAAgB,EAAE,CAAC;IACpC,KAAK,MAAM,CAAC,EAAE,EAAE,cAAc,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;QACnG,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,cAAc,CAAC,CAAC;QAC5C,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC1C,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACtC,IAAI,MAAM,IAAI,IAAI;gBAAE,QAAQ,EAAE,CAAC;iBAC1B,IAAI,MAAM,IAAI,IAAI;gBAAE,QAAQ,EAAE,CAAC;QACtC,CAAC;QAED,MAAM,uBAAuB,GAAG,EAAE,CAAC;QACnC,MAAM,WAAW,GAAG,cAAc,CAAC,IAAI,EAAE,CAAC;QAC1C,WAAW,CAAC,IAAI,CAAC;YACf,EAAE;YACF,IAAI,EAAE,aAAa,CAAC,cAAc,EAAE,EAAE,CAAC;YACvC,KAAK,EAAE,WAAW,CAAC,MAAM,GAAG,uBAAuB;gBACjD,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,uBAAuB,CAAC,EAAE,QAAQ,WAAW,CAAC,MAAM,GAAG,uBAAuB,OAAO,CAAC;gBACjH,CAAC,CAAC,WAAW;YACf,YAAY,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC;YACtF,cAAc,EAAE,QAAQ;YACxB,cAAc,EAAE,QAAQ;YACxB,QAAQ,EAAE,QAAQ,GAAG,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;SACzE,CAAC,CAAC;IACL,CAAC;IAED,yBAAyB;IACzB,MAAM,iBAAiB,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC;IAEhE,MAAM,MAAM,GAAoB;QAC9B,WAAW,EAAE,iBAAiB;QAC9B,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,IAAI;QAChD,WAAW,EAAE,KAAK,CAAC,MAAM;QACzB,GAAG,CAAC,WAAW,CAAC,MAAM,GAAG,eAAe;YACtC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,iBAAiB,EAAE,WAAW,CAAC,MAAM,EAAE;YAC5D,CAAC,CAAC,EAAE,CAAC;QACP,SAAS,EAAE,SAAS;QACpB,UAAU,EAAE,GAAG;KAChB,CAAC;IAEF,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO,EAAE,OAAO,EAAE,kBAAkB,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC;IACxD,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}