@andrebuzeli/git-mcp 2.27.4 → 2.28.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 (112) hide show
  1. package/dist/client.d.ts +306 -306
  2. package/dist/client.js +298 -298
  3. package/dist/config.d.ts +310 -310
  4. package/dist/config.js +392 -392
  5. package/dist/index.d.ts +22 -22
  6. package/dist/index.js +89 -89
  7. package/dist/providers/base-provider.d.ts +160 -156
  8. package/dist/providers/base-provider.d.ts.map +1 -1
  9. package/dist/providers/base-provider.js +274 -260
  10. package/dist/providers/base-provider.js.map +1 -1
  11. package/dist/providers/error-handler.d.ts +50 -50
  12. package/dist/providers/error-handler.js +175 -175
  13. package/dist/providers/gitea-provider.d.ts +97 -97
  14. package/dist/providers/gitea-provider.js +1001 -1001
  15. package/dist/providers/github-provider.d.ts +104 -104
  16. package/dist/providers/github-provider.js +1234 -1234
  17. package/dist/providers/index.d.ts +12 -12
  18. package/dist/providers/index.js +40 -40
  19. package/dist/providers/provider-factory.d.ts +74 -74
  20. package/dist/providers/provider-factory.js +311 -311
  21. package/dist/providers/types.d.ts +318 -298
  22. package/dist/providers/types.d.ts.map +1 -1
  23. package/dist/providers/types.js +6 -6
  24. package/dist/server.d.ts +76 -76
  25. package/dist/server.d.ts.map +1 -1
  26. package/dist/server.js +306 -305
  27. package/dist/server.js.map +1 -1
  28. package/dist/tools/gh-actions.d.ts +252 -252
  29. package/dist/tools/gh-actions.js +389 -389
  30. package/dist/tools/gh-analytics.d.ts +263 -263
  31. package/dist/tools/gh-analytics.js +401 -401
  32. package/dist/tools/gh-code-review.d.ts +304 -304
  33. package/dist/tools/gh-code-review.js +512 -512
  34. package/dist/tools/gh-codespaces.d.ts +138 -138
  35. package/dist/tools/gh-codespaces.js +282 -282
  36. package/dist/tools/gh-deployments.d.ts +300 -300
  37. package/dist/tools/gh-deployments.js +367 -367
  38. package/dist/tools/gh-gists.d.ts +174 -174
  39. package/dist/tools/gh-gists.js +321 -321
  40. package/dist/tools/gh-projects.d.ts +205 -205
  41. package/dist/tools/gh-projects.js +358 -358
  42. package/dist/tools/gh-security.d.ts +274 -274
  43. package/dist/tools/gh-security.js +395 -395
  44. package/dist/tools/gh-sync.d.ts +213 -213
  45. package/dist/tools/gh-sync.js +378 -378
  46. package/dist/tools/gh-workflows.d.ts +290 -290
  47. package/dist/tools/gh-workflows.js +432 -432
  48. package/dist/tools/git-archive.d.ts +165 -165
  49. package/dist/tools/git-archive.js +233 -233
  50. package/dist/tools/git-branches.d.ts +430 -430
  51. package/dist/tools/git-branches.d.ts.map +1 -1
  52. package/dist/tools/git-branches.js +627 -530
  53. package/dist/tools/git-branches.js.map +1 -1
  54. package/dist/tools/git-bundle.d.ts +171 -171
  55. package/dist/tools/git-bundle.js +241 -241
  56. package/dist/tools/git-cherry-pick.d.ts +158 -158
  57. package/dist/tools/git-cherry-pick.js +224 -224
  58. package/dist/tools/git-commits.d.ts +485 -485
  59. package/dist/tools/git-commits.d.ts.map +1 -1
  60. package/dist/tools/git-commits.js +735 -625
  61. package/dist/tools/git-commits.js.map +1 -1
  62. package/dist/tools/git-config.d.ts +140 -140
  63. package/dist/tools/git-config.js +268 -268
  64. package/dist/tools/git-files.d.ts +486 -486
  65. package/dist/tools/git-files.js +607 -607
  66. package/dist/tools/git-issues.d.ts +571 -571
  67. package/dist/tools/git-issues.d.ts.map +1 -1
  68. package/dist/tools/git-issues.js +740 -693
  69. package/dist/tools/git-issues.js.map +1 -1
  70. package/dist/tools/git-pulls.d.ts +694 -694
  71. package/dist/tools/git-pulls.js +732 -732
  72. package/dist/tools/git-rebase.d.ts +137 -137
  73. package/dist/tools/git-rebase.js +213 -213
  74. package/dist/tools/git-releases.d.ts +487 -487
  75. package/dist/tools/git-releases.js +557 -557
  76. package/dist/tools/git-remote.d.ts +138 -138
  77. package/dist/tools/git-remote.js +274 -274
  78. package/dist/tools/git-repositories.d.ts +483 -483
  79. package/dist/tools/git-repositories.js +640 -640
  80. package/dist/tools/git-reset.d.ts +130 -130
  81. package/dist/tools/git-reset.js +223 -223
  82. package/dist/tools/git-revert.d.ts +149 -149
  83. package/dist/tools/git-revert.js +198 -198
  84. package/dist/tools/git-stash.d.ts +140 -140
  85. package/dist/tools/git-stash.js +269 -269
  86. package/dist/tools/git-submodule.d.ts +152 -152
  87. package/dist/tools/git-submodule.js +289 -289
  88. package/dist/tools/git-sync.d.ts +178 -166
  89. package/dist/tools/git-sync.d.ts.map +1 -1
  90. package/dist/tools/git-sync.js +312 -117
  91. package/dist/tools/git-sync.js.map +1 -1
  92. package/dist/tools/git-tags.d.ts +411 -411
  93. package/dist/tools/git-tags.js +485 -485
  94. package/dist/tools/git-webhooks.d.ts +470 -482
  95. package/dist/tools/git-webhooks.d.ts.map +1 -1
  96. package/dist/tools/git-webhooks.js +543 -555
  97. package/dist/tools/git-webhooks.js.map +1 -1
  98. package/dist/tools/git-worktree.d.ts +159 -159
  99. package/dist/tools/git-worktree.js +269 -269
  100. package/dist/tools/repositories.d.ts +405 -405
  101. package/dist/tools/repositories.js +569 -569
  102. package/dist/tools/users.d.ts +372 -372
  103. package/dist/tools/users.js +499 -499
  104. package/dist/tools/validator.d.ts +170 -170
  105. package/dist/tools/validator.js +194 -194
  106. package/dist/tools/version-control.d.ts +136 -136
  107. package/dist/tools/version-control.js +164 -164
  108. package/dist/utils/terminal-controller.d.ts +80 -80
  109. package/dist/utils/terminal-controller.js +345 -345
  110. package/dist/utils/user-detection.d.ts +24 -24
  111. package/dist/utils/user-detection.js +53 -53
  112. package/package.json +59 -59
