snapcontext 2.1.0__tar.gz → 2.2.0__tar.gz

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 (38) hide show
  1. {snapcontext-2.1.0/snapcontext.egg-info → snapcontext-2.2.0}/PKG-INFO +14 -5
  2. {snapcontext-2.1.0 → snapcontext-2.2.0}/README.md +13 -4
  3. {snapcontext-2.1.0 → snapcontext-2.2.0}/agentes.py +165 -63
  4. {snapcontext-2.1.0 → snapcontext-2.2.0}/orquestador.py +3 -1
  5. {snapcontext-2.1.0 → snapcontext-2.2.0}/pyproject.toml +89 -89
  6. {snapcontext-2.1.0 → snapcontext-2.2.0/snapcontext.egg-info}/PKG-INFO +14 -5
  7. {snapcontext-2.1.0 → snapcontext-2.2.0}/snapcontext.egg-info/SOURCES.txt +1 -0
  8. {snapcontext-2.1.0 → snapcontext-2.2.0}/snapcontext.py +330 -5
  9. {snapcontext-2.1.0 → snapcontext-2.2.0}/tests/test_auto_017.py +1 -1
  10. {snapcontext-2.1.0 → snapcontext-2.2.0}/tests/test_diff_editor_210.py +1 -1
  11. snapcontext-2.2.0/tests/test_editor_ast_220.py +181 -0
  12. {snapcontext-2.1.0 → snapcontext-2.2.0}/tests/test_editor_propio_200.py +1 -1
  13. {snapcontext-2.1.0 → snapcontext-2.2.0}/tests/test_exe_150.py +1 -1
  14. {snapcontext-2.1.0 → snapcontext-2.2.0}/tests/test_jetbrains_170.py +2 -2
  15. {snapcontext-2.1.0 → snapcontext-2.2.0}/tests/test_mcp_014.py +1 -1
  16. {snapcontext-2.1.0 → snapcontext-2.2.0}/tests/test_mcp_140.py +1 -1
  17. {snapcontext-2.1.0 → snapcontext-2.2.0}/tests/test_memoria_015.py +1 -1
  18. {snapcontext-2.1.0 → snapcontext-2.2.0}/tests/test_permisos_013.py +1 -1
  19. {snapcontext-2.1.0 → snapcontext-2.2.0}/tests/test_plan_012.py +1 -1
  20. {snapcontext-2.1.0 → snapcontext-2.2.0}/tests/test_v010.py +1 -1
  21. {snapcontext-2.1.0 → snapcontext-2.2.0}/tests/test_validacion_130.py +1 -1
  22. {snapcontext-2.1.0 → snapcontext-2.2.0}/tests/test_vscode_016.py +2 -2
  23. {snapcontext-2.1.0 → snapcontext-2.2.0}/tests/test_web_160.py +1 -1
  24. {snapcontext-2.1.0 → snapcontext-2.2.0}/web/app.py +392 -392
  25. {snapcontext-2.1.0 → snapcontext-2.2.0}/LICENSE +0 -0
  26. {snapcontext-2.1.0 → snapcontext-2.2.0}/setup.cfg +0 -0
  27. {snapcontext-2.1.0 → snapcontext-2.2.0}/snapcontext.egg-info/__pycache__/top_level.cpython-313.pyc +0 -0
  28. {snapcontext-2.1.0 → snapcontext-2.2.0}/snapcontext.egg-info/dependency_links.txt +0 -0
  29. {snapcontext-2.1.0 → snapcontext-2.2.0}/snapcontext.egg-info/entry_points.txt +0 -0
  30. {snapcontext-2.1.0 → snapcontext-2.2.0}/snapcontext.egg-info/requires.txt +0 -0
  31. {snapcontext-2.1.0 → snapcontext-2.2.0}/snapcontext.egg-info/top_level.txt +0 -0
  32. {snapcontext-2.1.0 → snapcontext-2.2.0}/tests/test_agentes.py +0 -0
  33. {snapcontext-2.1.0 → snapcontext-2.2.0}/tests/test_deteccion.py +0 -0
  34. {snapcontext-2.1.0 → snapcontext-2.2.0}/tests/test_embeddings_110.py +0 -0
  35. {snapcontext-2.1.0 → snapcontext-2.2.0}/tests/test_orquestador.py +0 -0
  36. {snapcontext-2.1.0 → snapcontext-2.2.0}/tests/test_web_120.py +0 -0
  37. {snapcontext-2.1.0 → snapcontext-2.2.0}/web/__init__.py +0 -0
  38. {snapcontext-2.1.0 → snapcontext-2.2.0}/web/static/index.html +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: snapcontext
