eff-u-code 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (245) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +256 -0
  3. package/bin/fuck-u-code-mcp.js +2 -0
  4. package/bin/fuck-u-code.js +2 -0
  5. package/bin/postinstall.js +53 -0
  6. package/dist/ai/index.d.ts +34 -0
  7. package/dist/ai/index.d.ts.map +1 -0
  8. package/dist/ai/index.js +227 -0
  9. package/dist/ai/index.js.map +1 -0
  10. package/dist/ai/prompts/code-review.d.ts +9 -0
  11. package/dist/ai/prompts/code-review.d.ts.map +1 -0
  12. package/dist/ai/prompts/code-review.js +61 -0
  13. package/dist/ai/prompts/code-review.js.map +1 -0
  14. package/dist/ai/providers/anthropic.d.ts +11 -0
  15. package/dist/ai/providers/anthropic.d.ts.map +1 -0
  16. package/dist/ai/providers/anthropic.js +60 -0
  17. package/dist/ai/providers/anthropic.js.map +1 -0
  18. package/dist/ai/providers/fetch.d.ts +10 -0
  19. package/dist/ai/providers/fetch.d.ts.map +1 -0
  20. package/dist/ai/providers/fetch.js +50 -0
  21. package/dist/ai/providers/fetch.js.map +1 -0
  22. package/dist/ai/providers/gemini.d.ts +12 -0
  23. package/dist/ai/providers/gemini.d.ts.map +1 -0
  24. package/dist/ai/providers/gemini.js +66 -0
  25. package/dist/ai/providers/gemini.js.map +1 -0
  26. package/dist/ai/providers/ollama.d.ts +11 -0
  27. package/dist/ai/providers/ollama.d.ts.map +1 -0
  28. package/dist/ai/providers/ollama.js +54 -0
  29. package/dist/ai/providers/ollama.js.map +1 -0
  30. package/dist/ai/providers/openai.d.ts +11 -0
  31. package/dist/ai/providers/openai.d.ts.map +1 -0
  32. package/dist/ai/providers/openai.js +52 -0
  33. package/dist/ai/providers/openai.js.map +1 -0
  34. package/dist/ai/selector.d.ts +19 -0
  35. package/dist/ai/selector.d.ts.map +1 -0
  36. package/dist/ai/selector.js +145 -0
  37. package/dist/ai/selector.js.map +1 -0
  38. package/dist/ai/types.d.ts +120 -0
  39. package/dist/ai/types.d.ts.map +1 -0
  40. package/dist/ai/types.js +6 -0
  41. package/dist/ai/types.js.map +1 -0
  42. package/dist/analyzer/concurrent-analyzer.d.ts +11 -0
  43. package/dist/analyzer/concurrent-analyzer.d.ts.map +1 -0
  44. package/dist/analyzer/concurrent-analyzer.js +67 -0
  45. package/dist/analyzer/concurrent-analyzer.js.map +1 -0
  46. package/dist/analyzer/file-discovery.d.ts +23 -0
  47. package/dist/analyzer/file-discovery.d.ts.map +1 -0
  48. package/dist/analyzer/file-discovery.js +64 -0
  49. package/dist/analyzer/file-discovery.js.map +1 -0
  50. package/dist/analyzer/index.d.ts +27 -0
  51. package/dist/analyzer/index.d.ts.map +1 -0
  52. package/dist/analyzer/index.js +64 -0
  53. package/dist/analyzer/index.js.map +1 -0
  54. package/dist/cli/commands/ai-review.d.ts +6 -0
  55. package/dist/cli/commands/ai-review.d.ts.map +1 -0
  56. package/dist/cli/commands/ai-review.js +213 -0
  57. package/dist/cli/commands/ai-review.js.map +1 -0
  58. package/dist/cli/commands/analyze.d.ts +6 -0
  59. package/dist/cli/commands/analyze.d.ts.map +1 -0
  60. package/dist/cli/commands/analyze.js +145 -0
  61. package/dist/cli/commands/analyze.js.map +1 -0
  62. package/dist/cli/commands/config.d.ts +6 -0
  63. package/dist/cli/commands/config.d.ts.map +1 -0
  64. package/dist/cli/commands/config.js +147 -0
  65. package/dist/cli/commands/config.js.map +1 -0
  66. package/dist/cli/commands/mcp-install.d.ts +9 -0
  67. package/dist/cli/commands/mcp-install.d.ts.map +1 -0
  68. package/dist/cli/commands/mcp-install.js +102 -0
  69. package/dist/cli/commands/mcp-install.js.map +1 -0
  70. package/dist/cli/index.d.ts +7 -0
  71. package/dist/cli/index.d.ts.map +1 -0
  72. package/dist/cli/index.js +69 -0
  73. package/dist/cli/index.js.map +1 -0
  74. package/dist/cli/output/ai-review-output.d.ts +20 -0
  75. package/dist/cli/output/ai-review-output.d.ts.map +1 -0
  76. package/dist/cli/output/ai-review-output.js +324 -0
  77. package/dist/cli/output/ai-review-output.js.map +1 -0
  78. package/dist/cli/output/console.d.ts +31 -0
  79. package/dist/cli/output/console.d.ts.map +1 -0
  80. package/dist/cli/output/console.js +571 -0
  81. package/dist/cli/output/console.js.map +1 -0
  82. package/dist/cli/output/html.d.ts +20 -0
  83. package/dist/cli/output/html.d.ts.map +1 -0
  84. package/dist/cli/output/html.js +339 -0
  85. package/dist/cli/output/html.js.map +1 -0
  86. package/dist/cli/output/json.d.ts +8 -0
  87. package/dist/cli/output/json.d.ts.map +1 -0
  88. package/dist/cli/output/json.js +46 -0
  89. package/dist/cli/output/json.js.map +1 -0
  90. package/dist/cli/output/markdown.d.ts +17 -0
  91. package/dist/cli/output/markdown.d.ts.map +1 -0
  92. package/dist/cli/output/markdown.js +323 -0
  93. package/dist/cli/output/markdown.js.map +1 -0
  94. package/dist/cli/output/stats.d.ts +35 -0
  95. package/dist/cli/output/stats.d.ts.map +1 -0
  96. package/dist/cli/output/stats.js +63 -0
  97. package/dist/cli/output/stats.js.map +1 -0
  98. package/dist/cli/output/terminal-markdown.d.ts +23 -0
  99. package/dist/cli/output/terminal-markdown.d.ts.map +1 -0
  100. package/dist/cli/output/terminal-markdown.js +159 -0
  101. package/dist/cli/output/terminal-markdown.js.map +1 -0
  102. package/dist/config/index.d.ts +27 -0
  103. package/dist/config/index.d.ts.map +1 -0
  104. package/dist/config/index.js +266 -0
  105. package/dist/config/index.js.map +1 -0
  106. package/dist/config/schema.d.ts +179 -0
  107. package/dist/config/schema.d.ts.map +1 -0
  108. package/dist/config/schema.js +85 -0
  109. package/dist/config/schema.js.map +1 -0
  110. package/dist/gitignore/index.d.ts +5 -0
  111. package/dist/gitignore/index.d.ts.map +1 -0
  112. package/dist/gitignore/index.js +5 -0
  113. package/dist/gitignore/index.js.map +1 -0
  114. package/dist/gitignore/parser.d.ts +32 -0
  115. package/dist/gitignore/parser.d.ts.map +1 -0
  116. package/dist/gitignore/parser.js +110 -0
  117. package/dist/gitignore/parser.js.map +1 -0
  118. package/dist/gitignore/parser.test.d.ts +2 -0
  119. package/dist/gitignore/parser.test.d.ts.map +1 -0
  120. package/dist/gitignore/parser.test.js +217 -0
  121. package/dist/gitignore/parser.test.js.map +1 -0
  122. package/dist/i18n/index.d.ts +19 -0
  123. package/dist/i18n/index.d.ts.map +1 -0
  124. package/dist/i18n/index.js +43 -0
  125. package/dist/i18n/index.js.map +1 -0
  126. package/dist/i18n/locales/en.json +320 -0
  127. package/dist/i18n/locales/ru.json +320 -0
  128. package/dist/i18n/locales/zh.json +320 -0
  129. package/dist/index.d.ts +5 -0
  130. package/dist/index.d.ts.map +1 -0
  131. package/dist/index.js +10 -0
  132. package/dist/index.js.map +1 -0
  133. package/dist/mcp/server.d.ts +9 -0
  134. package/dist/mcp/server.d.ts.map +1 -0
  135. package/dist/mcp/server.js +156 -0
  136. package/dist/mcp/server.js.map +1 -0
  137. package/dist/metrics/complexity/cognitive.d.ts +25 -0
  138. package/dist/metrics/complexity/cognitive.d.ts.map +1 -0
  139. package/dist/metrics/complexity/cognitive.js +109 -0
  140. package/dist/metrics/complexity/cognitive.js.map +1 -0
  141. package/dist/metrics/complexity/cyclomatic.d.ts +21 -0
  142. package/dist/metrics/complexity/cyclomatic.d.ts.map +1 -0
  143. package/dist/metrics/complexity/cyclomatic.js +111 -0
  144. package/dist/metrics/complexity/cyclomatic.js.map +1 -0
  145. package/dist/metrics/complexity/nesting-depth.d.ts +19 -0
  146. package/dist/metrics/complexity/nesting-depth.d.ts.map +1 -0
  147. package/dist/metrics/complexity/nesting-depth.js +97 -0
  148. package/dist/metrics/complexity/nesting-depth.js.map +1 -0
  149. package/dist/metrics/documentation/comment-ratio.d.ts +21 -0
  150. package/dist/metrics/documentation/comment-ratio.d.ts.map +1 -0
  151. package/dist/metrics/documentation/comment-ratio.js +91 -0
  152. package/dist/metrics/documentation/comment-ratio.js.map +1 -0
  153. package/dist/metrics/duplication/code-duplication.d.ts +24 -0
  154. package/dist/metrics/duplication/code-duplication.d.ts.map +1 -0
  155. package/dist/metrics/duplication/code-duplication.js +167 -0
  156. package/dist/metrics/duplication/code-duplication.js.map +1 -0
  157. package/dist/metrics/duplication/code-duplication.test.d.ts +2 -0
  158. package/dist/metrics/duplication/code-duplication.test.d.ts.map +1 -0
  159. package/dist/metrics/duplication/code-duplication.test.js +612 -0
  160. package/dist/metrics/duplication/code-duplication.test.js.map +1 -0
  161. package/dist/metrics/error/error-handling.d.ts +23 -0
  162. package/dist/metrics/error/error-handling.d.ts.map +1 -0
  163. package/dist/metrics/error/error-handling.js +164 -0
  164. package/dist/metrics/error/error-handling.js.map +1 -0
  165. package/dist/metrics/error/error-handling.test.d.ts +2 -0
  166. package/dist/metrics/error/error-handling.test.d.ts.map +1 -0
  167. package/dist/metrics/error/error-handling.test.js +349 -0
  168. package/dist/metrics/error/error-handling.test.js.map +1 -0
  169. package/dist/metrics/index.d.ts +21 -0
  170. package/dist/metrics/index.d.ts.map +1 -0
  171. package/dist/metrics/index.js +50 -0
  172. package/dist/metrics/index.js.map +1 -0
  173. package/dist/metrics/naming/convention.d.ts +22 -0
  174. package/dist/metrics/naming/convention.d.ts.map +1 -0
  175. package/dist/metrics/naming/convention.js +117 -0
  176. package/dist/metrics/naming/convention.js.map +1 -0
  177. package/dist/metrics/size/file-length.d.ts +19 -0
  178. package/dist/metrics/size/file-length.d.ts.map +1 -0
  179. package/dist/metrics/size/file-length.js +68 -0
  180. package/dist/metrics/size/file-length.js.map +1 -0
  181. package/dist/metrics/size/function-length.d.ts +20 -0
  182. package/dist/metrics/size/function-length.d.ts.map +1 -0
  183. package/dist/metrics/size/function-length.js +101 -0
  184. package/dist/metrics/size/function-length.js.map +1 -0
  185. package/dist/metrics/size/parameter-count.d.ts +19 -0
  186. package/dist/metrics/size/parameter-count.d.ts.map +1 -0
  187. package/dist/metrics/size/parameter-count.js +97 -0
  188. package/dist/metrics/size/parameter-count.js.map +1 -0
  189. package/dist/metrics/structure/structure-analysis.d.ts +24 -0
  190. package/dist/metrics/structure/structure-analysis.d.ts.map +1 -0
  191. package/dist/metrics/structure/structure-analysis.js +223 -0
  192. package/dist/metrics/structure/structure-analysis.js.map +1 -0
  193. package/dist/metrics/structure/structure-analysis.test.d.ts +2 -0
  194. package/dist/metrics/structure/structure-analysis.test.d.ts.map +1 -0
  195. package/dist/metrics/structure/structure-analysis.test.js +342 -0
  196. package/dist/metrics/structure/structure-analysis.test.js.map +1 -0
  197. package/dist/metrics/types.d.ts +71 -0
  198. package/dist/metrics/types.d.ts.map +1 -0
  199. package/dist/metrics/types.js +5 -0
  200. package/dist/metrics/types.js.map +1 -0
  201. package/dist/parser/generic-parser.d.ts +28 -0
  202. package/dist/parser/generic-parser.d.ts.map +1 -0
  203. package/dist/parser/generic-parser.js +218 -0
  204. package/dist/parser/generic-parser.js.map +1 -0
  205. package/dist/parser/index.d.ts +19 -0
  206. package/dist/parser/index.d.ts.map +1 -0
  207. package/dist/parser/index.js +52 -0
  208. package/dist/parser/index.js.map +1 -0
  209. package/dist/parser/regex-parser.d.ts +46 -0
  210. package/dist/parser/regex-parser.d.ts.map +1 -0
  211. package/dist/parser/regex-parser.js +560 -0
  212. package/dist/parser/regex-parser.js.map +1 -0
  213. package/dist/parser/tree-sitter-parser.d.ts +50 -0
  214. package/dist/parser/tree-sitter-parser.d.ts.map +1 -0
  215. package/dist/parser/tree-sitter-parser.js +707 -0
  216. package/dist/parser/tree-sitter-parser.js.map +1 -0
  217. package/dist/parser/types.d.ts +52 -0
  218. package/dist/parser/types.d.ts.map +1 -0
  219. package/dist/parser/types.js +49 -0
  220. package/dist/parser/types.js.map +1 -0
  221. package/dist/scoring/index.d.ts +14 -0
  222. package/dist/scoring/index.d.ts.map +1 -0
  223. package/dist/scoring/index.js +80 -0
  224. package/dist/scoring/index.js.map +1 -0
  225. package/dist/utils/fs.d.ts +24 -0
  226. package/dist/utils/fs.d.ts.map +1 -0
  227. package/dist/utils/fs.js +61 -0
  228. package/dist/utils/fs.js.map +1 -0
  229. package/dist/utils/logger.d.ts +13 -0
  230. package/dist/utils/logger.d.ts.map +1 -0
  231. package/dist/utils/logger.js +43 -0
  232. package/dist/utils/logger.js.map +1 -0
  233. package/dist/utils/markdown.d.ts +16 -0
  234. package/dist/utils/markdown.d.ts.map +1 -0
  235. package/dist/utils/markdown.js +303 -0
  236. package/dist/utils/markdown.js.map +1 -0
  237. package/dist/utils/progress.d.ts +24 -0
  238. package/dist/utils/progress.d.ts.map +1 -0
  239. package/dist/utils/progress.js +79 -0
  240. package/dist/utils/progress.js.map +1 -0
  241. package/dist/utils/terminal.d.ts +62 -0
  242. package/dist/utils/terminal.d.ts.map +1 -0
  243. package/dist/utils/terminal.js +207 -0
  244. package/dist/utils/terminal.js.map +1 -0
  245. package/package.json +77 -0
