airev 1.2.0__py3-none-any.whl → 1.3.0__py3-none-any.whl
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.
- {airev-1.2.0.dist-info → airev-1.3.0.dist-info}/METADATA +1 -1
- {airev-1.2.0.dist-info → airev-1.3.0.dist-info}/RECORD +14 -14
- code_reviewer/__init__.py +1 -1
- code_reviewer/cli.py +13 -1
- code_reviewer/formatters/terminal.py +25 -2
- code_reviewer/locales/en.yaml +7 -0
- code_reviewer/locales/pt-br.yaml +7 -0
- code_reviewer/models.py +2 -1
- code_reviewer/prompt_builder.py +48 -0
- code_reviewer/prompts/review_system.md +1 -1
- code_reviewer/response_parser.py +5 -0
- {airev-1.2.0.dist-info → airev-1.3.0.dist-info}/WHEEL +0 -0
- {airev-1.2.0.dist-info → airev-1.3.0.dist-info}/entry_points.txt +0 -0
- {airev-1.2.0.dist-info → airev-1.3.0.dist-info}/top_level.txt +0 -0
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
code_reviewer/__init__.py,sha256=
|
|
2
|
-
code_reviewer/cli.py,sha256=
|
|
1
|
+
code_reviewer/__init__.py,sha256=2ikWG5DdNPMPpfzCE5-SuTregtDM1BjI70S5l4Wks60,82
|
|
2
|
+
code_reviewer/cli.py,sha256=2b7z5GX8Pv6DEEIq-kwuM0_Bc8RrRIGbcyjYdHyIpRw,6975
|
|
3
3
|
code_reviewer/context_builder.py,sha256=XJGsJpc5YOP3jhldpMFnrJ-hLc4uf9O6_efxZa3sbsc,8790
|
|
4
4
|
code_reviewer/diff_parser.py,sha256=07EO0kJFYuS6GRgDUHH0czYJBKcL8CxLR-jLdq6PShs,6896
|
|
5
|
-
code_reviewer/models.py,sha256=
|
|
6
|
-
code_reviewer/prompt_builder.py,sha256=
|
|
7
|
-
code_reviewer/response_parser.py,sha256=
|
|
5
|
+
code_reviewer/models.py,sha256=Rl3t216u-h304pM-Hpk4TtvsbGZHEFiXGsWsvlY_xsM,4311
|
|
6
|
+
code_reviewer/prompt_builder.py,sha256=d1Kov5WCdLbGo0X1AI8XOP5bdaOVfz3d_X6HQC563S0,7262
|
|
7
|
+
code_reviewer/response_parser.py,sha256=Cz1TdCVf52FyXZqx5VEaJnpUETG3Epb-q3rqLNRUIhg,7693
|
|
8
8
|
code_reviewer/formatters/__init__.py,sha256=LXkD8nK7yWGtbc6ox85SHWZdQX5sVr5xLXkkCO0XE8A,49
|
|
9
9
|
code_reviewer/formatters/progress.py,sha256=mUmoB2xQYYuYz5IRJzn23wgOpiV7bXehXrPhP5rDT-g,8529
|
|
10
|
-
code_reviewer/formatters/terminal.py,sha256=
|
|
10
|
+
code_reviewer/formatters/terminal.py,sha256=_bI4bf3Qcsy6pR83AkzaXi_1Af3yH5uc3-kw11gSZt8,6617
|
|
11
11
|
code_reviewer/i18n/__init__.py,sha256=Uzm_sic0_ehZQSpyzxI9-IFX_5Saxo5V-sLR35eqrIM,4696
|
|
12
|
-
code_reviewer/locales/en.yaml,sha256=
|
|
13
|
-
code_reviewer/locales/pt-br.yaml,sha256=
|
|
14
|
-
code_reviewer/prompts/review_system.md,sha256=
|
|
12
|
+
code_reviewer/locales/en.yaml,sha256=iIAP9eWSMUX1L0f2MQXYm1dVaI1bH9uObxV3vKcOQW8,2069
|
|
13
|
+
code_reviewer/locales/pt-br.yaml,sha256=DVELflzF7B1Cdrq9lQV9KkQ2Gr-IyCE0w7uptC44vOI,2242
|
|
14
|
+
code_reviewer/prompts/review_system.md,sha256=V2AeAOwXp5lYB1Op3WDAMaDZtTnUDJ1sztOWIXjaHGk,2017
|
|
15
15
|
code_reviewer/runners/__init__.py,sha256=cLxawmzHwhymN2xSC7nUWEOpHHvvSklzZOqjy2Q7HIM,1194
|
|
16
16
|
code_reviewer/runners/base.py,sha256=xikp7yI4IcOX86uNA7CUWTCL_oNuHSF9WIs6OP6rnx0,1491
|
|
17
17
|
code_reviewer/runners/copilot.py,sha256=GpBYO-Splmo66EaUBfCmU8Et-NRB0w2gn7XEtIq9THw,2433
|
|
@@ -21,8 +21,8 @@ code_reviewer/updater/http_client.py,sha256=g4PnuY5KKbsA0EqLtHhOK4sxg_6P0drzd1HK
|
|
|
21
21
|
code_reviewer/updater/notifier.py,sha256=o4crwJOnCOSnzqk5gMt0MkYP3xm-yEXIGSnix988YzA,992
|
|
22
22
|
code_reviewer/updater/upgrade.py,sha256=xoAfpomMJA_K9t6myeXC6tLEBnKwAgxR9OD8tcJ4YXE,5842
|
|
23
23
|
code_reviewer/updater/version_check.py,sha256=2Zv35s5oeR0dHAGODPwO70dyshECaCzrQx7vEZAXYJM,4917
|
|
24
|
-
airev-1.
|
|
25
|
-
airev-1.
|
|
26
|
-
airev-1.
|
|
27
|
-
airev-1.
|
|
28
|
-
airev-1.
|
|
24
|
+
airev-1.3.0.dist-info/METADATA,sha256=IOCRgO9Yzy1RSxPXrOWewf43vL5-7WPv4xYt6OyQvI0,6258
|
|
25
|
+
airev-1.3.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
26
|
+
airev-1.3.0.dist-info/entry_points.txt,sha256=LDd8UajxUO4QUs63xt6z635doU7E1XzBPFQZeMrlShU,49
|
|
27
|
+
airev-1.3.0.dist-info/top_level.txt,sha256=VqPHk5LmBEOeRJOUhXq1lkW5UiT48zW7a9h7NDy9N0E,14
|
|
28
|
+
airev-1.3.0.dist-info/RECORD,,
|
code_reviewer/__init__.py
CHANGED
code_reviewer/cli.py
CHANGED
|
@@ -75,6 +75,13 @@ def main():
|
|
|
75
75
|
type=click.Choice(get_available_languages()),
|
|
76
76
|
help="Idioma das mensagens (default: pt-br)",
|
|
77
77
|
)
|
|
78
|
+
@click.option(
|
|
79
|
+
"--text-quality",
|
|
80
|
+
"-t",
|
|
81
|
+
is_flag=True,
|
|
82
|
+
default=False,
|
|
83
|
+
help="Ativa verificação de ortografia e clareza em mensagens de usuário",
|
|
84
|
+
)
|
|
78
85
|
def review(
|
|
79
86
|
base: str,
|
|
80
87
|
runner: str,
|
|
@@ -83,6 +90,7 @@ def review(
|
|
|
83
90
|
no_progress: bool,
|
|
84
91
|
progress: bool,
|
|
85
92
|
lang: str,
|
|
93
|
+
text_quality: bool,
|
|
86
94
|
):
|
|
87
95
|
"""Analisa o diff da branch atual contra a branch base.
|
|
88
96
|
|
|
@@ -95,6 +103,8 @@ def review(
|
|
|
95
103
|
airev review --base main --json-output
|
|
96
104
|
|
|
97
105
|
airev review --base main --no-progress
|
|
106
|
+
|
|
107
|
+
airev review --base main --text-quality
|
|
98
108
|
"""
|
|
99
109
|
workdir = workdir or Path.cwd()
|
|
100
110
|
start_time = time.perf_counter()
|
|
@@ -173,7 +183,9 @@ def review(
|
|
|
173
183
|
|
|
174
184
|
# Monta o prompt
|
|
175
185
|
with reporter.status(t("cli.building_prompt")):
|
|
176
|
-
prompt = build_prompt(
|
|
186
|
+
prompt = build_prompt(
|
|
187
|
+
diff_files, context_graphs, current_branch, base, text_quality=text_quality
|
|
188
|
+
)
|
|
177
189
|
|
|
178
190
|
# Obtém o runner
|
|
179
191
|
try:
|
|
@@ -5,7 +5,7 @@ from typing import TextIO
|
|
|
5
5
|
import sys
|
|
6
6
|
|
|
7
7
|
from ..i18n import t
|
|
8
|
-
from ..models import Finding, ReviewResult, Severity
|
|
8
|
+
from ..models import Category, Finding, ReviewResult, Severity
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
# Códigos ANSI para cores
|
|
@@ -71,6 +71,28 @@ def format_severity(severity: Severity) -> str:
|
|
|
71
71
|
return _colorize(f"[{severity.value}]", Colors.BOLD, Colors.BLUE)
|
|
72
72
|
|
|
73
73
|
|
|
74
|
+
def format_category_badge(category: Category) -> str:
|
|
75
|
+
"""Formata o badge da categoria.
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
category: Categoria do finding
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
String formatada com ícone e cor para a categoria
|
|
82
|
+
"""
|
|
83
|
+
# Ícones e cores por categoria
|
|
84
|
+
category_styles = {
|
|
85
|
+
Category.SECURITY: ("🔒", Colors.RED),
|
|
86
|
+
Category.PERFORMANCE: ("⚡", Colors.YELLOW),
|
|
87
|
+
Category.BUG: ("🐛", Colors.MAGENTA),
|
|
88
|
+
Category.RESOURCE_LEAK: ("💧", Colors.CYAN),
|
|
89
|
+
Category.TEXT_QUALITY: ("✏️", Colors.CYAN),
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
icon, color = category_styles.get(category, ("•", Colors.WHITE))
|
|
93
|
+
return f"{icon} {_colorize(category.value, color)}"
|
|
94
|
+
|
|
95
|
+
|
|
74
96
|
def format_finding(finding: Finding) -> str:
|
|
75
97
|
"""Formata um finding para exibição.
|
|
76
98
|
|
|
@@ -84,10 +106,11 @@ def format_finding(finding: Finding) -> str:
|
|
|
84
106
|
|
|
85
107
|
# Header: [SEVERITY] arquivo:linha - Título
|
|
86
108
|
severity_str = format_severity(finding.severity)
|
|
109
|
+
category_badge = format_category_badge(finding.category)
|
|
87
110
|
location = _colorize(f"{finding.file}:{finding.line}", Colors.CYAN)
|
|
88
111
|
title = _colorize(finding.title, Colors.BOLD)
|
|
89
112
|
|
|
90
|
-
lines.append(f" {severity_str} {location} - {title}")
|
|
113
|
+
lines.append(f" {severity_str} {category_badge} {location} - {title}")
|
|
91
114
|
|
|
92
115
|
# Descrição
|
|
93
116
|
if finding.description:
|
code_reviewer/locales/en.yaml
CHANGED
|
@@ -47,6 +47,13 @@ terminal:
|
|
|
47
47
|
# Findings
|
|
48
48
|
suggestion: "Suggestion:"
|
|
49
49
|
|
|
50
|
+
# Categories
|
|
51
|
+
category_security: "security"
|
|
52
|
+
category_performance: "performance"
|
|
53
|
+
category_bug: "bug"
|
|
54
|
+
category_resource_leak: "resource leak"
|
|
55
|
+
category_text_quality: "text quality"
|
|
56
|
+
|
|
50
57
|
# Summary
|
|
51
58
|
summary: "SUMMARY:"
|
|
52
59
|
findings_count: "{count} finding(s)"
|
code_reviewer/locales/pt-br.yaml
CHANGED
|
@@ -47,6 +47,13 @@ terminal:
|
|
|
47
47
|
# Findings
|
|
48
48
|
suggestion: "Sugestão:"
|
|
49
49
|
|
|
50
|
+
# Categorias
|
|
51
|
+
category_security: "segurança"
|
|
52
|
+
category_performance: "performance"
|
|
53
|
+
category_bug: "bug"
|
|
54
|
+
category_resource_leak: "vazamento de recurso"
|
|
55
|
+
category_text_quality: "qualidade de texto"
|
|
56
|
+
|
|
50
57
|
# Resumo
|
|
51
58
|
summary: "RESUMO:"
|
|
52
59
|
findings_count: "{count} finding(s)"
|
code_reviewer/models.py
CHANGED
|
@@ -21,6 +21,7 @@ class Category(str, Enum):
|
|
|
21
21
|
PERFORMANCE = "performance"
|
|
22
22
|
BUG = "bug"
|
|
23
23
|
RESOURCE_LEAK = "resource-leak"
|
|
24
|
+
TEXT_QUALITY = "text-quality"
|
|
24
25
|
|
|
25
26
|
|
|
26
27
|
class DiffLine(BaseModel):
|
|
@@ -90,7 +91,7 @@ class Finding(BaseModel):
|
|
|
90
91
|
line: int = Field(description="Número da linha")
|
|
91
92
|
severity: Severity = Field(description="Severidade: CRITICAL, WARNING, INFO")
|
|
92
93
|
category: Category = Field(
|
|
93
|
-
description="Categoria: security, performance, bug, resource-leak"
|
|
94
|
+
description="Categoria: security, performance, bug, resource-leak, text-quality"
|
|
94
95
|
)
|
|
95
96
|
title: str = Field(description="Título curto do problema")
|
|
96
97
|
description: str = Field(description="Descrição detalhada do problema")
|
code_reviewer/prompt_builder.py
CHANGED
|
@@ -152,11 +152,54 @@ def format_references_for_prompt(context_graphs: list[ContextGraph]) -> str:
|
|
|
152
152
|
return "\n".join(parts)
|
|
153
153
|
|
|
154
154
|
|
|
155
|
+
def get_text_quality_section(language_name: str) -> str:
|
|
156
|
+
"""Retorna a seção de instruções para verificação de qualidade de texto.
|
|
157
|
+
|
|
158
|
+
Args:
|
|
159
|
+
language_name: Nome do idioma para verificação
|
|
160
|
+
|
|
161
|
+
Returns:
|
|
162
|
+
String com instruções de verificação de texto
|
|
163
|
+
"""
|
|
164
|
+
return f"""
|
|
165
|
+
## QUALIDADE DE TEXTO
|
|
166
|
+
|
|
167
|
+
Verifique ortografia e clareza semântica em mensagens voltadas ao usuário, no idioma **{language_name}**.
|
|
168
|
+
|
|
169
|
+
### O que verificar:
|
|
170
|
+
|
|
171
|
+
**Padrões de código:**
|
|
172
|
+
- `raise *Error("...")` e `raise *Exception("...")`
|
|
173
|
+
- `print("...")` e `console.log("...")`
|
|
174
|
+
- Parâmetros nomeados: `message=`, `label=`, `title=`, `description=`, `text=`
|
|
175
|
+
- Funções de UI: `flash("...")`, `toast("...")`, `alert("...")`
|
|
176
|
+
|
|
177
|
+
**Arquivos de i18n:**
|
|
178
|
+
- Arquivos em `locales/**/*`
|
|
179
|
+
- Arquivos em `i18n/**/*`
|
|
180
|
+
- Arquivos `messages.*` e `strings.*`
|
|
181
|
+
|
|
182
|
+
### O que ignorar:
|
|
183
|
+
|
|
184
|
+
- Identificadores: snake_case, camelCase, PascalCase
|
|
185
|
+
- Termos técnicos: HTTP, JSON, API, SQL, URL, etc.
|
|
186
|
+
- Nomes próprios e termos de domínio específico
|
|
187
|
+
- Chaves de configuração e variáveis de ambiente
|
|
188
|
+
|
|
189
|
+
### Formato dos findings:
|
|
190
|
+
|
|
191
|
+
- Categoria: `text-quality`
|
|
192
|
+
- Severidade: sempre `INFO`
|
|
193
|
+
- Inclua a correção sugerida no campo `suggestion`
|
|
194
|
+
"""
|
|
195
|
+
|
|
196
|
+
|
|
155
197
|
def build_prompt(
|
|
156
198
|
diff_files: list[DiffFile],
|
|
157
199
|
context_graphs: list[ContextGraph],
|
|
158
200
|
branch: str,
|
|
159
201
|
base: str,
|
|
202
|
+
text_quality: bool = False,
|
|
160
203
|
) -> str:
|
|
161
204
|
"""Monta o prompt completo para a IA.
|
|
162
205
|
|
|
@@ -165,6 +208,7 @@ def build_prompt(
|
|
|
165
208
|
context_graphs: Grafos de contexto com backtracking
|
|
166
209
|
branch: Nome da branch sendo analisada
|
|
167
210
|
base: Nome da branch base
|
|
211
|
+
text_quality: Se True, inclui verificação de ortografia e clareza
|
|
168
212
|
|
|
169
213
|
Returns:
|
|
170
214
|
Prompt completo pronto para enviar à IA
|
|
@@ -183,11 +227,15 @@ def build_prompt(
|
|
|
183
227
|
lang_code = get_language()
|
|
184
228
|
language_name = LANGUAGE_NAMES.get(lang_code, lang_code)
|
|
185
229
|
|
|
230
|
+
# Seção de text-quality (condicional)
|
|
231
|
+
text_quality_section = get_text_quality_section(language_name) if text_quality else ""
|
|
232
|
+
|
|
186
233
|
# Substitui placeholders
|
|
187
234
|
prompt = template.replace("{diff}", diff_section)
|
|
188
235
|
prompt = prompt.replace("{context}", context_section)
|
|
189
236
|
prompt = prompt.replace("{references}", references_section)
|
|
190
237
|
prompt = prompt.replace("{json_schema}", json_schema)
|
|
191
238
|
prompt = prompt.replace("{language}", language_name)
|
|
239
|
+
prompt = prompt.replace("{text_quality_section}", text_quality_section)
|
|
192
240
|
|
|
193
241
|
return prompt
|
|
@@ -25,7 +25,7 @@ O DIFF abaixo mostra APENAS as linhas alteradas, não o arquivo completo. Códig
|
|
|
25
25
|
- **Performance**: N+1 queries, loops desnecessários, operações O(n²), falta de índices, carregamento excessivo
|
|
26
26
|
- **Bugs potenciais**: null pointer, race conditions, off-by-one, divisão por zero, exceções não tratadas
|
|
27
27
|
- **Recursos não fechados**: conexões de banco, arquivos, sockets, locks não liberados
|
|
28
|
-
|
|
28
|
+
{text_quality_section}
|
|
29
29
|
## FORMATO DE SAÍDA
|
|
30
30
|
|
|
31
31
|
Retorne APENAS um JSON válido no formato abaixo. Não inclua explicações fora do JSON.
|
code_reviewer/response_parser.py
CHANGED
|
@@ -121,6 +121,11 @@ def normalize_category(value: str) -> Category:
|
|
|
121
121
|
"resource_leak": Category.RESOURCE_LEAK,
|
|
122
122
|
"leak": Category.RESOURCE_LEAK,
|
|
123
123
|
"memory": Category.RESOURCE_LEAK,
|
|
124
|
+
"text-quality": Category.TEXT_QUALITY,
|
|
125
|
+
"text_quality": Category.TEXT_QUALITY,
|
|
126
|
+
"spelling": Category.TEXT_QUALITY,
|
|
127
|
+
"grammar": Category.TEXT_QUALITY,
|
|
128
|
+
"typo": Category.TEXT_QUALITY,
|
|
124
129
|
}
|
|
125
130
|
|
|
126
131
|
return mapping.get(value_lower, Category.BUG)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|