3
- Version: 2.1.0
3
+ Version: 2.2.0
4
4
  Summary: SnapContext: Asistente de IA con contexto automático para desarrollo
5
5
  Author-email: SnapContext Contributors <tu@email.com>
6
6
  License-Expression: MIT
@@ -104,12 +104,18 @@ snapcontext interactive # o snapcontext --web
104
104
  Auto-detección de proyecto (Flutter, Node/React, Python, Go, Rust…) que ajusta
105
105
  carpetas, extensiones y comandos de test por defecto.
106
106
 
107
- ## 🛠️ Editor Integrado Propio (v2.1.0)
107
+ ## 🛠️ Editor Integrado Propio (v2.2.0)
108
108
 
109
- SnapContext incluye su propio editor integrado con soporte de parches unificados:
109
+ SnapContext incluye su propio editor integrado con soporte de parches unificados
110
+ y edición basada en AST (Árbol Sintáctico) para refactorizaciones precisas:
110
111
  - **`--editor propio`**: Aplica cambios directamente y crea copias de seguridad automáticas en `~/.snapcontext/backups/`.
111
- - **`--modo-edicion {auto,parche,sobrescribir}`**:
112
- - `auto` (por defecto): Genera un parche unificado (`git apply` / `patch`) y hace fallback a sobrescritura si no es aplicable.
112
+ - **`--modo-edicion {auto,parche,sobrescribir,ast}`**:
113
+ - `auto` (por defecto): Genera un parche unificado (`git apply` / `patch`), pero
114
+ para refactorizaciones estructurales intenta primero la edición **AST** y cae a
115
+ sobrescritura si nada es aplicable.
116
+ - `ast`: Edita comprendiendo la estructura sintáctica del archivo (Python con
117
+ `ast`, otros lenguajes con `tree-sitter` si está instalado). Soporta renombrar
118
+ símbolos, insertar imports y recibir el código completo resultante.
113
119
  - `parche`: Fuerza la aplicación de parches unificados para ediciones precisas.
114
120
  - `sobrescribir`: Sobrescribe el archivo completo.
115
121
  - **`--editor aider`** (por defecto): Mantiene el flujo de edición con Aider para máxima compatibilidad.
@@ -120,6 +126,9 @@ snapcontext "añadir endpoint de métricas" --editor propio
120
126
 
121
127
  # Forzar modo parche
122
128
  snapcontext "corregir tipado en login" --editor propio --modo-edicion parche
129
+
130
+ # Refactorización estructural con AST
131
+ snapcontext "renombrar la variable 'usuario' a 'cuenta'" --editor propio --modo-edicion ast
123
132
  ```
124
133
 
125
134
  ## 🧭 Modos y alias
@@ -59,12 +59,18 @@ snapcontext interactive # o snapcontext --web
59
59
  Auto-detección de proyecto (Flutter, Node/React, Python, Go, Rust…) que ajusta
60
60
  carpetas, extensiones y comandos de test por defecto.
61
61
 
62
- ## 🛠️ Editor Integrado Propio (v2.1.0)
62
+ ## 🛠️ Editor Integrado Propio (v2.2.0)
63
63
 
64
- SnapContext incluye su propio editor integrado con soporte de parches unificados:
64
+ SnapContext incluye su propio editor integrado con soporte de parches unificados
65
+ y edición basada en AST (Árbol Sintáctico) para refactorizaciones precisas:
65
66
  - **`--editor propio`**: Aplica cambios directamente y crea copias de seguridad automáticas en `~/.snapcontext/backups/`.
66
- - **`--modo-edicion {auto,parche,sobrescribir}`**:
67
- - `auto` (por defecto): Genera un parche unificado (`git apply` / `patch`) y hace fallback a sobrescritura si no es aplicable.
67
+ - **`--modo-edicion {auto,parche,sobrescribir,ast}`**:
68
+ - `auto` (por defecto): Genera un parche unificado (`git apply` / `patch`), pero
69
+ para refactorizaciones estructurales intenta primero la edición **AST** y cae a
70
+ sobrescritura si nada es aplicable.
71
+ - `ast`: Edita comprendiendo la estructura sintáctica del archivo (Python con
72
+ `ast`, otros lenguajes con `tree-sitter` si está instalado). Soporta renombrar
73
+ símbolos, insertar imports y recibir el código completo resultante.
68
74
  - `parche`: Fuerza la aplicación de parches unificados para ediciones precisas.
69
75
  - `sobrescribir`: Sobrescribe el archivo completo.
70
76
  - **`--editor aider`** (por defecto): Mantiene el flujo de edición con Aider para máxima compatibilidad.
@@ -75,6 +81,9 @@ snapcontext "añadir endpoint de métricas" --editor propio
75
81
 
76
82
  # Forzar modo parche
77
83
  snapcontext "corregir tipado en login" --editor propio --modo-edicion parche
84
+
85
+ # Refactorización estructural con AST
86
+ snapcontext "renombrar la variable 'usuario' a 'cuenta'" --editor propio --modo-edicion ast
78
87
  ```