@@ -0,0 +1,120 @@
1
+ /**
2
+ * AI module type definitions
3
+ * Adapted from tmp/ai/internal/types/types.ts
4
+ */
5
+ /** AI provider instance configuration */
6
+ export interface ProviderInstanceConfig {
7
+ name: string;
8
+ enabled: boolean;
9
+ baseUrl: string;
10
+ apiKey: string;
11
+ models: string[];
12
+ maxTokens: number;
13
+ temperature: number;
14
+ topP: number;
15
+ topK?: number;
16
+ timeout: number;
17
+ maxRetries: number;
18
+ rateLimit?: string;
19
+ }
20
+ /** AI provider configuration */
21
+ export interface ProviderConfig {
22
+ enabled: boolean;
23
+ instances: ProviderInstanceConfig[];
24
+ }
25
+ /** AI configuration */
26
+ export interface AIConfig {
27
+ providers: Record<string, ProviderConfig>;
28
+ defaultProvider?: string;
29
+ }
30
+ /** Chat message */
31
+ export interface Message {
32
+ role: 'system' | 'user' | 'assistant';
33
+ content: string;
34
+ }
35
+ /** Chat request */
36
+ export interface ChatRequest {
37
+ model?: string;
38
+ messages: Message[];
39
+ maxTokens?: number;
40
+ temperature?: number;
41
+ }
42
+ /** Chat response choice */
43
+ export interface Choice {
44
+ index: number;
45
+ message: Message;
46
+ finishReason: string;
47
+ }
48
+ /** Token usage statistics */
49
+ export interface Usage {
50
+ promptTokens: number;
51
+ completionTokens: number;
52
+ totalTokens: number;
53
+ }
54
+ /** Chat response */
55
+ export interface ChatResponse {
56
+ id: string;
57
+ model: string;
58
+ choices: Choice[];
59
+ usage: Usage;
60
+ provider: string;
61
+ }
62
+ /** Stream response delta */
63
+ export interface MessageDelta {
64
+ role?: string;
65
+ content?: string;
66
+ }
67
+ /** Stream response choice */
68
+ export interface StreamChoice {
69
+ index: number;
70
+ delta: MessageDelta;
71
+ finishReason: string;
72
+ }
73
+ /** Stream chat response */
74
+ export interface ChatStreamResponse {
75
+ id: string;
76
+ model: string;
77
+ choices: StreamChoice[];
78
+ usage?: Usage;
79
+ provider: string;
80
+ }
81
+ /** Provider context */
82
+ export interface ProviderContext {
83
+ providerName: string;
84
+ instanceName: string;
85
+ baseUrl: string;
86
+ apiKey: string;
87
+ model: string;
88
+ maxTokens: number;
89
+ temperature: number;
90
+ topP: number;
91
+ topK?: number;
92
+ timeout: number;
93
+ maxRetries: number;
94
+ }
95
+ /** AI provider interface */
96
+ export interface Provider {
97
+ chat(request: ChatRequest): Promise<ChatResponse>;
98
+ chatStream(request: ChatRequest): Promise<ReadableStream<ChatStreamResponse>>;
99
+ }
100
+ /** AI review result */
101
+ export interface AIReviewResult {
102
+ summary: string;
103
+ issues: AIReviewIssue[];
104
+ suggestions: string[];
105
+ securityConcerns: string[];
106
+ refactoringOpportunities: string[];
107
+ }
108
+ /** AI review issue */
109
+ export interface AIReviewIssue {
110
+ severity: 'low' | 'medium' | 'high' | 'critical';
111
+ category: string;
112
+ description: string;
113
+ location?: {
114
+ file: string;
115
+ line?: number;
116
+ function?: string;
117
+ };
118
+ suggestion?: string;
119
+ }
120
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/ai/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,yCAAyC;AACzC,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,gCAAgC;AAChC,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,sBAAsB,EAAE,CAAC;CACrC;AAED,uBAAuB;AACvB,MAAM,WAAW,QAAQ;IACvB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC1C,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,mBAAmB;AACnB,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,mBAAmB;AACnB,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,2BAA2B;AAC3B,MAAM,WAAW,MAAM;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,6BAA6B;AAC7B,MAAM,WAAW,KAAK;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,oBAAoB;AACpB,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,EAAE,KAAK,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,4BAA4B;AAC5B,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,6BAA6B;AAC7B,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,YAAY,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,2BAA2B;AAC3B,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,uBAAuB;AACvB,MAAM,WAAW,eAAe;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,4BAA4B;AAC5B,MAAM,WAAW,QAAQ;IACvB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAClD,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC,kBAAkB,CAAC,CAAC,CAAC;CAC/E;AAED,uBAAuB;AACvB,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,wBAAwB,EAAE,MAAM,EAAE,CAAC;CACpC;AAED,sBAAsB;AACtB,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;IACjD,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE;QACT,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * AI module type definitions
3
+ * Adapted from tmp/ai/internal/types/types.ts
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/ai/types.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Concurrent file analyzer
3
+ */
4
+ import type { DiscoveredFile } from './file-discovery.js';
5
+ import type { FileAnalysisResult } from '../metrics/types.js';
6
+ import type { RuntimeConfig } from '../config/schema.js';
7
+ /**
8
+ * Analyze files concurrently with configurable parallelism
9
+ */
10
+ export declare function analyzeFilesConcurrently(files: DiscoveredFile[], config: RuntimeConfig, onProgress?: (current: number, total: number) => void): Promise<FileAnalysisResult[]>;
11
+ //# sourceMappingURL=concurrent-analyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"concurrent-analyzer.d.ts","sourceRoot":"","sources":["../../src/analyzer/concurrent-analyzer.ts"],"names":[],"mappings":"AAAA;;GAEG;AASH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAKzD;;GAEG;AACH,wBAAsB,wBAAwB,CAC5C,KAAK,EAAE,cAAc,EAAE,EACvB,MAAM,EAAE,aAAa,EACrB,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,GACpD,OAAO,CAAC,kBAAkB,EAAE,CAAC,CA0B/B"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Concurrent file analyzer
3
+ */
4
+ import pLimit from 'p-limit';
5
+ import { readFileContent, getFileSize } from '../utils/fs.js';
6
+ import { createParser } from '../parser/index.js';
7
+ import { createMetrics } from '../metrics/index.js';
8
+ import { calculateScore } from '../scoring/index.js';
9
+ import { t } from '../i18n/index.js';
10
+ import { logger } from '../utils/logger.js';
11
+ const MAX_FILE_SIZE_KB = 500;
12
+ /**
13
+ * Analyze files concurrently with configurable parallelism
14
+ */
15
+ export async function analyzeFilesConcurrently(files, config, onProgress) {
16
+ const concurrency = config.concurrency || 8;
17
+ const limit = pLimit(concurrency);
18
+ const metrics = createMetrics(config);
19
+ let completed = 0;
20
+ const total = files.length;
21
+ const tasks = files.map((file) => limit(async () => {
22
+ try {
23
+ const result = await analyzeFile(file, metrics, config);
24
+ completed++;
25
+ onProgress?.(completed, total);
26
+ return result;
27
+ }
28
+ catch (error) {
29
+ logger.warn(t('warn_analyze_failed', { file: file.relativePath, error: String(error) }));
30
+ completed++;
31
+ onProgress?.(completed, total);
32
+ return null;
33
+ }
34
+ }));
35
+ const results = await Promise.all(tasks);
36
+ return results.filter((r) => r !== null);
37
+ }
38
+ /**
39
+ * Analyze a single file
40
+ */
41
+ async function analyzeFile(file, metrics, config) {
42
+ // Check file size
43
+ const fileSize = await getFileSize(file.absolutePath);
44
+ const fileSizeKB = Math.round(fileSize / 1024);
45
+ if (fileSizeKB > MAX_FILE_SIZE_KB) {
46
+ logger.warn(t('warn_file_too_large', { size: fileSizeKB, file: file.relativePath }));
47
+ return null;
48
+ }
49
+ // Read file content
50
+ const content = await readFileContent(file.absolutePath);
51
+ // Parse file
52
+ const parser = createParser(file.language);
53
+ const parseResult = await parser.parse(file.absolutePath, content);
54
+ // Add content to parse result for metrics that need it
55
+ parseResult.content = content;
56
+ // Calculate metrics
57
+ const metricResults = metrics.map((metric) => metric.calculate(parseResult));
58
+ // Calculate overall score
59
+ const score = calculateScore(metricResults, config);
60
+ return {
61
+ filePath: file.relativePath,
62
+ parseResult,
63
+ metrics: metricResults,
64
+ score,
65
+ };
66
+ }
67
+ //# sourceMappingURL=concurrent-analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"concurrent-analyzer.js","sourceRoot":"","sources":["../../src/analyzer/concurrent-analyzer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * File discovery module
3
+ * Uses only .gitignore for file exclusion
4
+ */
5
+ import { type Language } from '../parser/types.js';
6
+ import type { RuntimeConfig } from '../config/schema.js';
7
+ /** Discovered file information */
8
+ export interface DiscoveredFile {
9
+ absolutePath: string;
10
+ relativePath: string;
11
+ language: Language;
12
+ }
13
+ /** File discovery result */
14
+ export interface FileDiscoveryResult {
15
+ files: DiscoveredFile[];
16
+ skippedCount: number;
17
+ totalScanned: number;
18
+ }
19
+ /**
20
+ * Discover all analyzable files in the project
21
+ */
22
+ export declare function discoverFiles(config: RuntimeConfig): Promise<FileDiscoveryResult>;
23
+ //# sourceMappingURL=file-discovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-discovery.d.ts","sourceRoot":"","sources":["../../src/analyzer/file-discovery.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,kCAAkC;AAClC,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED,4BAA4B;AAC5B,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,mBAAmB,CAAC,CA4DvF"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * File discovery module
3
+ * Uses only .gitignore for file exclusion
4
+ */
5
+ import { glob } from 'glob';
6
+ import { join } from 'node:path';
7
+ import { loadGitignore, loadNestedGitignores, createMatcher } from '../gitignore/index.js';
8
+ import { detectLanguage } from '../parser/types.js';
9
+ /**
10
+ * Discover all analyzable files in the project
11
+ */
12
+ export async function discoverFiles(config) {
13
+ const { projectPath, include, exclude } = config;
14
+ const rootIgnore = await loadGitignore(projectPath);
15
+ // Add user-defined exclude patterns BEFORE creating matcher
16
+ for (const pattern of exclude) {
17
+ rootIgnore.add(pattern);
18
+ }
19
+ const nestedIgnores = await loadNestedGitignores(projectPath);
20
+ const matcher = createMatcher(rootIgnore, nestedIgnores);
21
+ // Common non-code directories to skip at glob level for performance
22
+ const globIgnore = [
23
+ '.git/**',
24
+ 'node_modules/**',
25
+ 'vendor/**',
26
+ 'dist/**',
27
+ 'build/**',
28
+ '.next/**',
29
+ '__pycache__/**',
30
+ 'target/**',
31
+ '.venv/**',
32
+ 'venv/**',
33
+ ];
34
+ const allFiles = [];
35
+ for (const pattern of include) {
36
+ const matches = await glob(pattern, {
37
+ cwd: projectPath,
38
+ nodir: true,
39
+ dot: true,
40
+ ignore: globIgnore,
41
+ });
42
+ allFiles.push(...matches);
43
+ }
44
+ const uniqueFiles = [...new Set(allFiles)];
45
+ const totalScanned = uniqueFiles.length;
46
+ const filteredFiles = matcher.filter(uniqueFiles);
47
+ const supportedFiles = [];
48
+ for (const relativePath of filteredFiles) {
49
+ const language = detectLanguage(relativePath);
50
+ if (language !== 'unknown') {
51
+ supportedFiles.push({
52
+ absolutePath: join(projectPath, relativePath),
53
+ relativePath,
54
+ language,
55
+ });
56
+ }
57
+ }
58
+ return {
59
+ files: supportedFiles,
60
+ skippedCount: totalScanned - supportedFiles.length,
61
+ totalScanned,
62
+ };
63
+ }
64
+ //# sourceMappingURL=file-discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-discovery.js","sourceRoot":"","sources":["../../src/analyzer/file-discovery.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3F,OAAO,EAAE,cAAc,EAAiB,MAAM,oBAAoB,CAAC;AAiBnE;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAAqB;IACvD,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;IAEjD,MAAM,UAAU,GAAG,MAAM,aAAa,CAAC,WAAW,CAAC,CAAC;IAEpD,4DAA4D;IAC5D,KAAK,MAAM,OAAO,IAAI,OAAO,EAAE,CAAC;QAC9B,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC1B,CAAC;IAED,MAAM,aAAa,GAAG,MAAM,oBAAoB,CAAC,WAAW,CAAC,CAAC;IAC9D,MAAM,OAAO,GAAG,aAAa,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;IAEzD,oEAAoE;IACpE,MAAM,UAAU,GAAG;QACjB,SAAS;QACT,iBAAiB;QACjB,WAAW;QACX,SAAS;QACT,UAAU;QACV,UAAU;QACV,gBAAgB;QAChB,WAAW;QACX,UAAU;QACV,SAAS;KACV,CAAC;IAEF,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,KAAK,MAAM,OAAO,IAAI,OAAO,EAAE,CAAC;QAC9B,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE;YAClC,GAAG,EAAE,WAAW;YAChB,KAAK,EAAE,IAAI;YACX,GAAG,EAAE,IAAI;YACT,MAAM,EAAE,UAAU;SACnB,CAAC,CAAC;QACH,QAAQ,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC;IAC5B,CAAC;IAED,MAAM,WAAW,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC3C,MAAM,YAAY,GAAG,WAAW,CAAC,MAAM,CAAC;IAExC,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAElD,MAAM,cAAc,GAAqB,EAAE,CAAC;IAC5C,KAAK,MAAM,YAAY,IAAI,aAAa,EAAE,CAAC;QACzC,MAAM,QAAQ,GAAG,cAAc,CAAC,YAAY,CAAC,CAAC;QAC9C,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,cAAc,CAAC,IAAI,CAAC;gBAClB,YAAY,EAAE,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC;gBAC7C,YAAY;gBACZ,QAAQ;aACT,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO;QACL,KAAK,EAAE,cAAc;QACrB,YAAY,EAAE,YAAY,GAAG,cAAc,CAAC,MAAM;QAClD,YAAY;KACb,CAAC;AACJ,CAAC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Main analyzer module
3
+ */
4
+ import type { RuntimeConfig } from '../config/schema.js';
5
+ import type { ProjectAnalysisResult } from '../metrics/types.js';
6
+ export interface AnalyzerCallbacks {
7
+ onDiscoveryStart?: () => void;
8
+ onDiscoveryComplete?: (fileCount: number) => void;
9
+ onAnalysisProgress?: (current: number, total: number) => void;
10
+ }
11
+ /**
12
+ * Analyzer class for code quality analysis
13
+ */
14
+ export declare class Analyzer {
15
+ private config;
16
+ private callbacks?;
17
+ constructor(config: RuntimeConfig, callbacks?: AnalyzerCallbacks);
18
+ /**
19
+ * Execute analysis on the project
20
+ */
21
+ analyze(): Promise<ProjectAnalysisResult>;
22
+ }
23
+ /**
24
+ * Create an analyzer instance
25
+ */
26
+ export declare function createAnalyzer(config: RuntimeConfig, callbacks?: AnalyzerCallbacks): Analyzer;
27
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/analyzer/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAEjE,MAAM,WAAW,iBAAiB;IAChC,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,mBAAmB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/D;AAED;;GAEG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,SAAS,CAAC,CAAoB;gBAE1B,MAAM,EAAE,aAAa,EAAE,SAAS,CAAC,EAAE,iBAAiB;IAKhE;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,qBAAqB,CAAC;CAgDhD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,EAAE,SAAS,CAAC,EAAE,iBAAiB,GAAG,QAAQ,CAE7F"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Main analyzer module
3
+ */
4
+ import { discoverFiles } from './file-discovery.js';
5
+ import { analyzeFilesConcurrently } from './concurrent-analyzer.js';
6
+ import { aggregateMetrics } from '../scoring/index.js';
7
+ /**
8
+ * Analyzer class for code quality analysis
9
+ */
10
+ export class Analyzer {
11
+ config;
12
+ callbacks;
13
+ constructor(config, callbacks) {
14
+ this.config = config;
15
+ this.callbacks = callbacks;
16
+ }
17
+ /**
18
+ * Execute analysis on the project
19
+ */
20
+ async analyze() {
21
+ const startTime = Date.now();
22
+ // Discover files
23
+ this.callbacks?.onDiscoveryStart?.();
24
+ const discovery = await discoverFiles(this.config);
25
+ this.callbacks?.onDiscoveryComplete?.(discovery.files.length);
26
+ if (discovery.files.length === 0) {
27
+ return {
28
+ projectPath: this.config.projectPath,
29
+ totalFiles: discovery.totalScanned,
30
+ analyzedFiles: 0,
31
+ skippedFiles: discovery.skippedCount,
32
+ fileResults: [],
33
+ aggregatedMetrics: [],
34
+ overallScore: 100,
35
+ analysisTime: Date.now() - startTime,
36
+ };
37
+ }
38
+ // Analyze files concurrently
39
+ const fileResults = await analyzeFilesConcurrently(discovery.files, this.config, this.callbacks?.onAnalysisProgress);
40
+ // Aggregate metrics
41
+ const aggregatedMetrics = aggregateMetrics(fileResults, this.config);
42
+ // Calculate overall score
43
+ const overallScore = fileResults.length > 0
44
+ ? fileResults.reduce((sum, r) => sum + r.score, 0) / fileResults.length
45
+ : 100;
46
+ return {
47
+ projectPath: this.config.projectPath,
48
+ totalFiles: discovery.totalScanned,
49
+ analyzedFiles: fileResults.length,
50
+ skippedFiles: discovery.skippedCount,
51
+ fileResults,
52
+ aggregatedMetrics,
53
+ overallScore,
54
+ analysisTime: Date.now() - startTime,
55
+ };
56
+ }
57
+ }
58
+ /**
59
+ * Create an analyzer instance
60
+ */
61
+ export function createAnalyzer(config, callbacks) {
62
+ return new Analyzer(config, callbacks);
63
+ }
64
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/analyzer/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAUvD;;GAEG;AACH,MAAM,OAAO,QAAQ;IACX,MAAM,CAAgB;IACtB,SAAS,CAAqB;IAEtC,YAAY,MAAqB,EAAE,SAA6B;QAC9D,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO;QACX,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE7B,iBAAiB;QACjB,IAAI,CAAC,SAAS,EAAE,gBAAgB,EAAE,EAAE,CAAC;QACrC,MAAM,SAAS,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACnD,IAAI,CAAC,SAAS,EAAE,mBAAmB,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAE9D,IAAI,SAAS,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACjC,OAAO;gBACL,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW;gBACpC,UAAU,EAAE,SAAS,CAAC,YAAY;gBAClC,aAAa,EAAE,CAAC;gBAChB,YAAY,EAAE,SAAS,CAAC,YAAY;gBACpC,WAAW,EAAE,EAAE;gBACf,iBAAiB,EAAE,EAAE;gBACrB,YAAY,EAAE,GAAG;gBACjB,YAAY,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;aACrC,CAAC;QACJ,CAAC;QAED,6BAA6B;QAC7B,MAAM,WAAW,GAAG,MAAM,wBAAwB,CAChD,SAAS,CAAC,KAAK,EACf,IAAI,CAAC,MAAM,EACX,IAAI,CAAC,SAAS,EAAE,kBAAkB,CACnC,CAAC;QAEF,oBAAoB;QACpB,MAAM,iBAAiB,GAAG,gBAAgB,CAAC,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAErE,0BAA0B;QAC1B,MAAM,YAAY,GAChB,WAAW,CAAC,MAAM,GAAG,CAAC;YACpB,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,GAAG,WAAW,CAAC,MAAM;YACvE,CAAC,CAAC,GAAG,CAAC;QAEV,OAAO;YACL,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW;YACpC,UAAU,EAAE,SAAS,CAAC,YAAY;YAClC,aAAa,EAAE,WAAW,CAAC,MAAM;YACjC,YAAY,EAAE,SAAS,CAAC,YAAY;YACpC,WAAW;YACX,iBAAiB;YACjB,YAAY;YACZ,YAAY,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;SACrC,CAAC;IACJ,CAAC;CACF;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,MAAqB,EAAE,SAA6B;IACjF,OAAO,IAAI,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AACzC,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * AI review command implementation
3
+ */
4
+ import { Command } from 'commander';
5
+ export declare function createAIReviewCommand(): Command;
6
+ //# sourceMappingURL=ai-review.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-review.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/ai-review.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA6BpC,wBAAgB,qBAAqB,IAAI,OAAO,CAyC/C"}
@@ -0,0 +1,213 @@
1
+ /**
2
+ * AI review command implementation
3
+ */
4
+ import { Command } from 'commander';
5
+ import { resolve } from 'node:path';
6
+ import { loadConfig, createRuntimeConfig, loadAIConfig } from '../../config/index.js';
7
+ import { createAnalyzer } from '../../analyzer/index.js';
8
+ import { createAIManager } from '../../ai/index.js';
9
+ import { createSpinner } from '../../utils/progress.js';
10
+ import { exists, isDirectory } from '../../utils/fs.js';
11
+ import { t } from '../../i18n/index.js';
12
+ import { renderMarkdownToTerminal } from '../../utils/markdown.js';
13
+ import { renderAIReviewMarkdown, renderAIReviewHtml, } from '../output/ai-review-output.js';
14
+ import { getTerminalWidth } from '../../utils/terminal.js';
15
+ import chalk from 'chalk';
16
+ export function createAIReviewCommand() {
17
+ const command = new Command('ai-review');
18
+ command
19
+ .description(t('cmd_ai_review_description'))
20
+ .argument('[path]', 'Project path to review', '.')
21
+ .option('-p, --provider <provider>', 'AI provider: openai, anthropic, deepseek, gemini, ollama')
22
+ .option('-m, --model <model>', 'Model to use (required)')
23
+ .option('-b, --base-url <url>', 'Custom API base URL (for OpenAI-compatible APIs)')
24
+ .option('-k, --api-key <key>', 'API key (can also use environment variables)')
25
+ .option('-t, --top <number>', 'Number of worst files to review (default: 5)', parseInt)
26
+ .option('-v, --verbose', 'Show verbose output')
27
+ .option('-l, --locale <locale>', 'Language: en, zh, ru')
28
+ .option('-f, --format <format>', t('cmd_ai_review_format_help'))
29
+ .option('-o, --output <file>', 'Write output to file instead of stdout')
30
+ .addHelpText('after', `
31
+ ${t('cli_examples')}
32
+ $ fuck-u-code ai-review . --model gpt-4o --api-key sk-xxx
33
+ $ fuck-u-code ai-review . --model claude-3-opus --provider anthropic
34
+ $ fuck-u-code ai-review . --model deepseek-chat --provider deepseek
35
+ $ fuck-u-code ai-review . --model gemini-2.5-flash --provider gemini
36
+ $ fuck-u-code ai-review . --model llama3 --provider ollama
37
+ $ fuck-u-code ai-review . --model gpt-4o --top 3
38
+
39
+ ${t('cmd_ai_review_env_header')}
40
+ OPENAI_API_KEY OpenAI-compatible API key
41
+ OPENAI_MODEL Default model for OpenAI-compatible provider
42
+ OPENAI_BASE_URL Custom API endpoint (for any OpenAI-compatible service)
43
+ ANTHROPIC_API_KEY Anthropic API key
44
+ DEEPSEEK_API_KEY DeepSeek API key
45
+ GEMINI_API_KEY Google Gemini API key
46
+ OLLAMA_HOST Ollama server URL (e.g., http://localhost:11434)
47
+ `)
48
+ .action(async (path, options) => {
49
+ await runAIReview(path, options);
50
+ });
51
+ return command;
52
+ }
53
+ async function runAIReview(projectPath, options) {
54
+ const resolvedPath = resolve(projectPath);
55
+ // Validate path
56
+ if (!(await exists(resolvedPath))) {
57
+ console.error(chalk.red(t('error_path_not_found', { path: resolvedPath })));
58
+ process.exit(1);
59
+ }
60
+ if (!(await isDirectory(resolvedPath))) {
61
+ console.error(chalk.red(t('error_not_a_directory', { path: resolvedPath })));
62
+ process.exit(1);
63
+ }
64
+ const config = await loadConfig(resolvedPath);
65
+ let aiConfig = loadAIConfig(config.ai, options.model);
66
+ if (options.baseUrl || options.apiKey || options.provider) {
67
+ const provider = options.provider || 'openai';
68
+ const apiKey = options.apiKey || process.env[`${provider.toUpperCase()}_API_KEY`];
69
+ if (!apiKey && provider !== 'ollama') {
70
+ console.error(chalk.red(t('ai_api_key_required')));
71
+ process.exit(1);
72
+ }
73
+ if (!options.model) {
74
+ console.error(chalk.red(t('ai_model_required')));
75
+ process.exit(1);
76
+ }
77
+ // When user explicitly specifies provider, use only that provider
78
+ aiConfig = {
79
+ providers: {
80
+ [provider]: {
81
+ enabled: true,
82
+ instances: [
83
+ {
84
+ name: 'cli',
85
+ enabled: true,
86
+ baseUrl: options.baseUrl || getDefaultBaseUrl(provider),
87
+ apiKey: apiKey || '',
88
+ models: [options.model],
89
+ maxTokens: 4096,
90
+ temperature: 0.7,
91
+ topP: 1,
92
+ timeout: 60,
93
+ maxRetries: 3,
94
+ },
95
+ ],
96
+ },
97
+ },
98
+ defaultProvider: provider,
99
+ };
100
+ }
101
+ if (Object.keys(aiConfig.providers).length === 0) {
102
+ console.error(chalk.red(t('noAIProvider')));
103
+ console.log(chalk.yellow(t('aiProviderHint')));
104
+ console.log(chalk.gray(`\n${t('ai_example_usage')}`));
105
+ console.log(chalk.gray(' fuck-u-code ai-review . --model gpt-4o --api-key sk-xxx'));
106
+ console.log(chalk.gray(' fuck-u-code ai-review . --model gemini-2.5-flash --provider gemini --api-key xxx'));
107
+ console.log(chalk.gray(`\n${t('ai_or_set_env')}`));
108
+ console.log(chalk.gray(' export OPENAI_API_KEY=sk-xxx'));
109
+ console.log(chalk.gray(' export OPENAI_MODEL=gpt-4o'));
110
+ process.exit(1);
111
+ }
112
+ const spinner = createSpinner(t('analyzing'));
113
+ spinner.start();
114
+ try {
115
+ const runtimeConfig = createRuntimeConfig(resolvedPath, config, {
116
+ verbose: options.verbose,
117
+ ai: {
118
+ enabled: true,
119
+ provider: options.provider,
120
+ model: options.model,
121
+ },
122
+ });
123
+ const analyzer = createAnalyzer(runtimeConfig);
124
+ const analysisResult = await analyzer.analyze();
125
+ const topCount = options.top ?? 5;
126
+ const worstFiles = analysisResult.fileResults
127
+ .sort((a, b) => a.score - b.score)
128
+ .slice(0, topCount);
129
+ if (worstFiles.length === 0) {
130
+ spinner.succeed(t('report_no_issues'));
131
+ return;
132
+ }
133
+ spinner.text = t('aiReviewing');
134
+ const aiManager = createAIManager(aiConfig);
135
+ const reviews = [];
136
+ for (const [i, file] of worstFiles.entries()) {
137
+ spinner.text = `${t('reviewingFile', { file: file.filePath })} [${i + 1}/${worstFiles.length}]`;
138
+ const review = await aiManager.reviewCode(file);
139
+ reviews.push({
140
+ filePath: file.filePath,
141
+ score: 100 - file.score,
142
+ review,
143
+ });
144
+ }
145
+ spinner.succeed(t('aiReviewComplete'));
146
+ const format = options.format ?? 'console';
147
+ const outputFile = options.output;
148
+ switch (format) {
149
+ case 'markdown': {
150
+ const markdown = renderAIReviewMarkdown(reviews);
151
+ if (outputFile) {
152
+ const { writeFile } = await import('node:fs/promises');
153
+ await writeFile(outputFile, markdown, 'utf-8');
154
+ console.log(t('outputWritten', { file: outputFile }));
155
+ }
156
+ else {
157
+ console.log(renderMarkdownToTerminal(markdown));
158
+ }
159
+ break;
160
+ }
161
+ case 'html': {
162
+ const html = renderAIReviewHtml(reviews);
163
+ if (outputFile) {
164
+ const { writeFile } = await import('node:fs/promises');
165
+ await writeFile(outputFile, html, 'utf-8');
166
+ console.log(t('outputWritten', { file: outputFile }));
167
+ }
168
+ else {
169
+ console.log(chalk.yellow(t('output_html_requires_file')));
170
+ renderConsoleReviews(reviews);
171
+ }
172
+ break;
173
+ }
174
+ default: {
175
+ renderConsoleReviews(reviews);
176
+ }
177
+ }
178
+ }
179
+ catch (error) {
180
+ spinner.fail(t('aiReviewFailed'));
181
+ console.error(chalk.red(error instanceof Error ? error.message : String(error)));
182
+ process.exit(1);
183
+ }
184
+ }
185
+ /** Render AI review results to the terminal with chalk styling */
186
+ function renderConsoleReviews(reviews) {
187
+ const termWidth = getTerminalWidth();
188
+ const reviewIndent = 3;
189
+ const contentWidth = termWidth - reviewIndent;
190
+ const indentStr = ' '.repeat(reviewIndent);
191
+ console.log('\n' + chalk.bold.yellow(`🌸 ${t('ai_review_title')} 🌸`));
192
+ console.log(indentStr + chalk.gray('─'.repeat(contentWidth)));
193
+ for (const [i, { filePath, score, review }] of reviews.entries()) {
194
+ console.log();
195
+ console.log(chalk.bold.magenta(`${i + 1}. ${filePath}`));
196
+ console.log(chalk.cyan(` ${t('report_file_score', { score: score.toFixed(1) })}`));
197
+ console.log();
198
+ console.log(renderMarkdownToTerminal(review, reviewIndent));
199
+ console.log(indentStr + chalk.gray('─'.repeat(contentWidth)));
200
+ }
201
+ }
202
+ /** Get default base URL for a provider */
203
+ function getDefaultBaseUrl(provider) {
204
+ const urls = {
205
+ openai: 'https://api.openai.com/v1',
206
+ anthropic: 'https://api.anthropic.com',
207
+ deepseek: 'https://api.deepseek.com/v1',
208
+ gemini: 'https://generativelanguage.googleapis.com',
209
+ ollama: 'http://localhost:11434',
210
+ };
211
+ return urls[provider] ?? `https://api.${provider}.com/v1`;
212
+ }
213
+ //# sourceMappingURL=ai-review.js.map