snapcontext 2.2.0__tar.gz → 3.0.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.
- {snapcontext-2.2.0/snapcontext.egg-info → snapcontext-3.0.0}/PKG-INFO +90 -4
- {snapcontext-2.2.0 → snapcontext-3.0.0}/README.md +89 -3
- {snapcontext-2.2.0 → snapcontext-3.0.0}/agentes.py +73 -1
- {snapcontext-2.2.0 → snapcontext-3.0.0}/orquestador.py +13 -1
- {snapcontext-2.2.0 → snapcontext-3.0.0}/pyproject.toml +3 -1
- {snapcontext-2.2.0 → snapcontext-3.0.0/snapcontext.egg-info}/PKG-INFO +90 -4
- {snapcontext-2.2.0 → snapcontext-3.0.0}/snapcontext.egg-info/SOURCES.txt +2 -0
- {snapcontext-2.2.0 → snapcontext-3.0.0}/snapcontext.py +1011 -27
- {snapcontext-2.2.0 → snapcontext-3.0.0}/tests/test_auto_017.py +190 -190
- {snapcontext-2.2.0 → snapcontext-3.0.0}/tests/test_diff_editor_210.py +103 -103
- {snapcontext-2.2.0 → snapcontext-3.0.0}/tests/test_editor_ast_220.py +1 -1
- {snapcontext-2.2.0 → snapcontext-3.0.0}/tests/test_editor_propio_200.py +91 -91
- {snapcontext-2.2.0 → snapcontext-3.0.0}/tests/test_exe_150.py +72 -72
- {snapcontext-2.2.0 → snapcontext-3.0.0}/tests/test_jetbrains_170.py +115 -115
- {snapcontext-2.2.0 → snapcontext-3.0.0}/tests/test_mcp_014.py +225 -225
- {snapcontext-2.2.0 → snapcontext-3.0.0}/tests/test_mcp_140.py +255 -255
- {snapcontext-2.2.0 → snapcontext-3.0.0}/tests/test_memoria_015.py +186 -186
- snapcontext-3.0.0/tests/test_memoria_300.py +319 -0
- {snapcontext-2.2.0 → snapcontext-3.0.0}/tests/test_permisos_013.py +190 -190
- {snapcontext-2.2.0 → snapcontext-3.0.0}/tests/test_plan_012.py +279 -279
- snapcontext-3.0.0/tests/test_plan_mcp_230.py +223 -0
- {snapcontext-2.2.0 → snapcontext-3.0.0}/tests/test_v010.py +248 -248
- {snapcontext-2.2.0 → snapcontext-3.0.0}/tests/test_validacion_130.py +133 -133
- {snapcontext-2.2.0 → snapcontext-3.0.0}/tests/test_vscode_016.py +94 -94
- {snapcontext-2.2.0 → snapcontext-3.0.0}/tests/test_web_160.py +95 -95
- {snapcontext-2.2.0 → snapcontext-3.0.0}/LICENSE +0 -0
- {snapcontext-2.2.0 → snapcontext-3.0.0}/setup.cfg +0 -0
- {snapcontext-2.2.0 → snapcontext-3.0.0}/snapcontext.egg-info/__pycache__/top_level.cpython-313.pyc +0 -0
- {snapcontext-2.2.0 → snapcontext-3.0.0}/snapcontext.egg-info/dependency_links.txt +0 -0
- {snapcontext-2.2.0 → snapcontext-3.0.0}/snapcontext.egg-info/entry_points.txt +0 -0
- {snapcontext-2.2.0 → snapcontext-3.0.0}/snapcontext.egg-info/requires.txt +0 -0
- {snapcontext-2.2.0 → snapcontext-3.0.0}/snapcontext.egg-info/top_level.txt +0 -0
- {snapcontext-2.2.0 → snapcontext-3.0.0}/tests/test_agentes.py +0 -0
- {snapcontext-2.2.0 → snapcontext-3.0.0}/tests/test_deteccion.py +0 -0
- {snapcontext-2.2.0 → snapcontext-3.0.0}/tests/test_embeddings_110.py +0 -0
- {snapcontext-2.2.0 → snapcontext-3.0.0}/tests/test_orquestador.py +0 -0
- {snapcontext-2.2.0 → snapcontext-3.0.0}/tests/test_web_120.py +0 -0
- {snapcontext-2.2.0 → snapcontext-3.0.0}/web/__init__.py +0 -0
- {snapcontext-2.2.0 → snapcontext-3.0.0}/web/app.py +0 -0
- {snapcontext-2.2.0 → snapcontext-3.0.0}/web/static/index.html +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: snapcontext
|
|
3
|
-
Version:
|
|
3
|
+
Version: 3.0.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
|
|
@@ -275,7 +275,7 @@ snapcontext --plan "tarea" --no-confirmar
|
|
|
275
275
|
|
|
276
276
|
1. El proveedor de IA descompone la tarea en pasos JSON:
|
|
277
277
|
```json
|
|
278
|
-
{"descripcion": "...", "accion": "editar|ejecutar|consultar",
|
|
278
|
+
{"descripcion": "...", "accion": "editar|ejecutar|consultar|mcp",
|
|
279
279
|
"archivos": ["..."], "comando": "...",
|
|
280
280
|
"dependencias": [1, 2],
|
|
281
281
|
"condicion": "archivo_existe('src/main.py')"}
|
|
@@ -283,7 +283,8 @@ snapcontext --plan "tarea" --no-confirmar
|
|
|
283
283
|
2. Los pasos se muestran numerados y se pide confirmación.
|
|
284
284
|
3. Cada paso se ejecuta secuencialmente: **editar** usa el pipeline completo
|
|
285
285
|
(`_planificar` + `_bucle_test`), **ejecutar** lanza comandos shell,
|
|
286
|
-
**consultar** pregunta al proveedor.
|
|
286
|
+
**consultar** pregunta al proveedor y **mcp** (v2.3.0) ejecuta una
|
|
287
|
+
herramienta MCP guardando su resultado en el contexto del plan.
|
|
287
288
|
4. Tras cada paso eliges: continuar / reintentar / saltar / abortar. Al final
|
|
288
289
|
hay un resumen que se guarda en `historial.json`.
|
|
289
290
|
|
|
@@ -296,10 +297,95 @@ snapcontext --plan "tarea" --no-confirmar
|
|
|
296
297
|
- `archivo_existe('src/main.py')`
|
|
297
298
|
- `archivo_contiene('src/main.py', 'def main')`
|
|
298
299
|
- `comando_exito('flutter test')`
|
|
300
|
+
- `variable_existe('mi_variable')` *(v2.3.0)*
|
|
301
|
+
|
|
302
|
+
Además, desde v2.3.0 acepta **comparaciones dinámicas** con resultados
|
|
303
|
+
de pasos previos o variables dejadas en el contexto (por pasos `mcp`):
|
|
304
|
+
|
|
305
|
+
```json
|
|
306
|
+
{"condicion": "pasos[0].resultado == 'ok'"}
|
|
307
|
+
{"condicion": "resultados.mi_variable != ''"}
|
|
308
|
+
```
|
|
299
309
|
|
|
300
310
|
Si la condición es falsa, el paso se salta (con aviso) y el plan continúa.
|
|
311
|
+
### Pasos MCP y contexto dinámico (v2.3.0)
|
|
312
|
+
|
|
313
|
+
Un paso con `"accion": "mcp"` ejecuta una herramienta MCP del registro
|
|
314
|
+
(`grep`, `read_file`, `list_files`, `ast`, `git_status`, `git_diff`,
|
|
315
|
+
`execute_command`, ...) usando los campos `"herramienta"` y `"args"`.
|
|
316
|
+
El resultado queda disponible para los pasos posteriores:
|
|
317
|
+
|
|
318
|
+
```json
|
|
319
|
+
{"descripcion": "buscar referencias", "accion": "mcp",
|
|
320
|
+
"herramienta": "grep", "args": {"patron": "def main"},
|
|
321
|
+
"variable": "coincidencias"}
|
|
322
|
+
{"descripcion": "usar resultado", "accion": "ejecutar",
|
|
323
|
+
"comando": "echo {{coincidencias}}"}
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
- El resultado siempre se guarda también como `{{resultado}}`; si el paso
|
|
327
|
+
define `"variable"`, se guarda bajo ese nombre.
|
|
328
|
+
- `execute_command` soporta `background=true` (devuelve un `pid`
|
|
329
|
+
consultable con `execute_command_status`) y `capture_output=false` para
|
|
330
|
+
mostrar la salida en tiempo real.
|
|
331
|
+
|
|
332
|
+
## 🧠 Aprendizaje autónomo: memoria SQLite, skills y curador (v3.0.0)
|
|
333
|
+
|
|
334
|
+
SnapContext ya no solo ejecuta tareas: **aprende de ellas**. Toda la
|
|
335
|
+
memoria avanzada vive en una base de datos SQLite (`~/.snapcontext/memoria.db`; sin dependencias externas: `sqlite3` viene con Python).
|
|
336
|
+
|
|
337
|
+
### Skills: procedimientos reutilizables
|
|
338
|
+
|
|
339
|
+
- Al terminar una tarea con `--plan` **con éxito**, SnapContext extrae
|
|
340
|
+
los pasos clave y guarda un *skill* (procedimiento reutilizable) en
|
|
341
|
+
la tabla `skills`, junto a su contexto (archivos, comandos) y
|
|
342
|
+
metadatos (fecha, usos, fallos, confiabilidad).
|
|
343
|
+
- Cuando repites una tarea similar, busca el skill más parecido con
|
|
344
|
+
similitud semántica (embeddings; fallback Jaccard/contención sin
|
|
345
|
+
dependencias) y lo reutiliza como punto de partida.
|
|
346
|
+
- Si el skill falla, se penaliza y queda marcado para revisión; si
|
|
347
|
+
tiene éxito repetidamente (3+ usos sin fallos) se marca como
|
|
348
|
+
**confiable** y se prioriza.
|
|
349
|
+
|
|
350
|
+
Comandos útiles:
|
|
351
|
+
|
|
352
|
+
```bash
|
|
353
|
+
snapcontext --skills # lista los skills aprendidos
|
|
354
|
+
snapcontext --curador # ejecuta una pasada del curador
|
|
355
|
+
snapcontext --daemon # daemon: curador + cola de skills
|
|
356
|
+
snapcontext --daemon-intervalo 24 # curador cada 24 h
|
|
357
|
+
snapcontext --plan "..." --sin-aprendizaje # desactiva el aprendizaje
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
Ejemplo de aprendizaje:
|
|
361
|
+
|
|
362
|
+
```bash
|
|
363
|
+
snapcontext --plan "migrar pagos a stripe" --auto --no-confirmar
|
|
364
|
+
# → al terminar (código 0): '[aprendizaje] Nuevo skill guardado:
|
|
365
|
+
# migrar-pagos-a-stripe'
|
|
366
|
+
snapcontext --plan "migrar pagos a stripe ya" --auto --no-confirmar
|
|
367
|
+
# → reutiliza y refuerza el skill existente (sube su confiabilidad)
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### Curador autónomo
|
|
371
|
+
|
|
372
|
+
- Archiva skills sin uso durante más de 30 días.
|
|
373
|
+
- Fusiona skills casi idénticos (similitud ≥ 0.90), conservando el más
|
|
374
|
+
usado y sumando sus estadísticas.
|
|
375
|
+
- Notifica por CLI los skills con baja confiabilidad (< 0.4).
|
|
376
|
+
- Se ejecuta manualmente (`--curador`) o periódicamente vía daemon.
|
|
377
|
+
|
|
378
|
+
### Daemon (`--daemon`)
|
|
379
|
+
|
|
380
|
+
Proceso en segundo plano que cada minuto sondea la memoria: ejecuta el
|
|
381
|
+
curador cuando vence el intervalo configurado (`--daemon-intervalo`,
|
|
382
|
+
168 h por defecto = semanal) y procesa la cola de skills pendientes
|
|
383
|
+
(tabla `cola`) para ejecutarlos sin intervención. La CLI y el chat
|
|
384
|
+
encolan skills con `_cola_encolar()`; el agente `AgenteAprendizaje`
|
|
385
|
+
(en `agentes.py`) expone toda esta memoria al orquestador.
|
|
386
|
+
|
|
301
387
|
- **Paralelismo**: con `--paralelo N` (junto a `--auto`) se ejecutan hasta N
|
|
302
|
-
pasos independientes a la vez; los logs llevan el identificador `[paso N]
|
|
388
|
+
pasos independientes a la vez; los logs llevan el identificador `[paso N]`. Desde v2.3.0 el planificador también respeta las dependencias dinámicas: un paso cuya condición usa una variable que otro paso aún no ha producido espera a que esté disponible:
|
|
303
389
|
|
|
304
390
|
```bash
|
|
305
391
|
snapcontext --plan "tarea grande" --auto --paralelo 3 --no-confirmar
|
|
@@ -230,7 +230,7 @@ snapcontext --plan "tarea" --no-confirmar
|
|
|
230
230
|
|
|
231
231
|
1. El proveedor de IA descompone la tarea en pasos JSON:
|
|
232
232
|
```json
|
|
233
|
-
{"descripcion": "...", "accion": "editar|ejecutar|consultar",
|
|
233
|
+
{"descripcion": "...", "accion": "editar|ejecutar|consultar|mcp",
|
|
234
234
|
"archivos": ["..."], "comando": "...",
|
|
235
235
|
"dependencias": [1, 2],
|
|
236
236
|
"condicion": "archivo_existe('src/main.py')"}
|
|
@@ -238,7 +238,8 @@ snapcontext --plan "tarea" --no-confirmar
|
|
|
238
238
|
2. Los pasos se muestran numerados y se pide confirmación.
|
|
239
239
|
3. Cada paso se ejecuta secuencialmente: **editar** usa el pipeline completo
|
|
240
240
|
(`_planificar` + `_bucle_test`), **ejecutar** lanza comandos shell,
|
|
241
|
-
**consultar** pregunta al proveedor.
|
|
241
|
+
**consultar** pregunta al proveedor y **mcp** (v2.3.0) ejecuta una
|
|
242
|
+
herramienta MCP guardando su resultado en el contexto del plan.
|
|
242
243
|
4. Tras cada paso eliges: continuar / reintentar / saltar / abortar. Al final
|
|
243
244
|
hay un resumen que se guarda en `historial.json`.
|
|
244
245
|
|
|
@@ -251,10 +252,95 @@ snapcontext --plan "tarea" --no-confirmar
|
|
|
251
252
|
- `archivo_existe('src/main.py')`
|
|
252
253
|
- `archivo_contiene('src/main.py', 'def main')`
|
|
253
254
|
- `comando_exito('flutter test')`
|
|
255
|
+
- `variable_existe('mi_variable')` *(v2.3.0)*
|
|
256
|
+
|
|
257
|
+
Además, desde v2.3.0 acepta **comparaciones dinámicas** con resultados
|
|
258
|
+
de pasos previos o variables dejadas en el contexto (por pasos `mcp`):
|
|
259
|
+
|
|
260
|
+
```json
|
|
261
|
+
{"condicion": "pasos[0].resultado == 'ok'"}
|
|
262
|
+
{"condicion": "resultados.mi_variable != ''"}
|
|
263
|
+
```
|
|
254
264
|
|
|
255
265
|
Si la condición es falsa, el paso se salta (con aviso) y el plan continúa.
|
|
266
|
+
### Pasos MCP y contexto dinámico (v2.3.0)
|
|
267
|
+
|
|
268
|
+
Un paso con `"accion": "mcp"` ejecuta una herramienta MCP del registro
|
|
269
|
+
(`grep`, `read_file`, `list_files`, `ast`, `git_status`, `git_diff`,
|
|
270
|
+
`execute_command`, ...) usando los campos `"herramienta"` y `"args"`.
|
|
271
|
+
El resultado queda disponible para los pasos posteriores:
|
|
272
|
+
|
|
273
|
+
```json
|
|
274
|
+
{"descripcion": "buscar referencias", "accion": "mcp",
|
|
275
|
+
"herramienta": "grep", "args": {"patron": "def main"},
|
|
276
|
+
"variable": "coincidencias"}
|
|
277
|
+
{"descripcion": "usar resultado", "accion": "ejecutar",
|
|
278
|
+
"comando": "echo {{coincidencias}}"}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
- El resultado siempre se guarda también como `{{resultado}}`; si el paso
|
|
282
|
+
define `"variable"`, se guarda bajo ese nombre.
|
|
283
|
+
- `execute_command` soporta `background=true` (devuelve un `pid`
|
|
284
|
+
consultable con `execute_command_status`) y `capture_output=false` para
|
|
285
|
+
mostrar la salida en tiempo real.
|
|
286
|
+
|
|
287
|
+
## 🧠 Aprendizaje autónomo: memoria SQLite, skills y curador (v3.0.0)
|
|
288
|
+
|
|
289
|
+
SnapContext ya no solo ejecuta tareas: **aprende de ellas**. Toda la
|
|
290
|
+
memoria avanzada vive en una base de datos SQLite (`~/.snapcontext/memoria.db`; sin dependencias externas: `sqlite3` viene con Python).
|
|
291
|
+
|
|
292
|
+
### Skills: procedimientos reutilizables
|
|
293
|
+
|
|
294
|
+
- Al terminar una tarea con `--plan` **con éxito**, SnapContext extrae
|
|
295
|
+
los pasos clave y guarda un *skill* (procedimiento reutilizable) en
|
|
296
|
+
la tabla `skills`, junto a su contexto (archivos, comandos) y
|
|
297
|
+
metadatos (fecha, usos, fallos, confiabilidad).
|
|
298
|
+
- Cuando repites una tarea similar, busca el skill más parecido con
|
|
299
|
+
similitud semántica (embeddings; fallback Jaccard/contención sin
|
|
300
|
+
dependencias) y lo reutiliza como punto de partida.
|
|
301
|
+
- Si el skill falla, se penaliza y queda marcado para revisión; si
|
|
302
|
+
tiene éxito repetidamente (3+ usos sin fallos) se marca como
|
|
303
|
+
**confiable** y se prioriza.
|
|
304
|
+
|
|
305
|
+
Comandos útiles:
|
|
306
|
+
|
|
307
|
+
```bash
|
|
308
|
+
snapcontext --skills # lista los skills aprendidos
|
|
309
|
+
snapcontext --curador # ejecuta una pasada del curador
|
|
310
|
+
snapcontext --daemon # daemon: curador + cola de skills
|
|
311
|
+
snapcontext --daemon-intervalo 24 # curador cada 24 h
|
|
312
|
+
snapcontext --plan "..." --sin-aprendizaje # desactiva el aprendizaje
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
Ejemplo de aprendizaje:
|
|
316
|
+
|
|
317
|
+
```bash
|
|
318
|
+
snapcontext --plan "migrar pagos a stripe" --auto --no-confirmar
|
|
319
|
+
# → al terminar (código 0): '[aprendizaje] Nuevo skill guardado:
|
|
320
|
+
# migrar-pagos-a-stripe'
|
|
321
|
+
snapcontext --plan "migrar pagos a stripe ya" --auto --no-confirmar
|
|
322
|
+
# → reutiliza y refuerza el skill existente (sube su confiabilidad)
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### Curador autónomo
|
|
326
|
+
|
|
327
|
+
- Archiva skills sin uso durante más de 30 días.
|
|
328
|
+
- Fusiona skills casi idénticos (similitud ≥ 0.90), conservando el más
|
|
329
|
+
usado y sumando sus estadísticas.
|
|
330
|
+
- Notifica por CLI los skills con baja confiabilidad (< 0.4).
|
|
331
|
+
- Se ejecuta manualmente (`--curador`) o periódicamente vía daemon.
|
|
332
|
+
|
|
333
|
+
### Daemon (`--daemon`)
|
|
334
|
+
|
|
335
|
+
Proceso en segundo plano que cada minuto sondea la memoria: ejecuta el
|
|
336
|
+
curador cuando vence el intervalo configurado (`--daemon-intervalo`,
|
|
337
|
+
168 h por defecto = semanal) y procesa la cola de skills pendientes
|
|
338
|
+
(tabla `cola`) para ejecutarlos sin intervención. La CLI y el chat
|
|
339
|
+
encolan skills con `_cola_encolar()`; el agente `AgenteAprendizaje`
|
|
340
|
+
(en `agentes.py`) expone toda esta memoria al orquestador.
|
|
341
|
+
|
|
256
342
|
- **Paralelismo**: con `--paralelo N` (junto a `--auto`) se ejecutan hasta N
|
|
257
|
-
pasos independientes a la vez; los logs llevan el identificador `[paso N]
|
|
343
|
+
pasos independientes a la vez; los logs llevan el identificador `[paso N]`. Desde v2.3.0 el planificador también respeta las dependencias dinámicas: un paso cuya condición usa una variable que otro paso aún no ha producido espera a que esté disponible:
|
|
258
344
|
|
|
259
345
|
```bash
|
|
260
346
|
snapcontext --plan "tarea grande" --auto --paralelo 3 --no-confirmar
|
|
@@ -420,4 +420,76 @@ class AgenteTester:
|
|
|
420
420
|
limite = getattr(sc, "MAX_ERROR_SALIDA", 4000)
|
|
421
421
|
if len(limpieza) > limite:
|
|
422
422
|
limpieza = "\n--- (salida recortada) ---\n" + limpieza[-limite:]
|
|
423
|
-
return limpieza
|
|
423
|
+
return limpieza
|
|
424
|
+
|
|
425
|
+
|
|
426
|
+
class AgenteAprendizaje:
|
|
427
|
+
"""Agente de Aprendizaje (v3.0.0): memoria persistente y skills.
|
|
428
|
+
|
|
429
|
+
Encapsula la memoria SQLite de SnapContext (skills, historial de
|
|
430
|
+
aprendizaje, contexto clave/valor) y el curador autónomo. Delega en las
|
|
431
|
+
funciones del módulo :mod:`snapcontext` para mantener una única fuente
|
|
432
|
+
de verdad; esta clase aporta la capa de alto nivel que consumen el
|
|
433
|
+
orquestador y futuras integraciones (chat, web).
|
|
434
|
+
"""
|
|
435
|
+
|
|
436
|
+
def inicializar(self) -> str:
|
|
437
|
+
"""Crea la base de datos de memoria si no existe. Devuelve su ruta."""
|
|
438
|
+
import snapcontext as sc
|
|
439
|
+
|
|
440
|
+
return sc._db_init()
|
|
441
|
+
|
|
442
|
+
def buscar_skill(self, consulta: str,
|
|
443
|
+
umbral: float = 0.75) -> Optional[dict]:
|
|
444
|
+
"""Busca un skill similar a ``consulta`` (embeddings o fallback)."""
|
|
445
|
+
import snapcontext as sc
|
|
446
|
+
|
|
447
|
+
return sc._skill_buscar(consulta, umbral=umbral)
|
|
448
|
+
|
|
449
|
+
def generar_skill(self, consulta: str, resultados: List[dict],
|
|
450
|
+
raiz: str = ".") -> Optional[int]:
|
|
451
|
+
"""Genera y guarda un skill a partir de una tarea exitosa."""
|
|
452
|
+
import snapcontext as sc
|
|
453
|
+
|
|
454
|
+
return sc._skill_generar(consulta, resultados, raiz=raiz)
|
|
455
|
+
|
|
456
|
+
def registrar_exito(self, skill_id: int) -> float:
|
|
457
|
+
"""Refuerza un skill tras reutilizarlo con éxito."""
|
|
458
|
+
import snapcontext as sc
|
|
459
|
+
|
|
460
|
+
return sc._skill_registrar_exito(skill_id)
|
|
461
|
+
|
|
462
|
+
def registrar_fallo(self, skill_id: int) -> float:
|
|
463
|
+
"""Penaliza un skill tras un fallo (queda marcado para revisión)."""
|
|
464
|
+
import snapcontext as sc
|
|
465
|
+
|
|
466
|
+
return sc._skill_registrar_fallo(skill_id)
|
|
467
|
+
|
|
468
|
+
def aprender_de_tarea(self, consulta: str, todo_ok: bool,
|
|
469
|
+
resultados: List[dict], raiz: str = ".",
|
|
470
|
+
detalle: str = "") -> Optional[int]:
|
|
471
|
+
"""Gancho principal: registra la tarea y aprende de ella."""
|
|
472
|
+
import snapcontext as sc
|
|
473
|
+
|
|
474
|
+
return sc._aprender_de_tarea(consulta, todo_ok, resultados,
|
|
475
|
+
raiz=raiz, detalle=detalle)
|
|
476
|
+
|
|
477
|
+
def encolar_skill(self, skill_id: int) -> int:
|
|
478
|
+
"""Encola un skill para ejecución en segundo plano por el daemon."""
|
|
479
|
+
import snapcontext as sc
|
|
480
|
+
|
|
481
|
+
return sc._cola_encolar(skill_id)
|
|
482
|
+
|
|
483
|
+
def curar(self, dias_sin_uso: int = 30,
|
|
484
|
+
umbral_fusion: float = 0.90) -> dict:
|
|
485
|
+
"""Ejecuta el curador autónomo y devuelve el resumen de acciones."""
|
|
486
|
+
import snapcontext as sc
|
|
487
|
+
|
|
488
|
+
return sc._curador_ejecutar(dias_sin_uso=dias_sin_uso,
|
|
489
|
+
umbral_fusion=umbral_fusion)
|
|
490
|
+
|
|
491
|
+
def listar_skills(self, incluir_archivados: bool = False) -> List[dict]:
|
|
492
|
+
"""Lista los skills almacenados en la memoria persistente."""
|
|
493
|
+
import snapcontext as sc
|
|
494
|
+
|
|
495
|
+
return sc._skill_listar(incluir_archivados=incluir_archivados)
|
|
@@ -21,7 +21,7 @@ import sys
|
|
|
21
21
|
from typing import List, Optional, Tuple
|
|
22
22
|
|
|
23
23
|
from agentes import (AgenteContexto, AgenteEditor, AgenteEditorAST,
|
|
24
|
-
AgenteEditorPropio, AgenteTester)
|
|
24
|
+
AgenteEditorPropio, AgenteAprendizaje, AgenteTester)
|
|
25
25
|
|
|
26
26
|
# Centinela diferenciado del None de "aborto": _planificar lo devuelve cuando
|
|
27
27
|
# el pipeline termina de forma exitosa y temprana (p. ej. --vista-previa).
|
|
@@ -43,6 +43,7 @@ class Orquestador:
|
|
|
43
43
|
self.agente_editor_propio = AgenteEditorPropio()
|
|
44
44
|
self.agente_editor_ast = AgenteEditorAST()
|
|
45
45
|
self.agente_tester = AgenteTester()
|
|
46
|
+
self.agente_aprendizaje = AgenteAprendizaje()
|
|
46
47
|
self.evento_callback = evento_callback
|
|
47
48
|
|
|
48
49
|
def _on_evento(self, evento: dict) -> None:
|
|
@@ -200,6 +201,17 @@ class Orquestador:
|
|
|
200
201
|
)
|
|
201
202
|
self._emitir_tipo("aider", accion="fin", ok=ok)
|
|
202
203
|
self._emitir_tipo("final", ok=ok)
|
|
204
|
+
# Aprendizaje continuo (v3.0.0): registrar el resultado de la
|
|
205
|
+
# tarea en la memoria persistente y generar/reforzar skills.
|
|
206
|
+
try:
|
|
207
|
+
if not getattr(args, "sin_aprendizaje", False):
|
|
208
|
+
self.agente_aprendizaje.aprender_de_tarea(
|
|
209
|
+
consulta, bool(ok),
|
|
210
|
+
[{"descripcion": consulta, "accion": "editar",
|
|
211
|
+
"archivos": seleccion}],
|
|
212
|
+
raiz=str(raiz))
|
|
213
|
+
except Exception as exc:
|
|
214
|
+
sc.aviso(f"[aprendizaje] No se pudo registrar ({exc})")
|
|
203
215
|
return 0 if ok else 1
|
|
204
216
|
finally:
|
|
205
217
|
# Si este orquestador fue quien registró el callback global, lo limpia.
|
|
@@ -6,13 +6,15 @@ build-backend = "setuptools.build_meta"
|
|
|
6
6
|
# Nombre verificado disponible en PyPI (18/08/2026): pypi.org/pypi/snapcontext → 404.
|
|
7
7
|
# Alternativas si algún día estuviera ocupado: "snapcontext-cli" o "snapcontext-tool".
|
|
8
8
|
name = "snapcontext"
|
|
9
|
-
version = "
|
|
9
|
+
version = "3.0.0"
|
|
10
10
|
description = "SnapContext: Asistente de IA con contexto automático para desarrollo"
|
|
11
11
|
readme = "README.md"
|
|
12
12
|
requires-python = ">=3.9"
|
|
13
13
|
# PEP 639: licencia SPDX + fichero de licencia incluido en el paquete.
|
|
14
14
|
license = "MIT"
|
|
15
15
|
license-files = ["LICENSE"]
|
|
16
|
+
# Nota (v3.0.0): la memoria avanzada usa `sqlite3`, incluido en la stdlib de
|
|
17
|
+
# Python; no añade dependencias externas.
|
|
16
18
|
authors = [
|
|
17
19
|
# TODO: cambia por tu nombre y correo reales antes de publicar.
|
|
18
20
|
{ name = "SnapContext Contributors", email = "tu@email.com" },
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: snapcontext
|
|
3
|
-
Version:
|
|
3
|
+
Version: 3.0.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
|
|
@@ -275,7 +275,7 @@ snapcontext --plan "tarea" --no-confirmar
|
|
|
275
275
|
|
|
276
276
|
1. El proveedor de IA descompone la tarea en pasos JSON:
|
|
277
277
|
```json
|
|
278
|
-
{"descripcion": "...", "accion": "editar|ejecutar|consultar",
|
|
278
|
+
{"descripcion": "...", "accion": "editar|ejecutar|consultar|mcp",
|
|
279
279
|
"archivos": ["..."], "comando": "...",
|
|
280
280
|
"dependencias": [1, 2],
|
|
281
281
|
"condicion": "archivo_existe('src/main.py')"}
|
|
@@ -283,7 +283,8 @@ snapcontext --plan "tarea" --no-confirmar
|
|
|
283
283
|
2. Los pasos se muestran numerados y se pide confirmación.
|
|
284
284
|
3. Cada paso se ejecuta secuencialmente: **editar** usa el pipeline completo
|
|
285
285
|
(`_planificar` + `_bucle_test`), **ejecutar** lanza comandos shell,
|
|
286
|
-
**consultar** pregunta al proveedor.
|
|
286
|
+
**consultar** pregunta al proveedor y **mcp** (v2.3.0) ejecuta una
|
|
287
|
+
herramienta MCP guardando su resultado en el contexto del plan.
|
|
287
288
|
4. Tras cada paso eliges: continuar / reintentar / saltar / abortar. Al final
|
|
288
289
|
hay un resumen que se guarda en `historial.json`.
|
|
289
290
|
|
|
@@ -296,10 +297,95 @@ snapcontext --plan "tarea" --no-confirmar
|
|
|
296
297
|
- `archivo_existe('src/main.py')`
|
|
297
298
|
- `archivo_contiene('src/main.py', 'def main')`
|
|
298
299
|
- `comando_exito('flutter test')`
|
|
300
|
+
- `variable_existe('mi_variable')` *(v2.3.0)*
|
|
301
|
+
|
|
302
|
+
Además, desde v2.3.0 acepta **comparaciones dinámicas** con resultados
|
|
303
|
+
de pasos previos o variables dejadas en el contexto (por pasos `mcp`):
|
|
304
|
+
|
|
305
|
+
```json
|
|
306
|
+
{"condicion": "pasos[0].resultado == 'ok'"}
|
|
307
|
+
{"condicion": "resultados.mi_variable != ''"}
|
|
308
|
+
```
|
|
299
309
|
|
|
300
310
|
Si la condición es falsa, el paso se salta (con aviso) y el plan continúa.
|
|
311
|
+
### Pasos MCP y contexto dinámico (v2.3.0)
|
|
312
|
+
|
|
313
|
+
Un paso con `"accion": "mcp"` ejecuta una herramienta MCP del registro
|
|
314
|
+
(`grep`, `read_file`, `list_files`, `ast`, `git_status`, `git_diff`,
|
|
315
|
+
`execute_command`, ...) usando los campos `"herramienta"` y `"args"`.
|
|
316
|
+
El resultado queda disponible para los pasos posteriores:
|
|
317
|
+
|
|
318
|
+
```json
|
|
319
|
+
{"descripcion": "buscar referencias", "accion": "mcp",
|
|
320
|
+
"herramienta": "grep", "args": {"patron": "def main"},
|
|
321
|
+
"variable": "coincidencias"}
|
|
322
|
+
{"descripcion": "usar resultado", "accion": "ejecutar",
|
|
323
|
+
"comando": "echo {{coincidencias}}"}
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
- El resultado siempre se guarda también como `{{resultado}}`; si el paso
|
|
327
|
+
define `"variable"`, se guarda bajo ese nombre.
|
|
328
|
+
- `execute_command` soporta `background=true` (devuelve un `pid`
|
|
329
|
+
consultable con `execute_command_status`) y `capture_output=false` para
|
|
330
|
+
mostrar la salida en tiempo real.
|
|
331
|
+
|
|
332
|
+
## 🧠 Aprendizaje autónomo: memoria SQLite, skills y curador (v3.0.0)
|
|
333
|
+
|
|
334
|
+
SnapContext ya no solo ejecuta tareas: **aprende de ellas**. Toda la
|
|
335
|
+
memoria avanzada vive en una base de datos SQLite (`~/.snapcontext/memoria.db`; sin dependencias externas: `sqlite3` viene con Python).
|
|
336
|
+
|
|
337
|
+
### Skills: procedimientos reutilizables
|
|
338
|
+
|
|
339
|
+
- Al terminar una tarea con `--plan` **con éxito**, SnapContext extrae
|
|
340
|
+
los pasos clave y guarda un *skill* (procedimiento reutilizable) en
|
|
341
|
+
la tabla `skills`, junto a su contexto (archivos, comandos) y
|
|
342
|
+
metadatos (fecha, usos, fallos, confiabilidad).
|
|
343
|
+
- Cuando repites una tarea similar, busca el skill más parecido con
|
|
344
|
+
similitud semántica (embeddings; fallback Jaccard/contención sin
|
|
345
|
+
dependencias) y lo reutiliza como punto de partida.
|
|
346
|
+
- Si el skill falla, se penaliza y queda marcado para revisión; si
|
|
347
|
+
tiene éxito repetidamente (3+ usos sin fallos) se marca como
|
|
348
|
+
**confiable** y se prioriza.
|
|
349
|
+
|
|
350
|
+
Comandos útiles:
|
|
351
|
+
|
|
352
|
+
```bash
|
|
353
|
+
snapcontext --skills # lista los skills aprendidos
|
|
354
|
+
snapcontext --curador # ejecuta una pasada del curador
|
|
355
|
+
snapcontext --daemon # daemon: curador + cola de skills
|
|
356
|
+
snapcontext --daemon-intervalo 24 # curador cada 24 h
|
|
357
|
+
snapcontext --plan "..." --sin-aprendizaje # desactiva el aprendizaje
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
Ejemplo de aprendizaje:
|
|
361
|
+
|
|
362
|
+
```bash
|
|
363
|
+
snapcontext --plan "migrar pagos a stripe" --auto --no-confirmar
|
|
364
|
+
# → al terminar (código 0): '[aprendizaje] Nuevo skill guardado:
|
|
365
|
+
# migrar-pagos-a-stripe'
|
|
366
|
+
snapcontext --plan "migrar pagos a stripe ya" --auto --no-confirmar
|
|
367
|
+
# → reutiliza y refuerza el skill existente (sube su confiabilidad)
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### Curador autónomo
|
|
371
|
+
|
|
372
|
+
- Archiva skills sin uso durante más de 30 días.
|
|
373
|
+
- Fusiona skills casi idénticos (similitud ≥ 0.90), conservando el más
|
|
374
|
+
usado y sumando sus estadísticas.
|
|
375
|
+
- Notifica por CLI los skills con baja confiabilidad (< 0.4).
|
|
376
|
+
- Se ejecuta manualmente (`--curador`) o periódicamente vía daemon.
|
|
377
|
+
|
|
378
|
+
### Daemon (`--daemon`)
|
|
379
|
+
|
|
380
|
+
Proceso en segundo plano que cada minuto sondea la memoria: ejecuta el
|
|
381
|
+
curador cuando vence el intervalo configurado (`--daemon-intervalo`,
|
|
382
|
+
168 h por defecto = semanal) y procesa la cola de skills pendientes
|
|
383
|
+
(tabla `cola`) para ejecutarlos sin intervención. La CLI y el chat
|
|
384
|
+
encolan skills con `_cola_encolar()`; el agente `AgenteAprendizaje`
|
|
385
|
+
(en `agentes.py`) expone toda esta memoria al orquestador.
|
|
386
|
+
|
|
301
387
|
- **Paralelismo**: con `--paralelo N` (junto a `--auto`) se ejecutan hasta N
|
|
302
|
-
pasos independientes a la vez; los logs llevan el identificador `[paso N]
|
|
388
|
+
pasos independientes a la vez; los logs llevan el identificador `[paso N]`. Desde v2.3.0 el planificador también respeta las dependencias dinámicas: un paso cuya condición usa una variable que otro paso aún no ha producido espera a que esté disponible:
|
|
303
389
|
|
|
304
390
|
```bash
|
|
305
391
|
snapcontext --plan "tarea grande" --auto --paralelo 3 --no-confirmar
|
|
@@ -23,9 +23,11 @@ tests/test_jetbrains_170.py
|
|
|
23
23
|
tests/test_mcp_014.py
|
|
24
24
|
tests/test_mcp_140.py
|
|
25
25
|
tests/test_memoria_015.py
|
|
26
|
+
tests/test_memoria_300.py
|
|
26
27
|
tests/test_orquestador.py
|
|
27
28
|
tests/test_permisos_013.py
|
|
28
29
|
tests/test_plan_012.py
|
|
30
|
+
tests/test_plan_mcp_230.py
|
|
29
31
|
tests/test_v010.py
|
|
30
32
|
tests/test_validacion_130.py
|
|
31
33
|
tests/test_vscode_016.py
|