79
88
 
80
89
  ## 🧭 Modos y alias
@@ -21,6 +21,22 @@ logs de depuración visibles con ``--depurar`` (marcas ``[Agente…]``).
21
21
  import subprocess
22
22
  from typing import List, Optional, Union
23
23
 
24
+ def _tarea_estructura(tarea: str) -> bool:
25
+ """Heurística simple para `auto`: ¿la tarea parece una refactorización estructural?
26
+
27
+ Si es así, merece la pena intentar primero la edición basada en AST.
28
+ Se normalizan acentos para tolerar variaciones ("renombra"/"renombrar", etc.).
29
+ """
30
+ if not tarea:
31
+ return False
32
+ import unicodedata as _u
33
+
34
+ t = _u.normalize("NFD", tarea.lower())
35
+ t = "".join(c for c in t if not _u.combining(c))
36
+ claves = ("refactor", "renombra", "renombrar", "extra", "extraer",
37
+ "mueve", "mover", "inserta", "insertar", "nueva funcion",
38
+ "crear funcion", "funcion", "extraccion")
39
+ return any(k in t for k in claves)
24
40
 
25
41
  class AgenteContexto:
26
42
  """Agente de Contexto: selecciona los archivos relevantes para la consulta.
@@ -175,6 +191,91 @@ class AgenteEditorPropio:
175
191
  sc.depurar(f"[AgenteEditorPropio] Aplicando parche en '{directorio}'")
176
192
  return sc._aplicar_parche(parche, directorio=directorio)
177
193
 
194
+ def _cadena_modos(self, archivo: str, mensaje: str,
195
+ modo_edicion: str) -> List[str]:
196
+ """Devuelve la cadena de estrategias de edición a intentar para un archivo.
197
+
198
+ - 'sobrescribir' → solo sobrescritura.
199
+ - 'parche' → solo parche unificado (sin fallback).
200
+ - 'ast' → AST y, si falla, sobrescritura.
201
+ - 'auto' → AST (si el lenguaje lo permite y la tarea es estructural),
202
+ luego parche y, por último, sobrescritura.
203
+ """
204
+ import snapcontext as sc
205
+
206
+ if modo_edicion == "sobrescribir":
207
+ return ["sobrescribir"]
208
+ if modo_edicion == "parche":
209
+ return ["parche"]
210
+ if modo_edicion == "ast":
211
+ return ["ast", "sobrescribir"]
212
+ # auto: heurística simple según lenguaje y tarea
213
+ if sc._ast_disponible(archivo) and _tarea_estructura(mensaje):
214
+ return ["ast", "parche", "sobrescribir"]
215
+ return ["parche", "sobrescribir"]
216
+
217
+ def editar_ast(self, archivo: str, tarea: str,
218
+ directorio: str = ".", modelo: Optional[str] = None) -> bool:
219
+ """Edita ``archivo`` con base en su AST usando el proveedor de IA."""
220
+ import snapcontext as sc
221
+
222
+ pref = sc.cargar_configuracion()
223
+ proveedor = pref.get("provider") or sc.PROVEEDOR_DEFECTO
224
+ sc.depurar(f"[AgenteEditorPropio] Editando por AST '{archivo}' en '{directorio}'")
225
+ return sc._editor_ast(archivo, tarea, directorio=directorio,
226
+ proveedor=proveedor, modelo=modelo)
227
+
228
+ def _aplicar_modo_parche(self, archivo: str, mensaje: str,
229
+ contenido_actual: str, modelo: Optional[str],
230
+ directorio: str) -> bool:
231
+ """Intenta editar `archivo` pidiendo un parche unificado al proveedor."""
232
+ import snapcontext as sc
233
+
234
+ pref = sc.cargar_configuracion()
235
+ proveedor = pref.get("provider") or sc.PROVEEDOR_DEFECTO
236
+ prompt = (
237
+ f"Genera un parche unificado (unified diff) que modifique el archivo para cumplir con la tarea. "
238
+ f"El parche debe ser aplicable con 'patch -p1' o 'git apply' (encabezados --- a/{archivo} y +++ b/{archivo}).\n\n"
239
+ f"Tarea: {mensaje}\n"
240
+ f"Archivo: {archivo}\n\n"
241
+ f"Contenido actual:\n```\n{contenido_actual}\n```\n\n"
242
+ f"Devuelve ÚNICAMENTE el diff unificado, sin explicaciones ni rodeos."
243
+ )
244
+ respuesta = sc._enviar_al_proveedor(
245
+ proveedor, modelo, [{"role": "user", "content": prompt}])
246
+ diff_limpio = respuesta
247
+ if "--- " in diff_limpio and "+++ " in diff_limpio:
248
+ idx_inicio = diff_limpio.find("--- ")
249
+ diff_limpio = diff_limpio[idx_inicio:]
250
+ if "```" in diff_limpio:
251
+ diff_limpio = diff_limpio[:diff_limpio.find("```")]
252
+ if "--- " in diff_limpio and "+++ " in diff_limpio and "@@" in diff_limpio:
253
+ return self.aplicar_parche(diff_limpio, directorio)
254
+ return False
255
+
256
+ def _aplicar_modo_sobrescribir(self, archivo: str, mensaje: str,
257
+ contenido_actual: str, modelo: Optional[str],
258
+ directorio: str) -> bool:
259
+ """Sobrescribe `archivo` con el código completo que devuelve el proveedor."""
260
+ import snapcontext as sc
261
+
262
+ pref = sc.cargar_configuracion()
263
+ proveedor = pref.get("provider") or sc.PROVEEDOR_DEFECTO
264
+ prompt = (
265
+ f"Modifica el siguiente archivo para cumplir con la tarea.\n\n"
266
+ f"Tarea: {mensaje}\n"
267
+ f"Archivo: {archivo}\n\n"
268
+ f"Contenido actual:\n```\n{contenido_actual}\n```\n\n"
269
+ f"Devuelve ÚNICAMENTE el código completo resultante, sin explicaciones ni markdown."
270
+ )
271
+ nuevo_contenido = sc._enviar_al_proveedor(
272
+ proveedor, modelo, [{"role": "user", "content": prompt}])
273
+ if nuevo_contenido.startswith("```"):
274
+ lineas = nuevo_contenido.splitlines()
275
+ if len(lineas) >= 2 and lineas[-1].startswith("```"):
276
+ nuevo_contenido = "\n".join(lineas[1:-1])
277
+ return self.sobrescribir(archivo, nuevo_contenido, directorio)
278
+
178
279
  def ejecutar(
179
280
  self,
180
281
  archivos: List[str],
@@ -187,14 +288,13 @@ class AgenteEditorPropio:
187
288
 
188
289
  - modo_edicion == 'parche': intenta aplicar parche unificado (falla si no puede).
189
290
  - modo_edicion == 'sobrescribir': aplica directamente sobrescritura de archivo.
190
- - modo_edicion == 'auto': intenta primero parche unificado; si falla o no es diff,
191
- hace fallback a sobrescritura.
291
+ - modo_edicion == 'ast': edita con base en el AST y cae a sobrescritura si falla.
292
+ - modo_edicion == 'auto': decide por heurística (AST para refactorizaciones,
293
+ parche, y fallback a sobrescritura).
192
294
  """