@@ -1,513 +1,513 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.codeReviewTool = void 0;
4
- const zod_1 = require("zod");
5
- const index_js_1 = require("../providers/index.js");
6
- const user_detection_js_1 = require("../utils/user-detection.js");
7
- /**
8
- * Tool: code-review
9
- *
10
- * DESCRIÇÃO:
11
- * Ferramenta completa de revisão de código com análise automatizada,
12
- * sugestões de melhorias, detecção de problemas e geração de relatórios.
13
- *
14
- * FUNCIONALIDADES:
15
- * - Análise de qualidade de código
16
- * - Detecção de bugs e vulnerabilidades
17
- * - Sugestões de otimização
18
- * - Revisão de commits e arquivos
19
- * - Geração de relatórios de qualidade
20
- * - Aplicação automática de correções
21
- *
22
- * USO:
23
- * - Para revisão automatizada de pull requests
24
- * - Para análise de qualidade de código
25
- * - Para detecção de problemas de segurança
26
- * - Para sugestões de melhorias de performance
27
- *
28
- * RECOMENDAÇÕES:
29
- * - Execute regularmente em novos commits
30
- * - Configure regras específicas por linguagem
31
- * - Use em conjunto com CI/CD
32
- * - Revise sugestões antes de aplicar
33
- */
34
- /**
35
- * Schema de validação para entrada da tool code-review
36
- */
37
- const CodeReviewInputSchema = zod_1.z.object({
38
- action: zod_1.z.enum(['analyze', 'review-file', 'review-commit', 'review-pr', 'generate-report', 'apply-suggestions']),
39
- // Parâmetros comuns
40
- repo: zod_1.z.string(),
41
- // Para analyze
42
- code: zod_1.z.string().optional(),
43
- language: zod_1.z.string().optional(),
44
- file_path: zod_1.z.string().optional(),
45
- // Para review-file e review-commit
46
- path: zod_1.z.string().optional(),
47
- sha: zod_1.z.string().optional(),
48
- branch: zod_1.z.string().optional(),
49
- // Para review-pr
50
- pull_number: zod_1.z.number().optional(),
51
- // Para generate-report
52
- report_type: zod_1.z.enum(['summary', 'detailed', 'security', 'performance']).optional(),
53
- include_suggestions: zod_1.z.boolean().optional(),
54
- // Para apply-suggestions
55
- suggestions: zod_1.z.array(zod_1.z.object({
56
- file_path: zod_1.z.string(),
57
- line_number: zod_1.z.number(),
58
- suggestion: zod_1.z.string(),
59
- severity: zod_1.z.enum(['low', 'medium', 'high', 'critical'])
60
- })).optional(),
61
- // Configurações
62
- rules: zod_1.z.array(zod_1.z.string()).optional(),
63
- exclude_patterns: zod_1.z.array(zod_1.z.string()).optional()
64
- }).refine((data) => {
65
- if (['analyze'].includes(data.action)) {
66
- return !!data.code || !!(data.repo && data.file_path);
67
- }
68
- if (['review-file', 'review-commit'].includes(data.action)) {
69
- return !!(data.repo && (data.path || data.sha));
70
- }
71
- if (['review-pr'].includes(data.action)) {
72
- return !!(data.repo && data.pull_number);
73
- }
74
- if (['apply-suggestions'].includes(data.action)) {
75
- return !!(data.repo && data.suggestions && data.suggestions.length > 0);
76
- }
77
- return !!data.repo;
78
- }, {
79
- message: "Parâmetros obrigatórios não fornecidos para a ação especificada"
80
- });
81
- /**
82
- * Schema de validação para resultado da tool code-review
83
- */
84
- const CodeReviewResultSchema = zod_1.z.object({
85
- success: zod_1.z.boolean(),
86
- action: zod_1.z.string(),
87
- message: zod_1.z.string(),
88
- data: zod_1.z.any().optional(),
89
- error: zod_1.z.string().optional()
90
- });
91
- /**
92
- * Implementação da tool code-review
93
- */
94
- exports.codeReviewTool = {
95
- name: 'gh-code-review',
96
- description: 'tool: Análise de código GitHub para qualidade e detecção de problemas\n──────────────\naction analyze: análise geral de código\naction analyze requires: code, language, context, problem, rules, exclude_patterns\n───────────────\naction review-file: revisão de arquivo específico\naction review-file requires: repo, file_path, branch, rules, exclude_patterns\n───────────────\naction review-commit: revisão de commit específico\naction review-commit requires: repo, sha, branch, rules, exclude_patterns\n───────────────\naction review-pr: revisão de Pull Request\naction review-pr requires: repo, pull_number, rules, exclude_patterns\n───────────────\naction generate-report: geração de relatório\naction generate-report requires: repo, report_type, include_suggestions, branch\n───────────────\naction apply-suggestions: aplicar sugestões de correção\naction apply-suggestions requires: repo, suggestions, branch',
97
- inputSchema: {
98
- type: 'object',
99
- properties: {
100
- action: {
101
- type: 'string',
102
- enum: ['analyze', 'review-file', 'review-commit', 'review-pr', 'generate-report', 'apply-suggestions'],
103
- description: 'Ação a executar: analyze (análise), review-file (revisar arquivo), review-commit (revisar commit), review-pr (revisar PR), generate-report (gerar relatório), apply-suggestions (aplicar sugestões)'
104
- },
105
- repo: {
106
- type: 'string',
107
- description: 'Nome do repositório (OBRIGATÓRIO para ações que acessam repositório)'
108
- },
109
- code: { type: 'string', description: 'Código para análise direta' },
110
- language: { type: 'string', description: 'Linguagem de programação' },
111
- file_path: { type: 'string', description: 'Caminho do arquivo para análise' },
112
- path: { type: 'string', description: 'Caminho do arquivo' },
113
- sha: { type: 'string', description: 'SHA do commit' },
114
- branch: { type: 'string', description: 'Branch específica para análise' },
115
- pull_number: { type: 'number', description: 'Número do Pull Request' },
116
- report_type: { type: 'string', enum: ['summary', 'detailed', 'security', 'performance'], description: 'Tipo de relatório' },
117
- include_suggestions: { type: 'boolean', description: 'Incluir sugestões no relatório' },
118
- suggestions: {
119
- type: 'array',
120
- items: {
121
- type: 'object',
122
- properties: {
123
- file_path: { type: 'string' },
124
- line_number: { type: 'number' },
125
- suggestion: { type: 'string' },
126
- severity: { type: 'string', enum: ['low', 'medium', 'high', 'critical'] }
127
- }
128
- },
129
- description: 'Lista de sugestões para aplicar'
130
- },
131
- rules: { type: 'array', items: { type: 'string' }, description: 'Regras específicas para análise' },
132
- exclude_patterns: { type: 'array', items: { type: 'string' }, description: 'Padrões para excluir da análise' }
133
- },
134
- required: ['action', 'repo']
135
- },
136
- async handler(input) {
137
- try {
138
- const validatedInput = CodeReviewInputSchema.parse(input);
139
- // Fixar provider como github para tools exclusivas do GitHub
140
- const updatedParams = await (0, user_detection_js_1.applyAutoUserDetection)(validatedInput, 'github');
141
- const provider = index_js_1.globalProviderFactory.getProvider('github');
142
- if (!provider) {
143
- throw new Error('Provider GitHub não encontrado');
144
- }
145
- switch (updatedParams.action) {
146
- case 'analyze':
147
- return await this.analyzeCode(validatedInput);
148
- case 'review-file':
149
- return await this.reviewCommit(updatedParams, provider);
150
- case 'review-commit':
151
- return await this.reviewPullRequest(updatedParams, provider);
152
- case 'review-pr':
153
- return await this.generateReport(updatedParams, provider);
154
- case 'generate-report':
155
- return await this.applySuggestions(updatedParams, provider);
156
- case 'apply-suggestions':
157
- return await this.applySuggestions(updatedParams, provider);
158
- default:
159
- throw new Error(`Ação não suportada: ${updatedParams.action}`);
160
- }
161
- }
162
- catch (error) {
163
- return {
164
- success: false,
165
- action: input.action || 'unknown',
166
- message: 'Erro na análise de código',
167
- error: error instanceof Error ? error.message : String(error)
168
- };
169
- }
170
- },
171
- /**
172
- * Análise geral de código
173
- */
174
- async analyzeCode(params) {
175
- try {
176
- // Esta tool é específica do GitHub
177
- const provider = index_js_1.globalProviderFactory.getProvider('github');
178
- let codeToAnalyze = params.code;
179
- let fileName = 'code.txt';
180
- // Se não foi fornecido código direto, buscar do repositório
181
- if (!codeToAnalyze && params.repo && params.file_path) {
182
- if (provider) {
183
- const currentUser = await provider.getCurrentUser();
184
- const owner = currentUser.login;
185
- const file = await provider.getFile((await provider.getCurrentUser()).login, params.repo, params.file_path);
186
- codeToAnalyze = file.content || '';
187
- fileName = params.file_path;
188
- }
189
- }
190
- if (!codeToAnalyze) {
191
- throw new Error('Código não fornecido para análise');
192
- }
193
- // Análise básica de qualidade
194
- const analysis = this.performCodeAnalysis(codeToAnalyze, params.language || 'unknown', fileName, params.rules);
195
- return {
196
- success: true,
197
- action: 'analyze',
198
- message: `Análise de código concluída para ${fileName}`,
199
- data: analysis
200
- };
201
- }
202
- catch (error) {
203
- throw new Error(`Falha na análise de código: ${error}`);
204
- }
205
- },
206
- /**
207
- * Revisão de arquivo específico
208
- */
209
- async reviewFile(params, provider) {
210
- try {
211
- if (!params.repo || !params.path) {
212
- throw new Error('Repo e path são obrigatórios');
213
- }
214
- const currentUser = await provider.getCurrentUser();
215
- const owner = currentUser.login;
216
- const file = await provider.getFile((await provider.getCurrentUser()).login, params.repo, params.path, params.branch);
217
- if (!file.content) {
218
- throw new Error('Arquivo não possui conteúdo para análise');
219
- }
220
- const analysis = this.performCodeAnalysis(file.content, this.detectLanguage(params.path), params.path, params.rules);
221
- return {
222
- success: true,
223
- action: 'review-file',
224
- message: `Revisão de arquivo '${params.path}' concluída`,
225
- data: {
226
- file: params.path,
227
- analysis,
228
- branch: params.branch || 'default'
229
- }
230
- };
231
- }
232
- catch (error) {
233
- throw new Error(`Falha na revisão de arquivo: ${error}`);
234
- }
235
- },
236
- /**
237
- * Revisão de commit específico
238
- */
239
- async reviewCommit(params, provider) {
240
- try {
241
- if (!params.repo || !params.sha) {
242
- throw new Error('Repo e sha são obrigatórios');
243
- }
244
- const currentUser = await provider.getCurrentUser();
245
- const owner = currentUser.login;
246
- const commit = await provider.getCommit((await provider.getCurrentUser()).login, params.repo, params.sha);
247
- // Análise básica da mensagem do commit
248
- const messageAnalysis = this.analyzeCommitMessage(commit.message);
249
- return {
250
- success: true,
251
- action: 'review-commit',
252
- message: `Revisão de commit ${params.sha.substring(0, 7)} concluída`,
253
- data: {
254
- commit: params.sha,
255
- message_analysis: messageAnalysis,
256
- author: commit.author,
257
- committer: commit.committer
258
- }
259
- };
260
- }
261
- catch (error) {
262
- throw new Error(`Falha na revisão de commit: ${error}`);
263
- }
264
- },
265
- /**
266
- * Revisão de Pull Request
267
- */
268
- async reviewPullRequest(params, provider) {
269
- try {
270
- if (!params.repo || !(params.pull_number || 0)) {
271
- throw new Error('Repo e pull_number são obrigatórios');
272
- }
273
- // Buscar informações do PR
274
- const currentUser = await provider.getCurrentUser();
275
- const owner = currentUser.login;
276
- const pr = await provider.getPullRequest((await provider.getCurrentUser()).login, params.repo, (params.pull_number || 0));
277
- const review = {
278
- pr_number: (params.pull_number || 0),
279
- title: pr.title,
280
- body: pr.body,
281
- changes: {
282
- additions: 'Não disponível',
283
- deletions: 'Não disponível',
284
- files_changed: 'Não disponível'
285
- },
286
- quality_score: this.calculateQualityScore(pr),
287
- suggestions: [
288
- 'Verificar se todos os testes estão passando',
289
- 'Revisar documentação atualizada',
290
- 'Verificar impacto em performance'
291
- ]
292
- };
293
- return {
294
- success: true,
295
- action: 'review-pr',
296
- message: `Revisão de PR #${(params.pull_number || 0)} concluída`,
297
- data: review
298
- };
299
- }
300
- catch (error) {
301
- throw new Error(`Falha na revisão de PR: ${error}`);
302
- }
303
- },
304
- /**
305
- * Geração de relatório de qualidade
306
- */
307
- async generateReport(params, provider) {
308
- try {
309
- // Validação movida para schema - owner/repo serão auto-detectados se não fornecidos
310
- const reportType = params.report_type || 'summary';
311
- const includeSuggestions = params.include_suggestions !== false;
312
- const report = {
313
- repository: `${params.repo}`,
314
- report_type: reportType,
315
- generated_at: new Date().toISOString(),
316
- summary: {
317
- total_files: 'Não disponível',
318
- quality_score: 'Não calculado',
319
- issues_found: 0,
320
- critical_issues: 0
321
- },
322
- recommendations: includeSuggestions ? [
323
- 'Implementar testes automatizados',
324
- 'Configurar linter específico da linguagem',
325
- 'Adicionar documentação técnica',
326
- 'Revisar dependências desatualizadas'
327
- ] : []
328
- };
329
- return {
330
- success: true,
331
- action: 'generate-report',
332
- message: `Relatório ${reportType} gerado com sucesso`,
333
- data: report
334
- };
335
- }
336
- catch (error) {
337
- throw new Error(`Falha na geração de relatório: ${error}`);
338
- }
339
- },
340
- /**
341
- * Aplicação de sugestões de correção
342
- */
343
- async applySuggestions(params, provider) {
344
- try {
345
- if (!params.repo || !params.suggestions) {
346
- throw new Error('Repo e suggestions são obrigatórios');
347
- }
348
- const applied = [];
349
- const failed = [];
350
- for (const suggestion of params.suggestions) {
351
- try {
352
- // Para cada sugestão, buscar o arquivo atual
353
- const currentUser = await provider.getCurrentUser();
354
- const owner = currentUser.login;
355
- const file = await provider.getFile((await provider.getCurrentUser()).login, params.repo, suggestion.file_path);
356
- if (file.content) {
357
- // Aplicar sugestão (simplificado - apenas marcar como aplicada)
358
- applied.push({
359
- file: suggestion.file_path,
360
- line: suggestion.line_number,
361
- suggestion: suggestion.suggestion,
362
- status: 'applied'
363
- });
364
- }
365
- }
366
- catch (error) {
367
- failed.push({
368
- file: suggestion.file_path,
369
- error: error instanceof Error ? error.message : String(error)
370
- });
371
- }
372
- }
373
- return {
374
- success: true,
375
- action: 'apply-suggestions',
376
- message: `Aplicadas ${applied.length} sugestões, ${failed.length} falharam`,
377
- data: {
378
- applied,
379
- failed,
380
- total: params.suggestions.length
381
- }
382
- };
383
- }
384
- catch (error) {
385
- throw new Error(`Falha na aplicação de sugestões: ${error}`);
386
- }
387
- },
388
- /**
389
- * Análise básica de código
390
- */
391
- performCodeAnalysis(code, language, fileName, rules) {
392
- const issues = [];
393
- const suggestions = [];
394
- const lines = code.split('\n');
395
- // Análise básica de complexidade
396
- if (lines.length > 300) {
397
- issues.push({
398
- type: 'complexity',
399
- severity: 'medium',
400
- message: 'Arquivo muito longo - considere dividir em módulos menores',
401
- line: 1
402
- });
403
- }
404
- // Detecção de código comentado
405
- let commentLines = 0;
406
- lines.forEach((line, index) => {
407
- if (line.trim().startsWith('//') || line.trim().startsWith('#') || line.trim().startsWith('/*')) {
408
- commentLines++;
409
- }
410
- // Detecção de console.log (comum em JS/TS)
411
- if (language === 'javascript' || language === 'typescript') {
412
- if (line.includes('console.log') && !rules?.includes('allow-console')) {
413
- issues.push({
414
- type: 'code-quality',
415
- severity: 'low',
416
- message: 'Uso de console.log detectado - considere remover para produção',
417
- line: index + 1
418
- });
419
- }
420
- }
421
- });
422
- // Análise de comentários
423
- const commentRatio = commentLines / lines.length;
424
- if (commentRatio < 0.1) {
425
- suggestions.push('Considere adicionar mais comentários explicativos');
426
- }
427
- return {
428
- file: fileName,
429
- language,
430
- lines_count: lines.length,
431
- comment_lines: commentLines,
432
- comment_ratio: Math.round(commentRatio * 100) / 100,
433
- issues,
434
- suggestions,
435
- quality_score: this.calculateQualityScore({ lines: lines.length, issues: issues.length })
436
- };
437
- },
438
- /**
439
- * Detecta linguagem baseada na extensão do arquivo
440
- */
441
- detectLanguage(filePath) {
442
- const ext = filePath.split('.').pop()?.toLowerCase();
443
- const languageMap = {
444
- 'js': 'javascript',
445
- 'ts': 'typescript',
446
- 'py': 'python',
447
- 'java': 'java',
448
- 'cpp': 'cpp',
449
- 'c': 'c',
450
- 'php': 'php',
451
- 'rb': 'ruby',
452
- 'go': 'go',
453
- 'rs': 'rust',
454
- 'swift': 'swift',
455
- 'kt': 'kotlin',
456
- 'scala': 'scala',
457
- 'html': 'html',
458
- 'css': 'css',
459
- 'scss': 'scss',
460
- 'md': 'markdown',
461
- 'json': 'json',
462
- 'xml': 'xml',
463
- 'yaml': 'yaml',
464
- 'yml': 'yaml'
465
- };
466
- return languageMap[ext || ''] || 'unknown';
467
- },
468
- /**
469
- * Análise de mensagem de commit
470
- */
471
- analyzeCommitMessage(message) {
472
- const analysis = {
473
- quality: 'good',
474
- suggestions: [],
475
- follows_conventions: false
476
- };
477
- // Verificar se segue convenção de commits
478
- const conventionalPattern = /^(feat|fix|docs|style|refactor|test|chore|perf|ci|build|revert)(\(.+\))?: .{1,50}/;
479
- analysis.follows_conventions = conventionalPattern.test(message);
480
- if (!analysis.follows_conventions) {
481
- analysis.suggestions.push('Considere usar conventional commits (feat:, fix:, docs:, etc.)');
482
- }
483
- if (message.length > 72) {
484
- analysis.quality = 'medium';
485
- analysis.suggestions.push('Mensagem muito longa - considere resumir na primeira linha');
486
- }
487
- if (message.length < 10) {
488
- analysis.quality = 'low';
489
- analysis.suggestions.push('Mensagem muito curta - seja mais descritivo');
490
- }
491
- return analysis;
492
- },
493
- /**
494
- * Calcula score de qualidade básico
495
- */
496
- calculateQualityScore(data) {
497
- let score = 100;
498
- // Penalizar por issues
499
- if (data.issues) {
500
- score -= data.issues * 10;
501
- }
502
- // Penalizar por complexidade
503
- if (data.lines && data.lines > 500) {
504
- score -= 20;
505
- }
506
- // Bonus por comentários adequados
507
- if (data.comment_ratio && data.comment_ratio > 0.2) {
508
- score += 10;
509
- }
510
- return Math.max(0, Math.min(100, score));
511
- }
512
- };
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.codeReviewTool = void 0;
4
+ const zod_1 = require("zod");
5
+ const index_js_1 = require("../providers/index.js");
6
+ const user_detection_js_1 = require("../utils/user-detection.js");
7
+ /**
8
+ * Tool: code-review
9
+ *
10
+ * DESCRIÇÃO:
11
+ * Ferramenta completa de revisão de código com análise automatizada,
12
+ * sugestões de melhorias, detecção de problemas e geração de relatórios.
13
+ *
14
+ * FUNCIONALIDADES:
15
+ * - Análise de qualidade de código
16
+ * - Detecção de bugs e vulnerabilidades
17
+ * - Sugestões de otimização
18
+ * - Revisão de commits e arquivos
19
+ * - Geração de relatórios de qualidade
20
+ * - Aplicação automática de correções
21
+ *
22
+ * USO:
23
+ * - Para revisão automatizada de pull requests
24
+ * - Para análise de qualidade de código
25
+ * - Para detecção de problemas de segurança
26
+ * - Para sugestões de melhorias de performance
27
+ *
28
+ * RECOMENDAÇÕES:
29
+ * - Execute regularmente em novos commits
30
+ * - Configure regras específicas por linguagem
31
+ * - Use em conjunto com CI/CD
32
+ * - Revise sugestões antes de aplicar
33
+ */
34
+ /**
35
+ * Schema de validação para entrada da tool code-review
36
+ */
37
+ const CodeReviewInputSchema = zod_1.z.object({
38
+ action: zod_1.z.enum(['analyze', 'review-file', 'review-commit', 'review-pr', 'generate-report', 'apply-suggestions']),
39
+ // Parâmetros comuns
40
+ repo: zod_1.z.string(),
41
+ // Para analyze
42
+ code: zod_1.z.string().optional(),
43
+ language: zod_1.z.string().optional(),
44
+ file_path: zod_1.z.string().optional(),
45
+ // Para review-file e review-commit
46
+ path: zod_1.z.string().optional(),
47
+ sha: zod_1.z.string().optional(),
48
+ branch: zod_1.z.string().optional(),
49
+ // Para review-pr
50
+ pull_number: zod_1.z.number().optional(),
51
+ // Para generate-report
52
+ report_type: zod_1.z.enum(['summary', 'detailed', 'security', 'performance']).optional(),
53
+ include_suggestions: zod_1.z.boolean().optional(),
54
+ // Para apply-suggestions
55
+ suggestions: zod_1.z.array(zod_1.z.object({
56
+ file_path: zod_1.z.string(),
57
+ line_number: zod_1.z.number(),
58
+ suggestion: zod_1.z.string(),
59
+ severity: zod_1.z.enum(['low', 'medium', 'high', 'critical'])
60
+ })).optional(),
61
+ // Configurações
62
+ rules: zod_1.z.array(zod_1.z.string()).optional(),
63
+ exclude_patterns: zod_1.z.array(zod_1.z.string()).optional()
64
+ }).refine((data) => {
65
+ if (['analyze'].includes(data.action)) {
66
+ return !!data.code || !!(data.repo && data.file_path);
67
+ }
68
+ if (['review-file', 'review-commit'].includes(data.action)) {
69
+ return !!(data.repo && (data.path || data.sha));
70
+ }
71
+ if (['review-pr'].includes(data.action)) {
72
+ return !!(data.repo && data.pull_number);
73
+ }
74
+ if (['apply-suggestions'].includes(data.action)) {
75
+ return !!(data.repo && data.suggestions && data.suggestions.length > 0);
76
+ }
77
+ return !!data.repo;
78
+ }, {
79
+ message: "Parâmetros obrigatórios não fornecidos para a ação especificada"
80
+ });
81
+ /**
82
+ * Schema de validação para resultado da tool code-review
83
+ */
84
+ const CodeReviewResultSchema = zod_1.z.object({
85
+ success: zod_1.z.boolean(),
86
+ action: zod_1.z.string(),
87
+ message: zod_1.z.string(),
88
+ data: zod_1.z.any().optional(),
89
+ error: zod_1.z.string().optional()
90
+ });
91
+ /**
92
+ * Implementação da tool code-review
93
+ */
94
+ exports.codeReviewTool = {
95
+ name: 'gh-code-review',
96
+ description: 'tool: Análise de código GitHub para qualidade e detecção de problemas\n──────────────\naction analyze: análise geral de código\naction analyze requires: code, language, context, problem, rules, exclude_patterns\n───────────────\naction review-file: revisão de arquivo específico\naction review-file requires: repo, file_path, branch, rules, exclude_patterns\n───────────────\naction review-commit: revisão de commit específico\naction review-commit requires: repo, sha, branch, rules, exclude_patterns\n───────────────\naction review-pr: revisão de Pull Request\naction review-pr requires: repo, pull_number, rules, exclude_patterns\n───────────────\naction generate-report: geração de relatório\naction generate-report requires: repo, report_type, include_suggestions, branch\n───────────────\naction apply-suggestions: aplicar sugestões de correção\naction apply-suggestions requires: repo, suggestions, branch',
97
+ inputSchema: {
98
+ type: 'object',
99
+ properties: {
100
+ action: {
101
+ type: 'string',
102
+ enum: ['analyze', 'review-file', 'review-commit', 'review-pr', 'generate-report', 'apply-suggestions'],
103
+ description: 'Ação a executar: analyze (análise), review-file (revisar arquivo), review-commit (revisar commit), review-pr (revisar PR), generate-report (gerar relatório), apply-suggestions (aplicar sugestões)'
104
+ },
105
+ repo: {
106
+ type: 'string',
107
+ description: 'Nome do repositório (OBRIGATÓRIO para ações que acessam repositório)'
108
+ },
109
+ code: { type: 'string', description: 'Código para análise direta' },
110
+ language: { type: 'string', description: 'Linguagem de programação' },
111
+ file_path: { type: 'string', description: 'Caminho do arquivo para análise' },
112
+ path: { type: 'string', description: 'Caminho do arquivo' },
113
+ sha: { type: 'string', description: 'SHA do commit' },
114
+ branch: { type: 'string', description: 'Branch específica para análise' },
115
+ pull_number: { type: 'number', description: 'Número do Pull Request' },
116
+ report_type: { type: 'string', enum: ['summary', 'detailed', 'security', 'performance'], description: 'Tipo de relatório' },
117
+ include_suggestions: { type: 'boolean', description: 'Incluir sugestões no relatório' },
118
+ suggestions: {
119
+ type: 'array',
120
+ items: {
121
+ type: 'object',
122
+ properties: {
123
+ file_path: { type: 'string' },
124
+ line_number: { type: 'number' },
125
+ suggestion: { type: 'string' },
126
+ severity: { type: 'string', enum: ['low', 'medium', 'high', 'critical'] }
127
+ }
128
+ },
129
+ description: 'Lista de sugestões para aplicar'
130
+ },
131
+ rules: { type: 'array', items: { type: 'string' }, description: 'Regras específicas para análise' },
132
+ exclude_patterns: { type: 'array', items: { type: 'string' }, description: 'Padrões para excluir da análise' }
133
+ },
134
+ required: ['action', 'repo']
135
+ },
136
+ async handler(input) {
137
+ try {
138
+ const validatedInput = CodeReviewInputSchema.parse(input);
139
+ // Fixar provider como github para tools exclusivas do GitHub
140
+ const updatedParams = await (0, user_detection_js_1.applyAutoUserDetection)(validatedInput, 'github');
141
+ const provider = index_js_1.globalProviderFactory.getProvider('github');
142
+ if (!provider) {
143
+ throw new Error('Provider GitHub não encontrado');
144
+ }
145
+ switch (updatedParams.action) {
146
+ case 'analyze':
147
+ return await this.analyzeCode(validatedInput);
148
+ case 'review-file':
149
+ return await this.reviewCommit(updatedParams, provider);
150
+ case 'review-commit':
151
+ return await this.reviewPullRequest(updatedParams, provider);
152
+ case 'review-pr':
153
+ return await this.generateReport(updatedParams, provider);
154
+ case 'generate-report':
155
+ return await this.applySuggestions(updatedParams, provider);
156
+ case 'apply-suggestions':
157
+ return await this.applySuggestions(updatedParams, provider);
158
+ default:
159
+ throw new Error(`Ação não suportada: ${updatedParams.action}`);
160
+ }
161
+ }
162
+ catch (error) {
163
+ return {
164
+ success: false,
165
+ action: input.action || 'unknown',
166
+ message: 'Erro na análise de código',
167
+ error: error instanceof Error ? error.message : String(error)
168
+ };
169
+ }
170
+ },
171
+ /**
172
+ * Análise geral de código
173
+ */
174
+ async analyzeCode(params) {
175
+ try {
176
+ // Esta tool é específica do GitHub
177
+ const provider = index_js_1.globalProviderFactory.getProvider('github');
178
+ let codeToAnalyze = params.code;
179
+ let fileName = 'code.txt';
180
+ // Se não foi fornecido código direto, buscar do repositório
181
+ if (!codeToAnalyze && params.repo && params.file_path) {
182
+ if (provider) {
183
+ const currentUser = await provider.getCurrentUser();
184
+ const owner = currentUser.login;
185
+ const file = await provider.getFile((await provider.getCurrentUser()).login, params.repo, params.file_path);
186
+ codeToAnalyze = file.content || '';
187
+ fileName = params.file_path;
188
+ }
189
+ }
190
+ if (!codeToAnalyze) {
191
+ throw new Error('Código não fornecido para análise');
192
+ }
193
+ // Análise básica de qualidade
194
+ const analysis = this.performCodeAnalysis(codeToAnalyze, params.language || 'unknown', fileName, params.rules);
195
+ return {
196
+ success: true,
197
+ action: 'analyze',
198
+ message: `Análise de código concluída para ${fileName}`,
199
+ data: analysis
200
+ };
201
+ }
202
+ catch (error) {
203
+ throw new Error(`Falha na análise de código: ${error}`);
204
+ }
205
+ },
206
+ /**
207
+ * Revisão de arquivo específico
208
+ */
209
+ async reviewFile(params, provider) {
210
+ try {
211
+ if (!params.repo || !params.path) {
212
+ throw new Error('Repo e path são obrigatórios');
213
+ }
214
+ const currentUser = await provider.getCurrentUser();
215
+ const owner = currentUser.login;
216
+ const file = await provider.getFile((await provider.getCurrentUser()).login, params.repo, params.path, params.branch);
217
+ if (!file.content) {
218
+ throw new Error('Arquivo não possui conteúdo para análise');
219
+ }
220
+ const analysis = this.performCodeAnalysis(file.content, this.detectLanguage(params.path), params.path, params.rules);
221
+ return {
222
+ success: true,
223
+ action: 'review-file',
224
+ message: `Revisão de arquivo '${params.path}' concluída`,
225
+ data: {
226
+ file: params.path,
227
+ analysis,
228
+ branch: params.branch || 'default'
229
+ }
230
+ };
231
+ }
232
+ catch (error) {
233
+ throw new Error(`Falha na revisão de arquivo: ${error}`);
234
+ }
235
+ },
236
+ /**
237
+ * Revisão de commit específico
238
+ */
239
+ async reviewCommit(params, provider) {
240
+ try {
241
+ if (!params.repo || !params.sha) {
242
+ throw new Error('Repo e sha são obrigatórios');
243
+ }
244
+ const currentUser = await provider.getCurrentUser();
245
+ const owner = currentUser.login;
246
+ const commit = await provider.getCommit((await provider.getCurrentUser()).login, params.repo, params.sha);
247
+ // Análise básica da mensagem do commit
248
+ const messageAnalysis = this.analyzeCommitMessage(commit.message);
249
+ return {
250
+ success: true,
251
+ action: 'review-commit',
252
+ message: `Revisão de commit ${params.sha.substring(0, 7)} concluída`,
253
+ data: {
254
+ commit: params.sha,
255
+ message_analysis: messageAnalysis,
256
+ author: commit.author,
257
+ committer: commit.committer
258
+ }
259
+ };
260
+ }
261
+ catch (error) {
262
+ throw new Error(`Falha na revisão de commit: ${error}`);
263
+ }
264
+ },
265
+ /**
266
+ * Revisão de Pull Request
267
+ */
268
+ async reviewPullRequest(params, provider) {
269
+ try {
270
+ if (!params.repo || !(params.pull_number || 0)) {
271
+ throw new Error('Repo e pull_number são obrigatórios');
272
+ }
273
+ // Buscar informações do PR
274
+ const currentUser = await provider.getCurrentUser();
275
+ const owner = currentUser.login;
276
+ const pr = await provider.getPullRequest((await provider.getCurrentUser()).login, params.repo, (params.pull_number || 0));
277
+ const review = {
278
+ pr_number: (params.pull_number || 0),
279
+ title: pr.title,
280
+ body: pr.body,
281
+ changes: {
282
+ additions: 'Não disponível',
283
+ deletions: 'Não disponível',
284
+ files_changed: 'Não disponível'
285
+ },
286
+ quality_score: this.calculateQualityScore(pr),
287
+ suggestions: [
288
+ 'Verificar se todos os testes estão passando',
289
+ 'Revisar documentação atualizada',
290
+ 'Verificar impacto em performance'
291
+ ]
292
+ };
293
+ return {
294
+ success: true,
295
+ action: 'review-pr',
296
+ message: `Revisão de PR #${(params.pull_number || 0)} concluída`,
297
+ data: review
298
+ };
299
+ }
300
+ catch (error) {
301
+ throw new Error(`Falha na revisão de PR: ${error}`);
302
+ }
303
+ },
304
+ /**
305
+ * Geração de relatório de qualidade
306
+ */
307
+ async generateReport(params, provider) {
308
+ try {
309
+ // Validação movida para schema - owner/repo serão auto-detectados se não fornecidos
310
+ const reportType = params.report_type || 'summary';
311
+ const includeSuggestions = params.include_suggestions !== false;
312
+ const report = {
313
+ repository: `${params.repo}`,
314
+ report_type: reportType,
315
+ generated_at: new Date().toISOString(),
316
+ summary: {
317
+ total_files: 'Não disponível',
318
+ quality_score: 'Não calculado',
319
+ issues_found: 0,
320
+ critical_issues: 0
321
+ },
322
+ recommendations: includeSuggestions ? [
323
+ 'Implementar testes automatizados',
324
+ 'Configurar linter específico da linguagem',
325
+ 'Adicionar documentação técnica',
326
+ 'Revisar dependências desatualizadas'
327
+ ] : []
328
+ };
329
+ return {
330
+ success: true,
331
+ action: 'generate-report',
332
+ message: `Relatório ${reportType} gerado com sucesso`,
333
+ data: report
334
+ };
335
+ }
336
+ catch (error) {
337
+ throw new Error(`Falha na geração de relatório: ${error}`);
338
+ }
339
+ },
340
+ /**
341
+ * Aplicação de sugestões de correção
342
+ */
343
+ async applySuggestions(params, provider) {
344
+ try {
345
+ if (!params.repo || !params.suggestions) {
346
+ throw new Error('Repo e suggestions são obrigatórios');
347
+ }
348
+ const applied = [];
349
+ const failed = [];
350
+ for (const suggestion of params.suggestions) {
351
+ try {
352
+ // Para cada sugestão, buscar o arquivo atual
353
+ const currentUser = await provider.getCurrentUser();
354
+ const owner = currentUser.login;
355
+ const file = await provider.getFile((await provider.getCurrentUser()).login, params.repo, suggestion.file_path);
356
+ if (file.content) {
357
+ // Aplicar sugestão (simplificado - apenas marcar como aplicada)
358
+ applied.push({
359
+ file: suggestion.file_path,
360
+ line: suggestion.line_number,
361
+ suggestion: suggestion.suggestion,
362
+ status: 'applied'
363
+ });
364
+ }
365
+ }
366
+ catch (error) {
367
+ failed.push({
368
+ file: suggestion.file_path,
369
+ error: error instanceof Error ? error.message : String(error)
370
+ });
371
+ }
372
+ }
373
+ return {
374
+ success: true,
375
+ action: 'apply-suggestions',
376
+ message: `Aplicadas ${applied.length} sugestões, ${failed.length} falharam`,
377
+ data: {
378
+ applied,
379
+ failed,
380
+ total: params.suggestions.length
381
+ }
382
+ };
383
+ }
384
+ catch (error) {
385
+ throw new Error(`Falha na aplicação de sugestões: ${error}`);
386
+ }
387
+ },
388
+ /**
389
+ * Análise básica de código
390
+ */
391
+ performCodeAnalysis(code, language, fileName, rules) {
392
+ const issues = [];
393
+ const suggestions = [];
394
+ const lines = code.split('\n');
395
+ // Análise básica de complexidade
396
+ if (lines.length > 300) {
397
+ issues.push({
398
+ type: 'complexity',
399
+ severity: 'medium',
400
+ message: 'Arquivo muito longo - considere dividir em módulos menores',
401
+ line: 1
402
+ });
403
+ }
404
+ // Detecção de código comentado
405
+ let commentLines = 0;
406
+ lines.forEach((line, index) => {
407
+ if (line.trim().startsWith('//') || line.trim().startsWith('#') || line.trim().startsWith('/*')) {
408
+ commentLines++;
409
+ }
410
+ // Detecção de console.log (comum em JS/TS)
411
+ if (language === 'javascript' || language === 'typescript') {
412
+ if (line.includes('console.log') && !rules?.includes('allow-console')) {
413
+ issues.push({
414
+ type: 'code-quality',
415
+ severity: 'low',
416
+ message: 'Uso de console.log detectado - considere remover para produção',
417
+ line: index + 1
418
+ });
419
+ }
420
+ }
421
+ });
422
+ // Análise de comentários
423
+ const commentRatio = commentLines / lines.length;
424
+ if (commentRatio < 0.1) {
425
+ suggestions.push('Considere adicionar mais comentários explicativos');
426
+ }
427
+ return {
428
+ file: fileName,
429
+ language,
430
+ lines_count: lines.length,
431
+ comment_lines: commentLines,
432
+ comment_ratio: Math.round(commentRatio * 100) / 100,
433
+ issues,
434
+ suggestions,
435
+ quality_score: this.calculateQualityScore({ lines: lines.length, issues: issues.length })
436
+ };
437
+ },
438
+ /**
439
+ * Detecta linguagem baseada na extensão do arquivo
440
+ */
441
+ detectLanguage(filePath) {
442
+ const ext = filePath.split('.').pop()?.toLowerCase();
443
+ const languageMap = {
444
+ 'js': 'javascript',
445
+ 'ts': 'typescript',
446
+ 'py': 'python',
447
+ 'java': 'java',
448
+ 'cpp': 'cpp',
449
+ 'c': 'c',
450
+ 'php': 'php',
451
+ 'rb': 'ruby',
452
+ 'go': 'go',
453
+ 'rs': 'rust',
454
+ 'swift': 'swift',
455
+ 'kt': 'kotlin',
456
+ 'scala': 'scala',
457
+ 'html': 'html',
458
+ 'css': 'css',
459
+ 'scss': 'scss',
460
+ 'md': 'markdown',
461
+ 'json': 'json',
462
+ 'xml': 'xml',
463
+ 'yaml': 'yaml',
464
+ 'yml': 'yaml'
465
+ };
466
+ return languageMap[ext || ''] || 'unknown';
467
+ },
468
+ /**
469
+ * Análise de mensagem de commit
470
+ */
471
+ analyzeCommitMessage(message) {
472
+ const analysis = {
473
+ quality: 'good',
474
+ suggestions: [],
475
+ follows_conventions: false
476
+ };
477
+ // Verificar se segue convenção de commits
478
+ const conventionalPattern = /^(feat|fix|docs|style|refactor|test|chore|perf|ci|build|revert)(\(.+\))?: .{1,50}/;
479
+ analysis.follows_conventions = conventionalPattern.test(message);
480
+ if (!analysis.follows_conventions) {
481
+ analysis.suggestions.push('Considere usar conventional commits (feat:, fix:, docs:, etc.)');
482
+ }
483
+ if (message.length > 72) {
484
+ analysis.quality = 'medium';
485
+ analysis.suggestions.push('Mensagem muito longa - considere resumir na primeira linha');
486
+ }
487
+ if (message.length < 10) {
488
+ analysis.quality = 'low';
489
+ analysis.suggestions.push('Mensagem muito curta - seja mais descritivo');
490
+ }
491
+ return analysis;
492
+ },
493
+ /**
494
+ * Calcula score de qualidade básico
495
+ */
496
+ calculateQualityScore(data) {
497
+ let score = 100;
498
+ // Penalizar por issues
499
+ if (data.issues) {
500
+ score -= data.issues * 10;
501
+ }
502
+ // Penalizar por complexidade
503
+ if (data.lines && data.lines > 500) {
504
+ score -= 20;
505
+ }
506
+ // Bonus por comentários adequados
507
+ if (data.comment_ratio && data.comment_ratio > 0.2) {
508
+ score += 10;
509
+ }
510
+ return Math.max(0, Math.min(100, score));
511
+ }
512
+ };
513
513
  //# sourceMappingURL=gh-code-review.js.map