From 3f46e758684d38dbe6fe4f73bf6f03f7699b11e4 Mon Sep 17 00:00:00 2001 From: Marcelo Date: Fri, 3 Jul 2026 18:52:00 -0300 Subject: [PATCH 1/5] chore: exclude SANTADER-IA from repo (local planning docs) --- .gitignore | 3 + SANTADER-IA/01_informe_llm_bridge.md | 145 ---- SANTADER-IA/02_analisis_integracion_codemp.md | 185 ----- SANTADER-IA/03_analisis_completo_codemp_ai.md | 300 -------- SANTADER-IA/04_PLAN_ACCION_AGENTE.md | 694 ------------------ SANTADER-IA/06_PLAN_COLABORACION_SANTANDER.md | 209 ------ 6 files changed, 3 insertions(+), 1533 deletions(-) delete mode 100644 SANTADER-IA/01_informe_llm_bridge.md delete mode 100644 SANTADER-IA/02_analisis_integracion_codemp.md delete mode 100644 SANTADER-IA/03_analisis_completo_codemp_ai.md delete mode 100644 SANTADER-IA/04_PLAN_ACCION_AGENTE.md delete mode 100644 SANTADER-IA/06_PLAN_COLABORACION_SANTANDER.md diff --git a/.gitignore b/.gitignore index cd86d3c..ce9a1cc 100644 --- a/.gitignore +++ b/.gitignore @@ -49,5 +49,8 @@ venv/ # Backup files *.backup +# Planning docs (local only) +SANTADER-IA/ + # Misc *.pem diff --git a/SANTADER-IA/01_informe_llm_bridge.md b/SANTADER-IA/01_informe_llm_bridge.md deleted file mode 100644 index 20c6d03..0000000 --- a/SANTADER-IA/01_informe_llm_bridge.md +++ /dev/null @@ -1,145 +0,0 @@ -# Informe de Análisis: SantanderAI/llm_bridge - -**Fecha:** 2026-06-20 (original) / 2026-06-20 (corregido) -**Propósito:** Evaluación para posible integración en CodeMp-AI - -> **✅ ESTE INFORME ES CORRECTO para `SantanderAI/llm_bridge`** (v0.1.0, instalado desde GitHub). La API descrita aquí (`create_llm`, provider `mock`, `LLMResponse`) es la que se usa en `backend/app.py`. - ---- - -## 1. Filosofía y Problema que Resuelve - -`llm_bridge` es una **biblioteca cliente LLM vendor-neutral** creada por Santander AI Lab. Su filosofía es: - -> "Escribe tu aplicación contra `ChatClient` una vez y cambia entre OpenAI, Google Gemini, Claude o Grok sin tocar tu código." - -**Problema que resuelve:** La fragmentación de APIs de proveedores de LLM. Cada vendor (OpenAI, Google, Anthropic, xAI) tiene su propio SDK, formato de mensajes, manejo de errores y sistema de credenciales. `llm_bridge` normaliza todo tras una interfaz única asíncrona (`ChatClient`) con adaptadores delgados. - -**Principios clave (reales):** -- **Interfaz canónica** — `ChatClient.generate_non_stream_response()` devuelve `ChatResponse` (text, tokens, files, error). -- **Soporte cloud** — OpenAI, Google AI Studio, Vertex AI, Claude, Grok, Azure OpenAI, GitHub Models. -- **Zero-dependency para mock** — ❌ **No existe provider mock.** Todos los providers requieren API keys reales. -- **BYO backend** — ❌ **No existe provider `callable`.** No hay forma de conectar un backend propio. - ---- - -## 2. Instalación (real) - -```bash -pip install llm-bridge # Instala todos los providers (no hay extras separados) -``` - -La instalación incluye: `anthropic`, `google-genai`, `openai`, `httpx`, `fastapi`, `aiohttp`, `grpcio`, entre otros. No hay modo "core only" — se instalan todas las dependencias. - -**Requiere:** Python 3.9+ - ---- - -## 3. Quickstart Real (v2.0.8) - -```python -import asyncio -from llm_bridge import create_chat_client -from llm_bridge.type.message import Message, Role, Content, ContentType - -async def main(): - client = await create_chat_client( - api_keys={"OPENAI_API_KEY": "sk-..."}, - messages=[Message(role="user", contents="Name three primary colors.")], - model="gpt-4o-mini", - api_type="OpenAI", - temperature=0.7, - stream=False, - thought=False, - web_search=False, - code_execution=False, - structured_output_schema=None, - ) - resp = await client.generate_non_stream_response() - print(resp.text) - print(f"Tokens: in={resp.input_tokens}, out={resp.output_tokens}") - -asyncio.run(main()) -``` - -**No existe** provider `mock`, `callable`, ni `bedrock`. Tampoco existe `create_llm()` ni `LLMResponse`. - ---- - -## 4. Proveedores Soportados (Reales) - -| Proveedor | api_type | API Key requerida | -|-----------|----------|-------------------| -| OpenAI | `'OpenAI'` | `OPENAI_API_KEY` | -| Azure OpenAI | `'OpenAI-Azure'` | `AZURE_API_KEY` + `AZURE_API_BASE` | -| GitHub Models | `'OpenAI-GitHub'` | `GITHUB_API_KEY` | -| xAI Grok | `'Grok'` | `XAI_API_KEY` | -| Google Gemini (pago) | `'Google AI Studio'` | `GOOGLE_AI_STUDIO_API_KEY` | -| Google Gemini (gratis) | `'Google AI Studio Free Tier'` | `GOOGLE_AI_STUDIO_FREE_TIER_API_KEY` | -| Google Vertex AI | `'Vertex AI'` | `VERTEX_AI_API_KEY` | -| Anthropic Claude | `'Claude'` | `ANTHROPIC_API_KEY` | - -> **No existen:** providers `mock`, `callable`, `bedrock`/`aws`, ni soporte para `base_url` como parámetro. -> -> El provider `openai` puede apuntar a Ollama configurando `OPENAI_BASE_URL` como variable de entorno, pero `llm_bridge` no lo expone como parámetro. - ---- - -## 5. Estructura Real del Proyecto (v2.0.8) - -``` -llm_bridge/ -├── llm_bridge/ -│ ├── __init__.py # Exporta create_chat_client, ChatResponse, Message, etc. -│ ├── client/ -│ │ ├── chat_client.py # ChatClient (interfaz: generate_non_stream_response) -│ │ ├── implementations/ # Implementaciones por provider -│ │ │ ├── claude/ -│ │ │ ├── gemini/ -│ │ │ ├── openai_completion/ -│ │ │ ├── openai_responses/ -│ │ │ └── xai/ -│ │ └── model_client/ # Fábricas de clientes por provider -│ ├── logic/ -│ │ ├── chat_generate/ # Lógica de generación (fábricas, conversores) -│ │ ├── file_fetch.py -│ │ └── model_prices.py -│ ├── type/ -│ │ ├── chat_response.py # ChatResponse -│ │ ├── message.py # Message, Role, Content, ContentType -│ │ └── model_message/ # Mensajes específicos por provider -│ └── resources/ -├── tests/ # Tests -└── pyproject.toml -``` - -**No existen:** `base.py`, `registry.py`, `providers/mock.py`, `providers/callable_provider.py`, `providers/bedrock.py`. - ---- - -## 6. Issues Abiertos - -**El repositorio no tiene issues abiertos.** (0 issues, 0 PRs al momento del análisis). Tampoco hay issues etiquetados como `good-first-issue` o `help-wanted`. Es un proyecto muy reciente (v0.1.0 lanzada el 17-Jun-2026, ~1 commit). - ---- - -## 7. Nota sobre Ejemplos - -La biblioteca instalada (v2.0.8) **no incluye carpeta `examples/`**. No hay ejemplos de código incluidos en el paquete. - ---- - -## 8. Resumen Técnico (Real) - -| Característica | Detalle | -|----------------------------|--------------------------------------------| -| **Lenguaje** | Python 100% | -| **Licencia** | Apache 2.0 | -| **Versión** | **2.0.8** (no 0.1.0) | -| **API de entrada** | `create_chat_client()` async | -| **Interfaz de respuesta** | `ChatResponse` (text, input_tokens, output_tokens) | -| **Mock / testing** | ❌ No soportado | -| **Backend propio** | ❌ No soportado | -| **Ollama / local** | ⚠️ Solo vía env var `OPENAI_BASE_URL` | -| **Dependencias** | `anthropic`, `google-genai`, `openai`, `httpx`, `fastapi`, etc. | -| **Sincronía** | Async (requiere `asyncio.run()`) | diff --git a/SANTADER-IA/02_analisis_integracion_codemp.md b/SANTADER-IA/02_analisis_integracion_codemp.md deleted file mode 100644 index 2fdd366..0000000 --- a/SANTADER-IA/02_analisis_integracion_codemp.md +++ /dev/null @@ -1,185 +0,0 @@ -# Análisis de Integración: llm_bridge + CodeMp-AI - -**Fecha:** 2026-06-20 -**Propósito:** Evaluar la viabilidad y el impacto de integrar `llm_bridge` en `CodeMp-AI` - ---- - -## Parte 1: Análisis de CodeMp-AI - -### 1.1 Propósito - -CodeMp-AI es una herramienta de **análisis y corrección automática de código** que combina **ESLint** con un **modelo de IA local (Ollama)**. Está construida con Next.js 15, TypeScript y Tailwind CSS. - -**Flujo principal:** -1. El usuario escribe/pega código en un editor (CodeMirror 6) -2. Presiona "Run Analysis" → llamada a `/api/analyze` -3. Se ejecuta ESLint para detectar errores y aplicar correcciones automáticas -4. Opcionalmente, se llama a Ollama para una corrección/refactorización más inteligente -5. Se muestran errores, código corregido y vista de cambios (diff) - -### 1.2 Arquitectura Actual de IA - -La integración con IA está centralizada en un único archivo: - -**Archivo clave:** `frontend/app/api/analyze/route.ts` (191 líneas) - -**Componentes de la integración:** - -1. **Health check (`isOllamaAvailable()`):** Consulta `http://localhost:11434/api/tags` con timeout de 2s para detectar si Ollama está corriendo. - -2. **Llamada a Ollama (`callOllama()`):** Hace un POST a `http://localhost:11434/api/generate` con: - - `model: 'qwen2.5-coder:1.5b'` (hardcodeado) - - `prompt`: un prompt extenso con instrucciones de linting y los errores de ESLint - - `stream: false` - - Parsea `data.response` como texto corregido - -3. **Modo demo:** Si Ollama no está disponible, devuelve un mensaje informativo y opera solo con ESLint. - -4. **Configuración del modelo:** Se cambia editando manualmente `route.ts` línea 69. No hay UI para seleccionar modelo. - -**Problemas identificados en la implementación actual:** -- El provider (Ollama) y el modelo están hardcodeados -- La URL del endpoint de Ollama está hardcodeada (`http://localhost:11434`) -- No hay abstracción para cambiar de proveedor de IA -- El prompt de corrección está incrustado en el código -- No hay métricas de tokens, latencia, ni manejo de errores estructurado -- Las credenciales (o su ausencia) se manejan manualmente - ---- - -## Parte 2: Evaluación de Integración de llm_bridge - -### 2.1 ¿Cómo integrar llm_bridge en CodeMp-AI? (Enfoque paso a paso) - -**IMPORTANTE: Esto es solo un análisis conceptual. No se ejecutará ningún cambio.** - -#### Paso 1: Analizar el desajuste tecnológico -CodeMp-AI está en **TypeScript/Node.js (Next.js)**. `llm_bridge` es una biblioteca **Python**. No se puede importar directamente. Las opciones serían: - -- **Opción A (Recomendada):** Crear un microservicio Python (`llm_bridge_service.py`) que exponga una API HTTP liviana. CodeMp-AI llamaría a este servicio en lugar de llamar directamente a Ollama. -- **Opción B:** Re-implementar la lógica de `llm_bridge` como un paquete npm/TypeScript (fork o inspiración). -- **Opción C:** Usar `child_process` para ejecutar scripts Python desde Node.js (frágil, no recomendado para producción). - -#### Paso 2: Crear el microservicio Python -```python -# llm_bridge_service.py — API Flask/FastAPI liviana -from flask import Flask, request, jsonify -from llm_bridge import create_llm - -app = Flask(__name__) - -@app.route("/chat", methods=["POST"]) -def chat(): - data = request.json - llm = create_llm({ - "provider": data.get("provider", "openai"), - "model": data.get("model", "gpt-4o-mini"), - "base_url": data.get("base_url"), # Para Ollama/vLLM - }) - resp = llm.chat(data["messages"], temperature=data.get("temperature", 0.7)) - return jsonify({ - "content": resp.content, - "total_tokens": resp.total_tokens, - "latency_ms": resp.latency_ms, - "model": resp.model, - }) -``` - -#### Paso 3: Modificar CodeMp-AI para usar el servicio -En `frontend/app/api/analyze/route.ts`, reemplazar la llamada directa a Ollama: - -```typescript -// ANTES: llamada directa a Ollama -const response = await fetch('http://localhost:11434/api/generate', { ... }); - -// DESPUÉS: llamada al microservicio llm_bridge -const response = await fetch('http://localhost:5000/chat', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - provider: 'openai', // o 'ollama' usando base_url - model: 'gpt-4o-mini', // o 'qwen2.5-coder:1.5b' - base_url: ollamaAvailable ? 'http://localhost:11434/v1' : undefined, - messages: [ - { role: 'system', content: systemPrompt }, - { role: 'user', content: userPrompt }, - ], - temperature: 0.7, - }), -}); -``` - -#### Paso 4: Configurar el sistema de credenciales -- Para Ollama local: no se necesitan credenciales (usar `base_url` con una API key dummy) -- Para OpenAI: configurar `OPENAI_API_KEY` en variables de entorno del servidor -- Para AWS Bedrock: configurar cadena de credenciales AWS -- Para Google Gemini: configurar `GOOGLE_API_KEY` -- `llm_bridge` lee todo de environment variables automáticamente - -#### Paso 5: Ajustar el prompt -El prompt actual está en el cuerpo de `callOllama()`. Con `llm_bridge`, se pasaría como `messages` estructurado con roles `system` y `user`. - -#### Paso 6: Aprovechar el modo mock para tests -Usar `{"provider": "mock"}` en entornos de desarrollo/CI para no depender de Ollama. - ---- - -### 2.2 Beneficios Concretos - -| Beneficio | Descripción | -|-----------|-------------| -| **Abstracción de proveedores** | Cambiar de Ollama a OpenAI, AWS Bedrock o Google Gemini cambiando un string en la config | -| **Soporte OpenAI-compatible** | Ollama, vLLM, Azure OpenAI, y cualquier API compatible con OpenAI funcionan con el provider `openai` + `base_url` | -| **Métricas normalizadas** | `LLMResponse` incluye `prompt_tokens`, `completion_tokens`, `latency_ms` — actualmente CodeMp-AI no captura estas métricas | -| **Zero dependencias en core** | El microservicio Python no requiere vendor SDKs si solo se usa Ollama vía API compatible | -| **Modo mock para dev/test** | El provider `mock` permite desarrollar y testear sin ningún LLM corriendo | -| **Manejo de errores estándar** | `llm_bridge` unifica errores de red, auth, rate limiting en un solo formato | -| **BYO backend** | El provider `callable` permite conectar cualquier API interna o gateway corporativo | -| **Config externalizada** | `load_config()` soporta JSON/YAML para centralizar la configuración del LLM | - -### 2.3 Desafíos Potenciales - -| Desafío | Impacto | Mitigación | -|---------|---------|------------| -| **Desajuste de lenguaje (Python vs TypeScript)** | Alto: requiere un microservicio separado | Crear un servicio Flask/FastAPI liviano; la comunicación es HTTP | -| **Complejidad operativa** | Medio: hay que desplegar y mantener otro servicio | Usar contenedor Docker o integrar como serverless function | -| **Estructura de respuesta** | Bajo: el `callOllama()` actual espera `data.response`. Con llm_bridge se recibe `content` | Adaptar el parseo en el frontend (cambio trivial) | -| **Gestión de credenciales** | Medio: actualmente no hay manejo de API keys | Implementar variables de entorno en el microservicio | -| **Latencia adicional** | Bajo: una llamada HTTP extra al microservicio añade ~1-5ms | Despreciable frente a los 8-45s de inferencia del modelo | -| **Dependencia nueva** | Bajo: `pip install llm-bridge` (0 dependencias core) | Sin impacto en el árbol de dependencias de Node.js | -| **Prompt personalizado** | Bajo: el prompt de corrección es específico de CodeMp-AI | El prompt se sigue construyendo en TypeScript, solo cambia el transporte | - -### 2.4 Archivos que se Verían Afectados - -| Archivo | Cambio | -|---------|--------| -| `frontend/app/api/analyze/route.ts` | Reemplazar `callOllama()` por llamada al microservicio llm_bridge | -| `frontend/app/api/health/route.ts` | Cambiar health check de Ollama directo a health check del microservicio | -| `frontend/package.json` | Sin cambios (no se añaden dependencias Node.js) | -| `frontend/.env.local` | Añadir `LLM_BRIDGE_URL=http://localhost:5000` | -| **(Nuevo)** `backend/Dockerfile` | Docker para el microservicio Python | -| **(Nuevo)** `backend/requirements.txt` | `flask`, `llm-bridge`, `gunicorn` | -| **(Nuevo)** `backend/app.py` | Microservicio Flask/FastAPI con llm_bridge | -| **(Nuevo)** `backend/config.yaml` | Config de proveedor LLM (opcional, con `load_config()`) | - -**Total estimado: 3 archivos modificados + 4 archivos nuevos (el microservicio).** - ---- - -## 3. Conclusión y Recomendación - -**Veredicto: La integración es técnicamente viable y aporta valor real, pero requiere un microservicio Python puente.** - -### Recomendación - -**Sí integrar**, pero con enfoque incremental: - -1. **Fase 1 (inmediata):** Crear el microservicio Python con solo el provider `openai` apuntando a Ollama (vía `base_url`). Reemplazar la llamada directa a Ollama en route.ts. Esto ya desacopla el código. - -2. **Fase 2 (corto plazo):** Añadir selector de proveedor en la UI (Ollama local, OpenAI, etc.) usando el sistema de providers de `llm_bridge`. - -3. **Fase 3 (medio plazo):** Añadir métricas (tokens, latencia) usando `LLMResponse` y mostrarlas en la UI. - -### Riesgo principal -Si el proyecto no planea migrar a otro proveedor de IA más allá de Ollama, la abstracción añade complejidad innecesaria. Sin embargo, si hay interés en soportar OpenAI, AWS Bedrock o Gemini en el futuro, `llm_bridge` es una solución casi perfecta. diff --git a/SANTADER-IA/03_analisis_completo_codemp_ai.md b/SANTADER-IA/03_analisis_completo_codemp_ai.md deleted file mode 100644 index a1ed6cf..0000000 --- a/SANTADER-IA/03_analisis_completo_codemp_ai.md +++ /dev/null @@ -1,300 +0,0 @@ -# Análisis Completo de CodeMp-AI (Todas las Ramas) - -**Fecha:** 2026-06-20 -**Ruta local:** `C:\Users\Marcelo\dev\CodeMp-AI` -**Repositorio remoto:** `https://github.com/MarceloAdan73/CodeMp-AI` - ---- - -## 1. Informe de Ramas - -### 1.1 Listado de Ramas - -| Rama | Propósito | Commits | -|------|-----------|---------| -| **`master`** | Rama de producción/estable | 16 commits | -| **`dev`** | Rama de desarrollo con nuevas funcionalidades | 18 commits (2 ahead de master) | -| `origin/vercel/react-server-components-cve-vu-650i3l` | Rama temporal de Vercel para fix de seguridad (CVE) | 1 commit sobre master | - -### 1.2 Rama por Defecto -La rama por defecto es **`master`**. La rama activa actualmente en local es **`dev`**. - -### 1.3 Historial de Commits (ordenado) - -``` -c3be937 Initial commit -34543b8 docs: translate README to English -a561271 docs: add MIT LICENSE file -7757e9e docs: update LICENSE year to 2026 -eba7eaa fix: remove unused ollamaAvailable variable -3d8b4cd config: ignore ESLint errors during build -08d8b1e (vercel) Fix React Server Components CVE vulnerabilities -9bdb0ac docs: update demo URL -8eb061c fix: correct ESLint config path for Vercel, add debug logs -a0a8695 fix: use baseConfig instead of overrideConfigFile for ESLint -8ded719 fix: remove unused path import -7e44891 fix: use overrideConfig instead of eslint.config.js -37426ec fix: remove eslint.config.js to avoid module loading error -c9ac1ab chore: update to Next.js 16, fix config for new version -0670732 feat: improve header responsiveness for mobile -a95b499 feat: add text labels to header buttons on mobile -4bac7d8 Add 10 unit tests + CI/CD workflow with green badge ← master HEAD -eb042a0 refactor: organize AI providers into separate functions ← dev -74b14ca feat: implement Gemini as fallback AI provider ← dev HEAD -``` - -### 1.4 Diferencias Clave: `dev` vs `master` - -| Aspecto | `master` | `dev` | -|---------|----------|-------| -| **Archivos modificados** | — | `route.ts`, `package.json`, `package-lock.json` | -| **Archivos nuevos** | — | Ninguno | -| **Archivos eliminados** | — | Ninguno | -| **Proveedor IA** | Solo Ollama | Ollama + Gemini (fallback automático) | -| **Estructura del código** | Monolítico en `POST` | Funciones separadas por responsabilidad | -| **Dependencias** | — | `@google/generative-ai` añadido | -| **Tests** | 6 archivos de test | Heredados de master (sin cambios) | - ---- - -## 2. Análisis de Estructura y Dependencias - -### 2.1 Estructura de Archivos (idéntica en master y dev) - -``` -CodeMp-AI/ -├── .github/workflows/ci.yml # CI/CD con GitHub Actions -├── .gitignore -├── LICENSE # MIT -├── README.md # Documentación principal -├── frontend/ # Aplicación Next.js -│ ├── __tests__/ # Tests unitarios (Jest) -│ │ ├── AnalysisButtons.test.tsx -│ │ ├── CodeEditor.test.tsx -│ │ ├── ErrorHandling.test.tsx -│ │ ├── LanguageDetection.test.tsx -│ │ ├── OllamaAPI.test.tsx -│ │ └── OllamaCommunication.test.tsx -│ ├── app/ -│ │ ├── api/ -│ │ │ ├── analyze/route.ts # ★ Núcleo: IA + ESLint -│ │ │ └── health/route.ts # Health check de Ollama -│ │ ├── favicon.ico -│ │ ├── globals.css # Estilos globales + Tailwind -│ │ ├── layout.tsx # Layout principal -│ │ └── page.tsx # Página principal -│ ├── components/ -│ │ ├── AnalysisSkeleton.tsx # Skeleton de carga animado -│ │ ├── CodeEditor.tsx # Editor CodeMirror 6 -│ │ ├── DemoBanner.tsx # Banner de modo demo -│ │ └── DiffViewer.tsx # Visor de cambios (diff) -│ ├── hooks/ -│ │ └── useTheme.tsx # Provider de tema (dark/light) -│ ├── public/ # Assets e imágenes -│ ├── package.json # Dependencias -│ ├── tsconfig.json # Config TypeScript -│ ├── next.config.ts # Config Next.js -│ ├── jest.config.ts # Config Jest -│ ├── jest.setup.ts # Setup de Jest -│ └── postcss.config.mjs # Config PostCSS/Tailwind -``` - -### 2.2 Dependencias Principales (package.json) - -| Dependencia | Propósito | -|-------------|-----------| -| `next` ^16.2.0 | Framework React (App Router) | -| `react` / `react-dom` ^18.3.1 | UI library | -| `eslint` ^9.24.0 | Linter de código (ejecutado en servidor) | -| `@codemirror/lang-javascript` ^6.2.4 | Editor de código JS/TS | -| `@codemirror/lang-python` ^6.2.1 | Editor de código Python | -| `@uiw/react-codemirror` ^4.25.5 | Wrapper React para CodeMirror | -| `framer-motion` ^12.36.0 | Animaciones UI | -| `react-diff-viewer-continued` ^4.1.2 | Visor de diferencias (diff) | -| **`@google/generative-ai` ^0.24.1** | ★ SDK de Gemini (SOLO en `dev`) | -| `@tailwindcss/postcss` ^4.1.4 | Estilos utility-first | -| `jest` / `@testing-library/*` | Tests unitarios | -| `@typescript-eslint/*` | Reglas ESLint para TypeScript | - ---- - -## 3. Análisis de la Integración con IA - -### 3.1 Arquitectura General - -``` -Usuario → CodeEditor (frontend) - ↓ POST /api/analyze {code} - ↓ - analyze/route.ts (Next.js API Route) - ↓ - ① runESLint(code) → {errors, fixedCode} - ↓ - ② ¿Hay errores? - ├── No → Devolver fixedCode (solo ESLint) - └── Sí → ¿Ollama disponible? - ├── Sí → analyzeWithOllama() - ├── No → analyzeWithGemini() [SOLO dev] - └── No AI → Modo demo - ↓ - ③ validateCorrection() [SOLO dev] - ↓ - ④ Respuesta JSON → Frontend -``` - -### 3.2 Integración en `master` (Producción Actual) - -**Archivo:** `frontend/app/api/analyze/route.ts` (191 líneas) - -- **Llamada a Ollama:** POST directo a `http://localhost:11434/api/generate` - - Modelo hardcodeado: `qwen2.5-coder:1.5b` - - Prompt hardcodeado con instrucciones de linting - - `stream: false` -- **Health check:** `isOllamaAvailable()` → `GET http://localhost:11434/api/tags` (timeout 2s) -- **Flujo:** ESLint → Ollama → devolución directa (sin validación posterior) -- **Modo demo:** Si Ollama no está disponible → mensaje informativo - -### 3.3 Integración en `dev` (Desarrollo) - -**Archivo:** `frontend/app/api/analyze/route.ts` (265 líneas, +74 líneas vs master) - -**Cambios significativos:** - -1. **Refactorización en funciones separadas:** - - `checkOllamaAvailability()` (renombrado desde `isOllamaAvailable()`) - - `runESLint(code)` (extraído, igual que master) - - **`analyzeWithOllama(code, errors)`** (extraído de `callOllama()`) - - **`analyzeWithGemini(code, errors, language?)`** ★ NUEVO - - **`detectLanguage(code)`** ★ NUEVO (detecta JS, Python, Rust, Go, C) - - **`validateCorrection(originalCode, correctedCode)`** ★ NUEVO - -2. **Proveedor Gemini como fallback:** - - SDK: `@google/generative-ai` - - Modelo: `gemini-2.0-flash` - - API Key: `process.env.GEMINI_API_KEY` - - Se ejecuta SOLO si Ollama no está disponible - - El prompt es similar al de Ollama pero incluye detección de lenguaje - - Limpia bloques de código markdown (```) de la respuesta - -3. **Lógica de selección de proveedor:** - ``` - if (ollamaAvailable) → analyzeWithOllama() - if (!usedProvider) → analyzeWithGemini() - if (!usedProvider) → modo demo - ``` - -4. **Validación de correcciones:** - - Se ejecuta ESLint sobre el código corregido por la IA - - Si introduce nuevos errores → se revierte al output de ESLint - - Función `validateCorrection()` reutilizable - -5. **Respuesta enriquecida:** - - Nuevo campo `usedProvider: 'ollama' | 'gemini' | null` - - Mensajes de resumen diferenciados por proveedor - -### 3.4 Puntos de Entrada/Salida de la Lógica de IA - -| Punto | Entrada | Salida | -|-------|---------|--------| -| `POST /api/analyze` | JSON `{code: string}` | JSON `{errores, resumen, codigoCorregido, mode, demoMessage}` | -| `GET /api/health` | — | JSON `{available: boolean}` | -| `analyzeWithOllama()` | `code: string, errors: LintMessage[]` | `string` (código corregido) | -| `analyzeWithGemini()` | `code: string, errors: LintMessage[], language?: string` | `string | null` | -| `validateCorrection()` | `originalCode, correctedCode` | `string` (corregido o revertido) | - ---- - -## 4. Análisis de Tests - -**6 archivos de test en `frontend/__tests__/`** (Jest + Testing Library): - -| Archivo | Cobertura | -|---------|-----------| -| `AnalysisButtons.test.tsx` | Renderizado de botón "Run Analysis" | -| `CodeEditor.test.tsx` | Renderizado del editor con valor inicial | -| `ErrorHandling.test.tsx` | Manejo de errores HTTP, red y modo demo | -| `LanguageDetection.test.tsx` | Selección de lenguaje en el editor | -| `OllamaAPI.test.tsx` | Llamada a `/api/analyze` y parseo de respuesta | -| `OllamaCommunication.test.tsx` | Health check + envío/recepción de correcciones | - -**Nota:** Los tests existen en `master` y `dev`. La rama `dev` NO añade tests nuevos para Gemini ni para las nuevas funciones extraídas. - -**Rama Vercel:** La rama `origin/vercel/...` **elimina** Jest y Testing Library del `package.json` (probablemente para reducir el bundle de deploy). - ---- - -## 5. Evaluación de Integración con `llm_bridge` - -### 5.1 Estado Actual de `dev` vs Master para la Integración - -La rama `dev` **ya ha dado pasos significativos** hacia una arquitectura que facilitaría la integración con `llm_bridge`: - -| Aspecto | Antes (master) | Ahora (dev) | ¿Facilita llm_bridge? | -|---------|----------------|-------------|----------------------| -| **Acoplamiento** | Ollama hardcodeado en `POST` | Funciones separadas por proveedor | ✅ Sí — hay un lugar claro donde inyectar | -| **Proveedores** | 1 (Ollama) | 2 (Ollama + Gemini) con fallback | ✅ Sí — el patrón de fallback es extensible | -| **Validación** | No existía | `validateCorrection()` reusable | ✅ Sí — se reutilizaría igual | -| **Detección lenguaje** | No existía | `detectLanguage()` | ✅ Sí — útil para prompts contextuales | -| **Métricas** | No | No | ❌ No — llm_bridge las proveería | - -### 5.2 ¿Qué tan factible es integrar `llm_bridge`? - -**Factibilidad: ALTA**, pero con la misma salvedad del informe anterior: `llm_bridge` es Python y CodeMp-AI es TypeScript. - -La rama `dev` ya estableció un **patrón de abstracción de proveedores** (funciones `analyzeWithOllama`, `analyzeWithGemini`). Para integrar `llm_bridge` se seguiría el mismo patrón: - -``` -analyzeWithOllama() → analyzeWithLLMBridge(provider: 'ollama') -analyzeWithGemini() → analyzeWithLLMBridge(provider: 'gemini') - analyzeWithLLMBridge(provider: 'openai') - analyzeWithLLMBridge(provider: 'bedrock') -``` - -El **cambio conceptual es mínimo**: donde hoy se llama a una función que hace HTTP directo al proveedor, se llamaría a una función que hace HTTP al microservicio `llm_bridge`, que a su vez usa `create_llm()`. - -### 5.3 Beneficios Específicos para `dev` - -1. **Unificación de providers:** Hoy `analyzeWithOllama()` hace fetch directo; `analyzeWithGemini()` usa SDK. Con `llm_bridge` ambas serían llamadas idénticas al microservicio. -2. **Métricas gratuitas:** `LLMResponse` ya incluye `latency_ms`, `total_tokens` — métricas que hoy CodeMp-AI no captura. -3. **Modo mock nativo:** El provider `mock` de `llm_bridge` reemplazaría el "modo demo" artesanal actual. -4. **OpenAI-compatible:** El provider `openai` de `llm_bridge` + `base_url` puede apuntar a Ollama, vLLM, o cualquier API compatible. Esto permitiría unificar todos los providers locales bajo un mismo código. - -### 5.4 Desafíos Persistentes - -| Desafío | Impacto | -|---------|---------| -| **Microservicio Python** | Necesario como puente (TypeScript ↔ Python) | -| **Despliegue extra** | El microservicio debe correr junto a Next.js | -| **Tests existentes** | Los tests de `OllamaAPI.test.tsx` y `OllamaCommunication.test.tsx` mockean `fetch` y necesitarían actualizarse para apuntar al microservicio | - -### 5.5 Archivos que se Verían Afectados - -| Archivo | Cambio | -|---------|--------| -| `frontend/app/api/analyze/route.ts` | Reemplazar `analyzeWithOllama()` y `analyzeWithGemini()` por una sola función que llame al microservicio `llm_bridge` | -| `frontend/app/api/health/route.ts` | Redirigir health check al microservicio | -| `frontend/__tests__/OllamaAPI.test.tsx` | Actualizar mocks para nueva URL | -| `frontend/__tests__/OllamaCommunication.test.tsx` | Actualizar mocks para nuevo endpoint | -| `frontend/package.json` | Sin cambios (no se añaden deps Node.js) | -| **(Nuevo)** `backend/app.py` | Microservicio Flask/FastAPI | -| **(Nuevo)** `backend/requirements.txt` | `llm-bridge`, `flask`, `gunicorn` | -| **(Nuevo)** `backend/Dockerfile` | Contenedor del microservicio | -| **(Nuevo)** `backend/config.yaml` | Config de proveedores (opcional) | - ---- - -## 6. Conclusión - -### Estado del Proyecto -- `master`: Versión estable con **solo Ollama** como proveedor IA -- `dev`: **Ya evolucionó** hacia una arquitectura multi-proveedor (Ollama + Gemini) con funciones separadas, validación y detección de lenguaje -- La rama `dev` está **alineada conceptualmente** con la estrategia de `llm_bridge` — solo falta el puente Python - -### Recomendación -La integración con `llm_bridge` es **altamente recomendable** si se planea: -1. Soportar OpenAI, AWS Bedrock u otros proveedores cloud -2. Obtener métricas de uso (tokens, latencia) -3. Tener un modo mock robusto para tests -4. Centralizar la gestión de credenciales - -La rama `dev` ya hizo el 50% del trabajo arquitectónico. `llm_bridge` completaría el otro 50% proporcionando la capa de abstracción real sobre los proveedores. diff --git a/SANTADER-IA/04_PLAN_ACCION_AGENTE.md b/SANTADER-IA/04_PLAN_ACCION_AGENTE.md deleted file mode 100644 index 7459842..0000000 --- a/SANTADER-IA/04_PLAN_ACCION_AGENTE.md +++ /dev/null @@ -1,694 +0,0 @@ -# PLAN DE ACCIÓN — Microservicio `llm_bridge` en CodeMp-AI - -**Versión:** 2.1 -**Última actualización:** 2026-06-22 - ---- - -## 🛡️ REGLAS DE SEGURIDAD (OBLIGATORIAS) - -La IA debe cumplir estas reglas en TODAS las fases: - -### 1. Verificar rama `dev` -Antes de cualquier modificación, ejecutar `git branch`. Si no se está en `dev`, **detener la ejecución** y notificar al usuario. - -### 2. Backups automáticos -Antes de modificar un archivo existente, crear una copia con extensión `.backup` en la misma carpeta: -- `route.ts` → `route.ts.backup` -- `health/route.ts` → `health/route.ts.backup` -- `README.md` → `README.md.backup` - -### 3. Prohibido ejecutar comandos destructivos -`rm -rf`, `git reset --hard`, `git push --force` o cualquier comando que elimine datos sin confirmación explícita del usuario. - -### 4. Confirmación entre fases -Al terminar una fase, preguntar: -> "La Fase X ha finalizado. ¿Confirmas que quieres continuar con la Fase Y?" - -No avanzar hasta recibir confirmación. - -### 5. Registro de acciones -Cada vez que se cree o modifique un archivo, la IA debe registrar en la conversación: -- Qué archivo se creó/modificó -- Resumen breve de los cambios - ---- - -## ARQUITECTURA REAL - -``` -Frontend (Next.js) → /api/analyze → backend (Flask :5000) → AI Provider - ├── mock → respuesta directa - ├── openai → OpenAI SDK (Ollama si base_url) - ├── google → llm_bridge → Gemini - ├── claude → llm_bridge → Claude - └── grok → llm_bridge → Grok -``` - -**API del microservicio (`POST /chat`):** -```json -{ - "provider": "openai", - "model": "qwen2.5-coder:1.5b", - "base_url": "http://localhost:11434/v1", - "messages": [{"role": "user", "content": "..."}], - "temperature": 0.7 -} -→ {"content": "...", "total_tokens": 0, "latency_ms": 0, "model": "..."} -``` - ---- - -## ESTADO DE PROGRESO - -> **Fase actual:** ✅ Proyecto CodeMp-AI completado -> **Próximo paso:** Colaboración con Santander (ver `06_PLAN_COLABORACION_SANTANDER.md`) - -| Fase | Estado | -|------|--------| -| **Fase 1:** Microservicio Python (`backend/`) | ✅ Completada | -| **Fase 2:** Integrar frontend con microservicio | ✅ Completada | -| **Fase 3:** Health check + Tests | ✅ Completada | -| **Fase 4:** Dockerizar + Documentar | ⏳ Pendiente (futuro) — ver nota al final | -| **Fase 5:** Selector de modelo IA en UI | ✅ Completada | -| **Fase 6:** Colaboración con Santander | ⬜ Pendiente — ver `06_PLAN_COLABORACION_SANTANDER.md` | - ---- - -## INSTRUCCIONES PARA LA IA - -### COMANDOS DE ACTIVACIÓN - -La IA responde a **dos comandos**: - -**`"sigamos"`** — Continuar con la fase actual (reanudar trabajo en progreso). -**`"ejecutar plan"`** — Iniciar el plan desde cero (Fase 1 si no hay progreso, o retomar desde donde se quedó). - -Ambos comandos siguen el mismo flujo: - -Cuando el usuario diga **"sigamos"** o **"ejecutar plan"**, debes: -1. Leer este archivo -2. **Cumplir las 🛡️ REGLAS DE SEGURIDAD** (verificar rama `dev`, backups, etc.) -3. Identificar la **Fase actual** -4. Ejecutar las tareas de esa fase en orden -5. **Registrar cada acción** (archivo creado/modificado + resumen) -6. Al terminar la fase, **pedir confirmación** antes de avanzar a la siguiente -7. Actualizar el estado en ESTADO DE PROGRESO - -Los comandos `npm install`, `pip install`, `git add`, `git commit`, etc. SÍ están permitidos, siempre que se cumplan las reglas de seguridad. - ---- - -# FASE 1: MICROSERVICIO PYTHON — ✅ COMPLETADA - -**Objetivo cumplido:** Crear el servicio `backend/` que expone los endpoints `/chat` y `/health`. - -### Archivos creados - -| Archivo | Descripción | -|---------|-------------| -| `backend/requirements.txt` | flask, llm-bridge, openai, gunicorn | -| `backend/app.py` | Microservicio Flask con 3 handlers: mock, openai, llm_bridge | -| `backend/.env.example` | Plantilla de variables de entorno | -| `backend/venv/` | Entorno virtual Python (dependencias instaladas) | - -### Estrategia de implementación (app.py) - -```python -# Mock → respuesta directa sin LLM -if provider == 'mock': - return jsonify({'content': 'mock response', 'total_tokens': 10, ...}) - -# OpenAI/Ollama → OpenAI SDK directo con base_url opcional -elif provider == 'openai': - client = OpenAI(api_key='...', base_url=base_url) # base_url → Ollama - response = client.chat.completions.create(...) - -# Cloud providers → llm_bridge (async) -elif provider in ('google', 'claude', 'grok'): - client = await create_chat_client(api_type=..., api_keys=..., ...) - response = await client.generate_non_stream_response() -``` - ---- - -# FASE 2: INTEGRAR FRONTEND CON MICROSERVICIO - -**Objetivo:** Reemplazar las llamadas directas a Ollama/Gemini en `route.ts` por llamadas al microservicio `backend/app.py`. - -## Paso 2.1 — Modificar frontend/app/api/analyze/route.ts - -### Cambios específicos: - -1. **Añadir constante** al inicio del archivo: - ```typescript - const LLM_BRIDGE_URL = process.env.LLM_BRIDGE_URL || 'http://localhost:5000'; - ``` - -2. **Eliminar funciones:** - - `checkOllamaAvailability()` — el health check va al microservicio - - `analyzeWithOllama()` — se reemplaza por llamada genérica - - `analyzeWithGemini()` — se reemplaza por llamada genérica - -3. **Crear función genérica** `analyzeWithBridge()`: - ```typescript - interface BridgeRequest { - provider: string; - model: string; - base_url?: string; - messages: { role: string; content: string }[]; - temperature?: number; - } - - interface BridgeResponse { - content: string; - total_tokens: number; - latency_ms: number; - model: string; - } - - async function analyzeWithBridge(config: BridgeRequest): Promise { - try { - const response = await fetch(`${LLM_BRIDGE_URL}/chat`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(config), - }); - if (!response.ok) return null; - return await response.json(); - } catch { - console.error('Error calling LLM bridge:', error); - return null; - } - } - ``` - -4. **Modificar el POST handler** para usar `analyzeWithBridge()`: - - **Para Ollama (local):** - ```typescript - const llmResult = await analyzeWithBridge({ - provider: 'openai', - model: 'qwen2.5-coder:1.5b', - base_url: 'http://localhost:11434/v1', - messages: [ - { role: 'system', content: systemPrompt }, - { role: 'user', content: userPrompt }, - ], - temperature: 0.7, - }); - ``` - - **Para Gemini:** - ```typescript - const llmResult = await analyzeWithBridge({ - provider: 'google', - model: 'gemini-2.0-flash', - messages: [ - { role: 'system', content: systemPrompt }, - { role: 'user', content: userPrompt }, - ], - temperature: 0.7, - }); - ``` - - **Para Claude:** - ```typescript - const llmResult = await analyzeWithBridge({ - provider: 'claude', - model: 'claude-sonnet-4-20250514', - messages: [ - { role: 'system', content: systemPrompt }, - { role: 'user', content: userPrompt }, - ], - temperature: 0.7, - }); - ``` - -5. **Flujo del POST handler (simplificado):** - ```typescript - export async function POST(req: Request) { - const { code } = await req.json(); - const lintResult = await runESLint(code); - - if (lintResult.errors.length === 0) { - return NextResponse.json({ codigoCorregido: lintResult.fixedCode, mode: 'full' }); - } - - // Intentar Ollama primero - let result = await analyzeWithBridge({ provider: 'openai', base_url: 'http://localhost:11434/v1', ... }); - let usedProvider = result ? 'ollama' : null; - - // Fallback a Gemini - if (!result) { - result = await analyzeWithBridge({ provider: 'google', ... }); - usedProvider = result ? 'gemini' : null; - } - - // Fallback a Claude - if (!result) { - result = await analyzeWithBridge({ provider: 'claude', ... }); - usedProvider = result ? 'claude' : null; - } - - // Validar corrección - const finalCode = result ? await validateCorrection(lintResult.fixedCode, result.content) : lintResult.fixedCode; - - return NextResponse.json({ - errores: lintResult.errors, - codigoCorregido: finalCode, - mode: usedProvider ? 'full' : 'demo', - usedProvider, - }); - } - ``` - -6. **Mantener sin cambios:** - - `runESLint()` — no tocar - - `validateCorrection()` — no tocar - - `detectLanguage()` — no tocar - - Estructura de respuesta JSON — misma interfaz - -## Paso 2.2 — Añadir variable de entorno - -**Archivo:** `frontend/.env.local` - -``` -LLM_BRIDGE_URL=http://localhost:5000 -``` - -## ✅ Criterios de éxito de Fase 2 - -- [ ] `route.ts` ya NO contiene `checkOllamaAvailability()` -- [ ] `route.ts` ya NO contiene `analyzeWithOllama()` -- [ ] `route.ts` ya NO contiene `analyzeWithGemini()` -- [ ] `route.ts` SÍ contiene `analyzeWithBridge()` genérica -- [ ] Los prompts se envían como `messages` estructurados (system + user) -- [ ] Soporta múltiples providers con fallback automático -- [ ] Se mantienen `runESLint()`, `validateCorrection()`, `detectLanguage()` -- [ ] La respuesta JSON al frontend es idéntica (mismos campos) -- [ ] `frontend/.env.local` existe con `LLM_BRIDGE_URL` - ---- - -# FASE 3: HEALTH CHECK + TESTS - -**Objetivo:** Actualizar el health check para que apunte al microservicio y crear tests del backend. - -## Paso 3.1 — Modificar health/route.ts - -Reemplazar todo el contenido: - -```typescript -import { NextResponse } from 'next/server'; - -const LLM_BRIDGE_URL = process.env.LLM_BRIDGE_URL || 'http://localhost:5000'; - -export async function GET() { - try { - const response = await fetch(`${LLM_BRIDGE_URL}/health`); - const data = await response.json(); - return NextResponse.json({ available: data.status === 'ok' }); - } catch { - return NextResponse.json({ available: false }); - } -} -``` - -## Paso 3.2 — Tests del backend (Python) - -**Archivo:** `backend/tests/test_service.py` - -```python -import pytest -from app import app - -@pytest.fixture -def client(): - app.config['TESTING'] = True - with app.test_client() as client: - yield client - -def test_health(client): - resp = client.get('/health') - assert resp.status_code == 200 - assert resp.get_json()['status'] == 'ok' - -def test_chat_mock(client): - resp = client.post('/chat', json={ - 'provider': 'mock', - 'messages': [{'role': 'user', 'content': 'Hello'}], - }) - assert resp.status_code == 200 - data = resp.get_json() - assert 'content' in data - assert 'total_tokens' in data - assert 'latency_ms' in data - -def test_chat_no_messages(client): - resp = client.post('/chat', json={}) - assert resp.status_code == 400 - -def test_chat_unknown_provider(client): - resp = client.post('/chat', json={ - 'provider': 'nonexistent', - 'messages': [{'role': 'user', 'content': 'Hello'}], - }) - assert resp.status_code == 400 -``` - -Ejecutar con: -```bash -cd backend -pip install pytest -pytest tests/ -v -``` - -## Paso 3.3 — Tests del frontend - -- `OllamaAPI.test.tsx` — actualizar mocks si la URL cambia (request sigue siendo `/api/analyze`) -- `OllamaCommunication.test.tsx` — verificar que health check mock funciona con nuevo endpoint - -Ejecutar: -```bash -cd frontend -npm test -``` - -## ✅ Criterios de éxito de Fase 3 - -- [ ] `health/route.ts` redirige al microservicio (`backend/app.py`) -- [ ] `backend/tests/test_service.py` existe con 4+ tests -- [ ] Tests del backend pasan (`pytest`) -- [ ] Tests del frontend siguen pasando (`npm test`) - ---- - -# FASE 4: DOCKERIZAR + DOCUMENTAR - -**Objetivo:** Empaquetar el microservicio y documentar la arquitectura final. - -## Paso 4.1 — Dockerfile - -**Archivo:** `backend/Dockerfile` - -```dockerfile -FROM python:3.11-slim - -WORKDIR /app - -COPY requirements.txt . -RUN pip install --no-cache-dir -r requirements.txt - -COPY app.py . - -EXPOSE 5000 - -CMD ["gunicorn", "--bind", "0.0.0.0:5000", "app:app"] -``` - -## Paso 4.2 — docker-compose.yml raíz - -**Archivo:** `docker-compose.yml` (en raíz del proyecto) - -```yaml -services: - llm-bridge: - build: ./backend - ports: - - "5000:5000" - environment: - - GOOGLE_API_KEY=${GOOGLE_API_KEY:-} - - GEMINI_API_KEY=${GEMINI_API_KEY:-} - - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-} - - XAI_API_KEY=${XAI_API_KEY:-} - - frontend: - build: ./frontend - ports: - - "3000:3000" - environment: - - LLM_BRIDGE_URL=http://llm-bridge:5000 - depends_on: - - llm-bridge -``` - -## Paso 4.3 — README.md (ya actualizado parcialmente) - -Verificar que README.md incluya: -- Diagrama de arquitectura (Frontend → Next.js API → Microservicio → AI Provider) -- Requisitos: Node.js 18+, Python 3.9+, Ollama (opcional) -- Instrucciones de inicio rápido (backend + frontend) -- Tabla de proveedores y sus API keys -- Variables de entorno documentadas -- Tests - -## ✅ Criterios de éxito de Fase 4 - -- [ ] `backend/Dockerfile` existe y se construye sin errores -- [ ] `docker-compose.yml` raíz existe -- [ ] `docker-compose up` arranca ambos servicios -- [ ] README.md completo con toda la documentación - ---- - -# FASE 5: SELECTOR DE MODELO IA EN UI — ✅ COMPLETADA - -**Objetivo:** Permitir al usuario elegir qué proveedor IA usar directamente desde la interfaz. - -## Cambios realizados - -### route.ts -- Ahora acepta `provider` y `model` opcionales en el body del POST -- Si se envía `provider`, solo intenta ese proveedor específico -- Si no se envía, mantiene el fallback automático original - -### page.tsx -- Agregado estado `selectedProvider` -- Dropdown `