193
295
  import snapcontext as sc
194
296
  from pathlib import Path
195
297
 
196
- pref = sc.cargar_configuracion()
197
- proveedor = pref.get("provider") or sc.PROVEEDOR_DEFECTO
198
298
  raiz = Path(directorio).resolve()
199
299
  todo_ok = True
200
300
 
@@ -203,75 +303,77 @@ class AgenteEditorPropio:
203
303
  contenido_actual = ""
204
304
  if camino.is_file():
205
305
  try:
206
- contenido_actual = camino.read_text(encoding="utf-8", errors="replace")
306
+ contenido_actual = camino.read_text(encoding="utf-8",
307
+ errors="replace")
207
308
  except Exception:
208
309
  pass
209
310
 
210
- if modo_edicion in ("parche", "auto"):
211
- prompt = (
212
- f"Genera un parche unificado (unified diff) que modifique el archivo para cumplir con la tarea. "
213
- f"El parche debe ser aplicable con 'patch -p1' o 'git apply' (encabezados --- a/{arch} y +++ b/{arch}).\n\n"
214
- f"Tarea: {mensaje}\n"
215
- f"Archivo: {arch}\n\n"
216
- f"Contenido actual:\n```\n{contenido_actual}\n```\n\n"
217
- f"Devuelve ÚNICAMENTE el diff unificado, sin explicaciones ni rodeos."
218
- )
311
+ cadena = self._cadena_modos(arch, mensaje, modo_edicion)
312
+ conseguido = False
313
+ for estrategia in cadena:
219
314
  try:
