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.
- package/LICENSE +21 -0
- package/README.md +256 -0
- package/bin/fuck-u-code-mcp.js +2 -0
- package/bin/fuck-u-code.js +2 -0
- package/bin/postinstall.js +53 -0
- package/dist/ai/index.d.ts +34 -0
- package/dist/ai/index.d.ts.map +1 -0
- package/dist/ai/index.js +227 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/ai/prompts/code-review.d.ts +9 -0
- package/dist/ai/prompts/code-review.d.ts.map +1 -0
- package/dist/ai/prompts/code-review.js +61 -0
- package/dist/ai/prompts/code-review.js.map +1 -0
- package/dist/ai/providers/anthropic.d.ts +11 -0
- package/dist/ai/providers/anthropic.d.ts.map +1 -0
- package/dist/ai/providers/anthropic.js +60 -0
- package/dist/ai/providers/anthropic.js.map +1 -0
- package/dist/ai/providers/fetch.d.ts +10 -0
- package/dist/ai/providers/fetch.d.ts.map +1 -0
- package/dist/ai/providers/fetch.js +50 -0
- package/dist/ai/providers/fetch.js.map +1 -0
- package/dist/ai/providers/gemini.d.ts +12 -0
- package/dist/ai/providers/gemini.d.ts.map +1 -0
- package/dist/ai/providers/gemini.js +66 -0
- package/dist/ai/providers/gemini.js.map +1 -0
- package/dist/ai/providers/ollama.d.ts +11 -0
- package/dist/ai/providers/ollama.d.ts.map +1 -0
- package/dist/ai/providers/ollama.js +54 -0
- package/dist/ai/providers/ollama.js.map +1 -0
- package/dist/ai/providers/openai.d.ts +11 -0
- package/dist/ai/providers/openai.d.ts.map +1 -0
- package/dist/ai/providers/openai.js +52 -0
- package/dist/ai/providers/openai.js.map +1 -0
- package/dist/ai/selector.d.ts +19 -0
- package/dist/ai/selector.d.ts.map +1 -0
- package/dist/ai/selector.js +145 -0
- package/dist/ai/selector.js.map +1 -0
- package/dist/ai/types.d.ts +120 -0
- package/dist/ai/types.d.ts.map +1 -0
- package/dist/ai/types.js +6 -0
- package/dist/ai/types.js.map +1 -0
- package/dist/analyzer/concurrent-analyzer.d.ts +11 -0
- package/dist/analyzer/concurrent-analyzer.d.ts.map +1 -0
- package/dist/analyzer/concurrent-analyzer.js +67 -0
- package/dist/analyzer/concurrent-analyzer.js.map +1 -0
- package/dist/analyzer/file-discovery.d.ts +23 -0
- package/dist/analyzer/file-discovery.d.ts.map +1 -0
- package/dist/analyzer/file-discovery.js +64 -0
- package/dist/analyzer/file-discovery.js.map +1 -0
- package/dist/analyzer/index.d.ts +27 -0
- package/dist/analyzer/index.d.ts.map +1 -0
- package/dist/analyzer/index.js +64 -0
- package/dist/analyzer/index.js.map +1 -0
- package/dist/cli/commands/ai-review.d.ts +6 -0
- package/dist/cli/commands/ai-review.d.ts.map +1 -0
- package/dist/cli/commands/ai-review.js +213 -0
- package/dist/cli/commands/ai-review.js.map +1 -0
- package/dist/cli/commands/analyze.d.ts +6 -0
- package/dist/cli/commands/analyze.d.ts.map +1 -0
- package/dist/cli/commands/analyze.js +145 -0
- package/dist/cli/commands/analyze.js.map +1 -0
- package/dist/cli/commands/config.d.ts +6 -0
- package/dist/cli/commands/config.d.ts.map +1 -0
- package/dist/cli/commands/config.js +147 -0
- package/dist/cli/commands/config.js.map +1 -0
- package/dist/cli/commands/mcp-install.d.ts +9 -0
- package/dist/cli/commands/mcp-install.d.ts.map +1 -0
- package/dist/cli/commands/mcp-install.js +102 -0
- package/dist/cli/commands/mcp-install.js.map +1 -0
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +69 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/output/ai-review-output.d.ts +20 -0
- package/dist/cli/output/ai-review-output.d.ts.map +1 -0
- package/dist/cli/output/ai-review-output.js +324 -0
- package/dist/cli/output/ai-review-output.js.map +1 -0
- package/dist/cli/output/console.d.ts +31 -0
- package/dist/cli/output/console.d.ts.map +1 -0
- package/dist/cli/output/console.js +571 -0
- package/dist/cli/output/console.js.map +1 -0
- package/dist/cli/output/html.d.ts +20 -0
- package/dist/cli/output/html.d.ts.map +1 -0
- package/dist/cli/output/html.js +339 -0
- package/dist/cli/output/html.js.map +1 -0
- package/dist/cli/output/json.d.ts +8 -0
- package/dist/cli/output/json.d.ts.map +1 -0
- package/dist/cli/output/json.js +46 -0
- package/dist/cli/output/json.js.map +1 -0
- package/dist/cli/output/markdown.d.ts +17 -0
- package/dist/cli/output/markdown.d.ts.map +1 -0
- package/dist/cli/output/markdown.js +323 -0
- package/dist/cli/output/markdown.js.map +1 -0
- package/dist/cli/output/stats.d.ts +35 -0
- package/dist/cli/output/stats.d.ts.map +1 -0
- package/dist/cli/output/stats.js +63 -0
- package/dist/cli/output/stats.js.map +1 -0
- package/dist/cli/output/terminal-markdown.d.ts +23 -0
- package/dist/cli/output/terminal-markdown.d.ts.map +1 -0
- package/dist/cli/output/terminal-markdown.js +159 -0
- package/dist/cli/output/terminal-markdown.js.map +1 -0
- package/dist/config/index.d.ts +27 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +266 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/schema.d.ts +179 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +85 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/gitignore/index.d.ts +5 -0
- package/dist/gitignore/index.d.ts.map +1 -0
- package/dist/gitignore/index.js +5 -0
- package/dist/gitignore/index.js.map +1 -0
- package/dist/gitignore/parser.d.ts +32 -0
- package/dist/gitignore/parser.d.ts.map +1 -0
- package/dist/gitignore/parser.js +110 -0
- package/dist/gitignore/parser.js.map +1 -0
- package/dist/gitignore/parser.test.d.ts +2 -0
- package/dist/gitignore/parser.test.d.ts.map +1 -0
- package/dist/gitignore/parser.test.js +217 -0
- package/dist/gitignore/parser.test.js.map +1 -0
- package/dist/i18n/index.d.ts +19 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/index.js +43 -0
- package/dist/i18n/index.js.map +1 -0
- package/dist/i18n/locales/en.json +320 -0
- package/dist/i18n/locales/ru.json +320 -0
- package/dist/i18n/locales/zh.json +320 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/server.d.ts +9 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +156 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/metrics/complexity/cognitive.d.ts +25 -0
- package/dist/metrics/complexity/cognitive.d.ts.map +1 -0
- package/dist/metrics/complexity/cognitive.js +109 -0
- package/dist/metrics/complexity/cognitive.js.map +1 -0
- package/dist/metrics/complexity/cyclomatic.d.ts +21 -0
- package/dist/metrics/complexity/cyclomatic.d.ts.map +1 -0
- package/dist/metrics/complexity/cyclomatic.js +111 -0
- package/dist/metrics/complexity/cyclomatic.js.map +1 -0
- package/dist/metrics/complexity/nesting-depth.d.ts +19 -0
- package/dist/metrics/complexity/nesting-depth.d.ts.map +1 -0
- package/dist/metrics/complexity/nesting-depth.js +97 -0
- package/dist/metrics/complexity/nesting-depth.js.map +1 -0
- package/dist/metrics/documentation/comment-ratio.d.ts +21 -0
- package/dist/metrics/documentation/comment-ratio.d.ts.map +1 -0
- package/dist/metrics/documentation/comment-ratio.js +91 -0
- package/dist/metrics/documentation/comment-ratio.js.map +1 -0
- package/dist/metrics/duplication/code-duplication.d.ts +24 -0
- package/dist/metrics/duplication/code-duplication.d.ts.map +1 -0
- package/dist/metrics/duplication/code-duplication.js +167 -0
- package/dist/metrics/duplication/code-duplication.js.map +1 -0
- package/dist/metrics/duplication/code-duplication.test.d.ts +2 -0
- package/dist/metrics/duplication/code-duplication.test.d.ts.map +1 -0
- package/dist/metrics/duplication/code-duplication.test.js +612 -0
- package/dist/metrics/duplication/code-duplication.test.js.map +1 -0
- package/dist/metrics/error/error-handling.d.ts +23 -0
- package/dist/metrics/error/error-handling.d.ts.map +1 -0
- package/dist/metrics/error/error-handling.js +164 -0
- package/dist/metrics/error/error-handling.js.map +1 -0
- package/dist/metrics/error/error-handling.test.d.ts +2 -0
- package/dist/metrics/error/error-handling.test.d.ts.map +1 -0
- package/dist/metrics/error/error-handling.test.js +349 -0
- package/dist/metrics/error/error-handling.test.js.map +1 -0
- package/dist/metrics/index.d.ts +21 -0
- package/dist/metrics/index.d.ts.map +1 -0
- package/dist/metrics/index.js +50 -0
- package/dist/metrics/index.js.map +1 -0
- package/dist/metrics/naming/convention.d.ts +22 -0
- package/dist/metrics/naming/convention.d.ts.map +1 -0
- package/dist/metrics/naming/convention.js +117 -0
- package/dist/metrics/naming/convention.js.map +1 -0
- package/dist/metrics/size/file-length.d.ts +19 -0
- package/dist/metrics/size/file-length.d.ts.map +1 -0
- package/dist/metrics/size/file-length.js +68 -0
- package/dist/metrics/size/file-length.js.map +1 -0
- package/dist/metrics/size/function-length.d.ts +20 -0
- package/dist/metrics/size/function-length.d.ts.map +1 -0
- package/dist/metrics/size/function-length.js +101 -0
- package/dist/metrics/size/function-length.js.map +1 -0
- package/dist/metrics/size/parameter-count.d.ts +19 -0
- package/dist/metrics/size/parameter-count.d.ts.map +1 -0
- package/dist/metrics/size/parameter-count.js +97 -0
- package/dist/metrics/size/parameter-count.js.map +1 -0
- package/dist/metrics/structure/structure-analysis.d.ts +24 -0
- package/dist/metrics/structure/structure-analysis.d.ts.map +1 -0
- package/dist/metrics/structure/structure-analysis.js +223 -0
- package/dist/metrics/structure/structure-analysis.js.map +1 -0
- package/dist/metrics/structure/structure-analysis.test.d.ts +2 -0
- package/dist/metrics/structure/structure-analysis.test.d.ts.map +1 -0
- package/dist/metrics/structure/structure-analysis.test.js +342 -0
- package/dist/metrics/structure/structure-analysis.test.js.map +1 -0
- package/dist/metrics/types.d.ts +71 -0
- package/dist/metrics/types.d.ts.map +1 -0
- package/dist/metrics/types.js +5 -0
- package/dist/metrics/types.js.map +1 -0
- package/dist/parser/generic-parser.d.ts +28 -0
- package/dist/parser/generic-parser.d.ts.map +1 -0
- package/dist/parser/generic-parser.js +218 -0
- package/dist/parser/generic-parser.js.map +1 -0
- package/dist/parser/index.d.ts +19 -0
- package/dist/parser/index.d.ts.map +1 -0
- package/dist/parser/index.js +52 -0
- package/dist/parser/index.js.map +1 -0
- package/dist/parser/regex-parser.d.ts +46 -0
- package/dist/parser/regex-parser.d.ts.map +1 -0
- package/dist/parser/regex-parser.js +560 -0
- package/dist/parser/regex-parser.js.map +1 -0
- package/dist/parser/tree-sitter-parser.d.ts +50 -0
- package/dist/parser/tree-sitter-parser.d.ts.map +1 -0
- package/dist/parser/tree-sitter-parser.js +707 -0
- package/dist/parser/tree-sitter-parser.js.map +1 -0
- package/dist/parser/types.d.ts +52 -0
- package/dist/parser/types.d.ts.map +1 -0
- package/dist/parser/types.js +49 -0
- package/dist/parser/types.js.map +1 -0
- package/dist/scoring/index.d.ts +14 -0
- package/dist/scoring/index.d.ts.map +1 -0
- package/dist/scoring/index.js +80 -0
- package/dist/scoring/index.js.map +1 -0
- package/dist/utils/fs.d.ts +24 -0
- package/dist/utils/fs.d.ts.map +1 -0
- package/dist/utils/fs.js +61 -0
- package/dist/utils/fs.js.map +1 -0
- package/dist/utils/logger.d.ts +13 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +43 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/markdown.d.ts +16 -0
- package/dist/utils/markdown.d.ts.map +1 -0
- package/dist/utils/markdown.js +303 -0
- package/dist/utils/markdown.js.map +1 -0
- package/dist/utils/progress.d.ts +24 -0
- package/dist/utils/progress.d.ts.map +1 -0
- package/dist/utils/progress.js +79 -0
- package/dist/utils/progress.js.map +1 -0
- package/dist/utils/terminal.d.ts +62 -0
- package/dist/utils/terminal.d.ts.map +1 -0
- package/dist/utils/terminal.js +207 -0
- package/dist/utils/terminal.js.map +1 -0
- 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":"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"}
|
package/dist/ai/types.js
ADDED
|
@@ -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 @@
|
|
|
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
|