220
- respuesta = sc._enviar_al_proveedor(
221
- proveedor, modelo,
222
- [{"role": "user", "content": prompt}]
223
- )
224
- # Limpiar delimitadores markdown si vinieron
225
- diff_limpio = respuesta
226
- if "--- " in diff_limpio and "+++ " in diff_limpio:
227
- # Extraer solo desde ---
228
- idx_inicio = diff_limpio.find("--- ")
229
- diff_limpio = diff_limpio[idx_inicio:]
230
- if "```" in diff_limpio:
231
- diff_limpio = diff_limpio[:diff_limpio.find("```")]
232
-
233
- # Si parece un diff unificado válido, intentar aplicarlo
234
- if ("--- " in diff_limpio and "+++ " in diff_limpio and "@@" in diff_limpio):
235
- if self.aplicar_parche(diff_limpio, str(raiz)):
236
- continue
237
- sc.aviso(f"[AgenteEditorPropio] Parche para '{arch}' falló al aplicarse.")
238
- if modo_edicion == "parche":
239
- todo_ok = False
240
- continue
315
+ if estrategia == "ast":
316
+ conseguido = self.editar_ast(arch, mensaje,
317
+ str(raiz), modelo)
318
+ elif estrategia == "parche":
319
+ conseguido = self._aplicar_modo_parche(
320
+ arch, mensaje, contenido_actual, modelo, str(raiz))
321
+ elif estrategia == "sobrescribir":
322
+ conseguido = self._aplicar_modo_sobrescribir(
323
+ arch, mensaje, contenido_actual, modelo, str(raiz))
324
+ else:
325
+ conseguido = False
241
326
  except Exception as exc:
242
- sc.depurar(f"[AgenteEditorPropio] Error pidiendo parche para '{arch}': {exc}")
243
- if modo_edicion == "parche":
244
- sc.error(f"Error generando parche para {arch}: {exc}")
245
- todo_ok = False
246
- continue
247
-
248
- # Fallback o modo sobrescribir
249
- sc.depurar(f"[AgenteEditorPropio] Aplicando edición por sobrescritura para '{arch}'...")
250
- prompt_sobrescribir = (
251
- f"Modifica el siguiente archivo para cumplir con la tarea.\n\n"
252
- f"Tarea: {mensaje}\n"
253
- f"Archivo: {arch}\n\n"
254
- f"Contenido actual:\n```\n{contenido_actual}\n```\n\n"
255
- f"Devuelve ÚNICAMENTE el código completo resultante, sin explicaciones ni markdown."
256
- )
257
- try:
258
- nuevo_contenido = sc._enviar_al_proveedor(
259
- proveedor, modelo,
260
- [{"role": "user", "content": prompt_sobrescribir}]
261
- )
262
- if nuevo_contenido.startswith("```"):
263
- lineas = nuevo_contenido.splitlines()
264
- if len(lineas) >= 2 and lineas[-1].startswith("```"):
265
- nuevo_contenido = "\n".join(lineas[1:-1])
266
- if not self.sobrescribir(arch, nuevo_contenido, str(raiz)):
267
- todo_ok = False
268
- except Exception as exc:
269
- sc.error(f"Error generando cambios por sobrescritura para {arch}: {exc}")
327
+ sc.depurar(
328
+ f"[AgenteEditorPropio] {estrategia} falló para '{arch}': {exc}")
329
+ conseguido = False
330
+ if conseguido:
331
+ break
332
+ if not conseguido:
333
+ sc.error(f"[AgenteEditorPropio] No se pudo editar '{arch}'.")
270
334
  todo_ok = False
271
335
 
272
336
  return todo_ok
273
337
 
274
338
 
339
+ class AgenteEditorAST:
340
+ """Agente Editor AST (Fase 3): ediciones precisas basadas en árbol sintáctico.
341
+
342
+ Trabaja directamente con el AST del archivo (Python con ``ast``; otros
343
+ lenguajes con ``tree-sitter`` si está instalado) pidiendo al proveedor
344
+ operaciones de modificación del árbol o el código completo resultante.
345
+ """
346
+
347
+ def editar(
348
+ self,
349
+ archivos: List[str],
350
+ mensaje: str,
351
+ directorio: str = ".",
352
+ modelo: Optional[str] = None,
353
+ ) -> bool:
354
+ """Aplica a cada archivo una edición guiada por AST. Devuelve bool."""
355
+ todo = True
356
+ for archivo in archivos:
357
+ if not self.editar_archivo(archivo, mensaje,
358
+ directorio=directorio, modelo=modelo):
359
+ todo = False
360
+ return todo
361
+
362
+ def editar_archivo(
363
+ self,
364
+ archivo: str,
365
+ tarea: str,
366
+ directorio: str = ".",
367
+ modelo: Optional[str] = None,
368
+ ) -> bool:
369
+ """Edita un único archivo con AST. Devuelve ``True`` si tuvo éxito."""
370
+ import snapcontext as sc
371
+
372
+ pref = sc.cargar_configuracion()
373
+ proveedor = pref.get("provider") or sc.PROVEEDOR_DEFECTO
374
+ sc.depurar(f"[AgenteEditorAST] AST sobre '{archivo}' en '{directorio}'")
375
+ return sc._editor_ast(archivo, tarea, directorio=directorio,
376
+ proveedor=proveedor, modelo=modelo)
275
377
 
276
378
 
277
379
  class AgenteTester:
@@ -20,7 +20,8 @@ import shlex
20
20
  import sys
21
21
  from typing import List, Optional, Tuple
22
22
 
23
- from agentes import AgenteContexto, AgenteEditor, AgenteEditorPropio, AgenteTester
23
+ from agentes import (AgenteContexto, AgenteEditor, AgenteEditorAST,
24
+ AgenteEditorPropio, AgenteTester)
24
25
 
25
26
  # Centinela diferenciado del None de "aborto": _planificar lo devuelve cuando
26
27
  # el pipeline termina de forma exitosa y temprana (p. ej. --vista-previa).
@@ -40,6 +41,7 @@ class Orquestador:
40
41
  self.agente_contexto = AgenteContexto()
41
42
  self.agente_editor = AgenteEditor()
42
43
  self.agente_editor_propio = AgenteEditorPropio()
44
+ self.agente_editor_ast = AgenteEditorAST()
43
45
  self.agente_tester = AgenteTester()
44
46
  self.evento_callback = evento_callback
45
47
 
@@ -1,90 +1,90 @@
1
- [build-system]
2
- requires = ["setuptools>=77"]
3
- build-backend = "setuptools.build_meta"
4
-
5
- [project]
6
- # Nombre verificado disponible en PyPI (18/08/2026): pypi.org/pypi/snapcontext → 404.
7
- # Alternativas si algún día estuviera ocupado: "snapcontext-cli" o "snapcontext-tool".
8
- name = "snapcontext"
9
- version = "2.1.0"
10
- description = "SnapContext: Asistente de IA con contexto automático para desarrollo"
11
- readme = "README.md"
12
- requires-python = ">=3.9"
13
- # PEP 639: licencia SPDX + fichero de licencia incluido en el paquete.
14
- license = "MIT"
15
- license-files = ["LICENSE"]
16
- authors = [
17
- # TODO: cambia por tu nombre y correo reales antes de publicar.
18
- { name = "SnapContext Contributors", email = "tu@email.com" },
19
- ]
20
- keywords = [
21
- "ai", "aider", "gemini", "ollama", "deepseek", "groq", "claude", "anthropic",
22
- "flutter", "supabase", "cli",
23
- ]
24
- classifiers = [
25
- "Development Status :: 5 - Production/Stable",
26
- "Environment :: Console",
27
- "Intended Audience :: Developers",
28
- "Operating System :: OS Independent",
29
- "Programming Language :: Python :: 3",
30
- "Programming Language :: Python :: 3.9",
31
- "Programming Language :: Python :: 3.10",
32
- "Programming Language :: Python :: 3.11",
33
- "Programming Language :: Python :: 3.12",
34
- "Programming Language :: Python :: 3.13",
35
- "Topic :: Software Development :: Code Generators",
36
- ]
37
- dependencies = [
38
- "google-generativeai>=0.8.3",
39
- "openai>=1.30.0",
40
- ]
41
-
42
- [project.optional-dependencies]
43
- dev = [
44
- "aider-chat>=0.67.0",
45
- "build>=1.2.0",
46
- "twine>=5.0.0",
47
- ]
48
- # Menú interactivo de selección de proveedor (--provider y --local omitidos).
49
- interactive = [
50
- "questionary>=1.10.0",
51
- ]
52
- # Claude (Anthropic) como proveedor de IA (--provider anthropic, --chat).
53
- anthropic = [
54
- "anthropic>=0.30.0",
55
- ]
56
- # Interfaz web (FastAPI + WebSockets) con --web.
57
- web = [
58
- "fastapi>=0.110.0",
59
- "uvicorn[standard]>=0.29.0",
60
- ]
61
- # Búsqueda semántica local con embeddings (--search, pre-filtro del planificador).
62
- embeddings = [
63
- "sentence-transformers>=3.0.0",
64
- "torch>=2.0.0",
65
- ]
66
- # MCP avanzado (v1.4.0): análisis sintáctico multi-lenguaje con tree-sitter
67
- # (herramienta `ast_avanzado`). Sin él, cae a `ast` de la stdlib (solo Python).
68
- mcp_avanzado = [
69
- "tree-sitter>=0.20.0",
70
- "tree-sitter-languages>=1.10.0",
71
- ]
72
-
73
- [project.urls]
74
- # TODO: apunta a tu repositorio real (no bloquea la publicación si lo dejas).
75
- Homepage = "https://github.com/NicolasBruna24/snapcontext"
76
- Repository = "https://github.com/NicolasBruna24/snapcontext"
77
- "Bug Tracker" = "https://github.com/NicolasBruna24/snapcontext/issues"
78
-
79
- # Entry point: expone el comando `snapcontext` que llama a main().
80
- [project.scripts]
81
- snapcontext = "snapcontext:main"
82
-
83
- [tool.setuptools]
84
- # Módulos en la raíz (sin paquete): CLI + arquitectura de agentes.
85
- py-modules = ["snapcontext", "agentes", "orquestador"]
86
- packages = ["web"]
87
-
88
- [tool.setuptools.package-data]
89
- # El estático de la interfaz web debe viajar dentro del paquete instalado.
1
+ [build-system]
2
+ requires = ["setuptools>=77"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ # Nombre verificado disponible en PyPI (18/08/2026): pypi.org/pypi/snapcontext → 404.
7
+ # Alternativas si algún día estuviera ocupado: "snapcontext-cli" o "snapcontext-tool".
8
+ name = "snapcontext"
9
+ version = "2.2.0"
10
+ description = "SnapContext: Asistente de IA con contexto automático para desarrollo"
11
+ readme = "README.md"
12
+ requires-python = ">=3.9"
13
+ # PEP 639: licencia SPDX + fichero de licencia incluido en el paquete.
14
+ license = "MIT"
15
+ license-files = ["LICENSE"]
16
+ authors = [
17
+ # TODO: cambia por tu nombre y correo reales antes de publicar.
18
+ { name = "SnapContext Contributors", email = "tu@email.com" },
19
+ ]
20
+ keywords = [
21
+ "ai", "aider", "gemini", "ollama", "deepseek", "groq", "claude", "anthropic",
22
+ "flutter", "supabase", "cli",
23
+ ]
24
+ classifiers = [
25
+ "Development Status :: 5 - Production/Stable",
26
+ "Environment :: Console",
27
+ "Intended Audience :: Developers",
28
+ "Operating System :: OS Independent",
29
+ "Programming Language :: Python :: 3",
30
+ "Programming Language :: Python :: 3.9",
31
+ "Programming Language :: Python :: 3.10",
32
+ "Programming Language :: Python :: 3.11",
33
+ "Programming Language :: Python :: 3.12",
34
+ "Programming Language :: Python :: 3.13",
35
+ "Topic :: Software Development :: Code Generators",
36
+ ]
37
+ dependencies = [
38
+ "google-generativeai>=0.8.3",
39
+ "openai>=1.30.0",
40
+ ]
41
+
42
+ [project.optional-dependencies]
43
+ dev = [
44
+ "aider-chat>=0.67.0",
45
+ "build>=1.2.0",
46
+ "twine>=5.0.0",
47
+ ]
48
+ # Menú interactivo de selección de proveedor (--provider y --local omitidos).
49
+ interactive = [
50
+ "questionary>=1.10.0",
51
+ ]
52
+ # Claude (Anthropic) como proveedor de IA (--provider anthropic, --chat).
53
+ anthropic = [
54
+ "anthropic>=0.30.0",
55
+ ]
56
+ # Interfaz web (FastAPI + WebSockets) con --web.
57
+ web = [
58
+ "fastapi>=0.110.0",
59
+ "uvicorn[standard]>=0.29.0",
60
+ ]
61
+ # Búsqueda semántica local con embeddings (--search, pre-filtro del planificador).
62
+ embeddings = [
63
+ "sentence-transformers>=3.0.0",
64
+ "torch>=2.0.0",
65
+ ]
66
+ # MCP avanzado (v1.4.0): análisis sintáctico multi-lenguaje con tree-sitter
67
+ # (herramienta `ast_avanzado`). Sin él, cae a `ast` de la stdlib (solo Python).
68
+ mcp_avanzado = [
69
+ "tree-sitter>=0.20.0",
70
+ "tree-sitter-languages>=1.10.0",
71
+ ]
72
+
73
+ [project.urls]
74
+ # TODO: apunta a tu repositorio real (no bloquea la publicación si lo dejas).
75
+ Homepage = "https://github.com/NicolasBruna24/snapcontext"
76
+ Repository = "https://github.com/NicolasBruna24/snapcontext"
77
+ "Bug Tracker" = "https://github.com/NicolasBruna24/snapcontext/issues"
78
+
79
+ # Entry point: expone el comando `snapcontext` que llama a main().
80
+ [project.scripts]
81
+ snapcontext = "snapcontext:main"
82
+
83
+ [tool.setuptools]
84
+ # Módulos en la raíz (sin paquete): CLI + arquitectura de agentes.
85
+ py-modules = ["snapcontext", "agentes", "orquestador"]
86
+ packages = ["web"]
87
+
88
+ [tool.setuptools.package-data]
89
+ # El estático de la interfaz web debe viajar dentro del paquete instalado.
90
90
  "web" = ["static/index.html"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: snapcontext
3
- Version: 2.1.0
3
+ Version: 2.2.0
4
4
  Summary: SnapContext: Asistente de IA con contexto automático para desarrollo
5
5
  Author-email: SnapContext Contributors <tu@email.com>
6
6
  License-Expression: MIT
@@ -104,12 +104,18 @@ snapcontext interactive # o snapcontext --web
104
104
  Auto-detección de proyecto (Flutter, Node/React, Python, Go, Rust…) que ajusta
105
105
  carpetas, extensiones y comandos de test por defecto.
106
106
 
107
- ## 🛠️ Editor Integrado Propio (v2.1.0)
107
+ ## 🛠️ Editor Integrado Propio (v2.2.0)
108
108
 
109
- SnapContext incluye su propio editor integrado con soporte de parches unificados:
109
+ SnapContext incluye su propio editor integrado con soporte de parches unificados
110
+ y edición basada en AST (Árbol Sintáctico) para refactorizaciones precisas:
110
111
  - **`--editor propio`**: Aplica cambios directamente y crea copias de seguridad automáticas en `~/.snapcontext/backups/`.
111
- - **`--modo-edicion {auto,parche,sobrescribir}`**:
112
- - `auto` (por defecto): Genera un parche unificado (`git apply` / `patch`) y hace fallback a sobrescritura si no es aplicable.
112
+ - **`--modo-edicion {auto,parche,sobrescribir,ast}`**:
113
+ - `auto` (por defecto): Genera un parche unificado (`git apply` / `patch`), pero
114
+ para refactorizaciones estructurales intenta primero la edición **AST** y cae a
115
+ sobrescritura si nada es aplicable.
116
+ - `ast`: Edita comprendiendo la estructura sintáctica del archivo (Python con
117
+ `ast`, otros lenguajes con `tree-sitter` si está instalado). Soporta renombrar
118
+ símbolos, insertar imports y recibir el código completo resultante.
113
119
  - `parche`: Fuerza la aplicación de parches unificados para ediciones precisas.
114
120
  - `sobrescribir`: Sobrescribe el archivo completo.
115
121
  - **`--editor aider`** (por defecto): Mantiene el flujo de edición con Aider para máxima compatibilidad.
@@ -120,6 +126,9 @@ snapcontext "añadir endpoint de métricas" --editor propio
120
126
 
121
127
  # Forzar modo parche
122
128
  snapcontext "corregir tipado en login" --editor propio --modo-edicion parche
129
+
130
+ # Refactorización estructural con AST
131
+ snapcontext "renombrar la variable 'usuario' a 'cuenta'" --editor propio --modo-edicion ast
123
132
  ```
124
133
 
125
134
  ## 🧭 Modos y alias
@@ -15,6 +15,7 @@ tests/test_agentes.py
15
15
  tests/test_auto_017.py
16
16
  tests/test_deteccion.py
17
17
  tests/test_diff_editor_210.py
18
+ tests/test_editor_ast_220.py
18
19
  tests/test_editor_propio_200.py
19
20
  tests/test_embeddings_110.py
20
21
  tests/test_exe_150.py