Spaces:
Sleeping
Sleeping
Commit History
Yesterday
-
fix(deploy): copiar supabase/migrations en Dockerfile y deshabilitar cache de statements para pgbouncer
fab4746 -
fix(byok): inyectar Depends(get_user_keys) en endpoints y aislar credenciales en produccion
c601882 -
f9: implementar conexion BYOK dinamica supabase y auto-migracion de esquema backend
- backend/db/session.py: cacheo por DSN de AsyncEngine y async_sessionmaker, ensure_schema_initialized(dsn) - backend/api/deps.py: soporte X-User-Database-Url en UserKeys.database_url, fallback a DATABASE_URL solo si no es placeholder, get_db usa DSN y lanza 503 si no hay - backend/api/credentials.py: POST /api/credentials/connect-db y GET /api/credentials/status actualizado para headers X-User-* - backend/services/parcels.py: pass keys.database_url a get_sessionmaker en run_indices_backfill - tests/unit/test_byok_db_session.py: pruebas unitarias de resolucion de DSN, cache de ensure_schema y endpoint connect-db - docs: marcar Fase 9 como completadac56e3e8
2 days ago
-
merge: fase 5 api y backfill selectivo e incremental de indices
534bf3e -
feat(api): soportar selección y backfill incremental de índices satelitales
Se extienden los esquemas FieldIn/FieldUpdate con crop_variety y selected_indices validados contra el catálogo de cinco índices. El servicio de parcelas generaliza run_ndvi_backfill en run_indices_backfill, persiste cada serie solicitada y mantiene el wrapper NDVI retrocompatible. Los routers /api/fields y /api/vegetation/reprocess agendan solo los índices elegidos o el diferencial añadido, exponen selected_indices/calculated_indices y permiten el reproceso selectivo. La integración con Fase 4 se resuelve con inspección de firma y getattr para no romper repositorios o mocks previos. Co-Authored-By: DeepSeek <noreply@deepseek.com>85ebce0 -
feat(repo): soporta índices seleccionados e índices calculados
Extiende create_field con crop_variety y selected_indices (default ['ndvi']), incluye la columna en get_field y list_fields, y permite actualizarla vía update_field_attributes. Añade get_calculated_indices para leer los index_type distintos ya persistidos en vegetation_indices y habilitar el backfill incremental. Co-Authored-By: DeepSeek <noreply@deepseek.com>17acdc0
10 days ago
-
merge: fase 2 esquema ddl y migraciones versionadas
e404865 -
feat(db): agregar migración inicial PostGIS idempotente
Se crea 0001_initial_schema.sql con PostGIS, las siete tablas del modelo (fields, vegetation_indices, weather_data, user_profiles, plant_counts, chat_messages y events), constraints, índices GIST/JSONB/FK y RLS condicional para Supabase y PostgreSQL local. El migrador normaliza DSN de SQLAlchemy, omite *.down.sql y falla si no hay migraciones. Se agregan tests unitarios y de integración; la migración se validó dos veces contra PostGIS 16 y el aislamiento RLS se comprobó con dos usuarios. Co-Authored-By: DeepSeek <noreply@deepseek.com>c521d70 -
fix(backend): corrige imports y longitud de línea reportados por Ruff
Se movieron los imports de httpx, dateutil y SQLAlchemy al encabezado de weather.py para eliminar los E402, y se partieron las cadenas largas de logging y consultas SQL en weather.py y repositories.py para respetar el límite de 100 caracteres. También se corrigió el typo "Persitiendo" en el log de persistencia. Co-Authored-By: DeepSeek <noreply@deepseek.com>b872632
-
style(api): wrap long line in weather.py for ruff compatibility
ad28490 -
fix(weather): fix hourly 0 degrees chart bug due to timezone and end timestamp query limit
1599ae4 -
feat(weather): map database weather fields to mockup vocab and add detailed backend logging
14a00e1 -
perf(weather): cast parameters to timestamps and support raw data queries for client-side processing
a6ba435
-
feat(backend): implementa endpoint PATCH de parcelas y esquemas Pydantic
Se añadió el esquema 'FieldUpdate' para validación de atributos opcionales y se actualizó 'FieldOut'. También se implementó el router 'PATCH /api/fields/{field_id}' en fields.py para recibir las actualizaciones parciales, llamar al servicio de parcelas y emitir el evento de telemetría 'field_updated'.ab47166 -
feat(db): agrega columnas de configuracion de parcela en base de datos y repositorio
Se implementó la función 'update_field_attributes' en repositories.py para realizar una actualización PATCH dinámica sobre los 10 nuevos atributos de la parcela. Se modificaron también las funciones de lectura para mapear y retornar las nuevas columnas desde la base de datos Supabase, e integrado a parcels.py.e98298e
-
feat(chat): añade contexto de chat por parcela y sincroniza tareas
Se integró el parámetro 'field_id' en la base de datos (chat_messages) y APIs para acotar el historial y las respuestas del asistente agéntico según la parcela activa. Además, se reestructuró 'docs/task/tareas.md' documentando las fases 13, 14 y 15 como finalizadas y se corrigieron advertencias de longitud de línea (Ruff) en todo el backend.3aee0ae -
feat(ui): añadir weather_data al explorador de datos
6d27062 -
feat(weather): migrar consulta de open-meteo de on-demand a persistencia horaria en base de datos
784f348
-
feat(db): elimina tabla ndvi_timeseries (legacy)
Migración 0006 DROP TABLE ndvi_timeseries y sus políticas RLS. Elimina la tabla del ALLOWED_TABLES en data.py, remueve funciones deprecated (upsert_ndvi_points, get_ndvi_series) de repositories.py, actualiza frontend ER diagram y tests de integración.29437e9 -
style(ndvi): migra ndvi_timeseries legacy a vegetation_indices
Elimina fallback de ndvi_timeseries en get_index_series(). Marca upsert_ndvi_points() y get_ndvi_series() como DEPRECATED. _describe_trend() usa mean_value en vez de mean_ndvi. Tests actualizados a upsert_index_points/get_index_series. data.py añade vegetation_indices a ALLOWED_TABLES. check constraint de 0004 incluye 'ndvi'. Nueva migración 0005 copia datos legacy.f841950 -
feat(vegetation): añade endpoint reprocess y eventos de telemetría en rutas
Crea POST /api/vegetation/reprocess con modos indices/weather/all. Corrige route ordering (reprocess antes que /{index}). Añade emit_event() en fields.py, ndvi.py, parcels.py para trazabilidad de backfill y consultas de índice. Parcels usa index_series_monthly + upsert_index_points (NDVI genérico).9070b0c -
feat(telemetry): agrega logging de agrovision.* y emisión de eventos backend
Añade _setup_agrovision_logging() en lifespan de main.py para emitir logs agrovision.* a stdout. Crea emit() en events.py para que el backend publique eventos directo al buffer sin HTTP. En remote_sensing.py, añade logger y emite eventos copernicus_stats/copernicus_process.28e54f7 -
feat(weather): agrega humedad relativa y viento máximo a series climáticas
Amplía Open-Meteo con wind_speed_10m_max (daily) y relative_humidity_2m (hourly). aggregate_weather_monthly ahora acepta bloque horario y produce humidity_mean y wind_max. open_meteo() descarga ambos bloques. Tests actualizados.9fab384 -
feat(teledeteccion): añade índices espectrales EVI, SAVI, NDWI, NDRE (Fase 13)
Nuevos 4 índices sobre Sentinel-2: core/indices.py (funciones puras), remote_sensing.py (evalscripts genéricos + index_series_monthly/index_heatmap_png), api/vegetation.py (router parametrizado), migración 0004_indices.sql, repositorios upsert/get, selector UI con rangos dinámicos, y 14 tests unitarios.8f8389b -
style: aplica formato ruff a archivos del backend
Correcciones automáticas de ruff format en 7 archivos: data.py, deps.py, geometry.py, ndvi.py, agent.py, test_db.py, test_teledeteccion.py. Sin cambios de lógica.bbe2c25
-
feat(fase-11-12): explorador de datos y visor de telemetría en UI
Fase 11: Pestaña Explorador de Datos con GET /api/data/{table} y POST /api/data/query (solo SELECT, máx 1000 filas). Fase 12: Endpoint GET /api/events/all para eventos persistidos, modal de telemetría con fallback a buffer en memoria, y status dinámico (verde/ámbar/rojo) según credenciales disponibles vía /api/credentials/status.50b8a66 -
feat: add data explorer tab, enforce BYOK in production, detect env
df71cfc -
build: consolida y optimiza Dockerfile (1 solo, no-root, libs mínimas, sin cache de wheels) + compose/render
13f1a88 -
feat(seguridad): rate limiting en /api + cabeceras de hardening (Fase 10)
7afd4d9 -
refactor: elimina Shiny (dashboard, run_ui, deps) y el deploy a shinyapps (Fase 10)
22026b0 -
feat(telemetria): endpoint /api/events, ring buffer y tabla events (Fase 9)
cf2d03b -
feat(ui): click en parcela vuela a su polígono + dibuja parcelas en el mapa
- /api/fields incluye geojson (ST_AsGeoJSON) por parcela. - Mapa de Creación de Parcelas dibuja los polígonos guardados (capa verde) y hace fitBounds al cargar; click en un item de la lista -> flyToBounds del polígono. - Verificado con Playwright (click en 'Lote NDVI' vuela a su polígono; 0 errores).d17e4f4 -
fix(ui): sidebar responsive robusto + mapa (satélite/relieve) + parcela demo + botón .env
- Sidebar: estado por CSS propio (is-open móvil / is-collapsed desktop) porque Tailwind v4 usa la propiedad 'translate' y el transform inline no la cancelaba; plegar/reabrir en desktop, drawer + backdrop en móvil (backdrop md:hidden para no interceptar en desktop). - Mapa de parcelas: capas Satélite (Esri) / Normal (OSM) / Relieve (OpenTopoMap), centrado en Lomas de Lachay; botón 'Cargar parcela demo (Lomas de Lachay)'. - Credenciales: botón 'Revisar .env del servidor' + endpoint GET /api/credentials/status (solo presencia, sin valores) para usar las llaves del .env sin reescribirlas. - Verificado con Playwright (desktop plegado, móvil drawer, satélite, .env detectado).ef1afea -
feat(ui): UI Astro completa servida por el gateway (Fase 8 — vistas, responsive, plegable)
- index.astro: SPA hash-routing con los 6 módulos (look del mockup), responsive + sidebar/footer plegables; Leaflet+Leaflet-draw (parcelas), Chart.js (NDVI/clima), heatmap, chat, credenciales efímeras (X-User-* en memoria), API por fetch relativo. - main.py: monta StaticFiles(html=True) en / (tras /api y /shiny) -> sirve la UI Astro. - scripts/build_ui.ps1: pnpm build -> backend/static. backend/Dockerfile: etapa Node compila Astro y la copia. docker-compose: sin servicio ui; frontend/Dockerfile eliminado. - ejecucion.md: flujo de UI Astro (gateway en / · dev :4321 · Shiny legacy :8001). - Verificado en vivo con Playwright (capturas en .playwright-mcp/).26161c7
-
feat(ui): Shiny -> backend/dashboard.py (legacy) + scaffold Astro+Tailwind (Fase 8, SF8.1)
- Reubica la UI Shiny a backend/dashboard.py (montable en /shiny, legacy); frontend/ queda para Astro. Ajusta run_ui.ps1 y README al nuevo path. - Scaffold Astro 5 + Tailwind v4 (plugin @tailwindcss/vite, NO @astrojs/tailwind): package.json, astro.config.mjs (output static + inlineStylesheets 'always' = Regla de Oro + proxy /api y /shiny en dev), tsconfig, src/pages/index.astro, src/styles/global.css. - pnpm-workspace.yaml (allowBuilds) para que pnpm 11 corra esbuild/sharp; build verificado.68ec720 -
feat(ui): plataforma Shiny de 6 módulos + soporte backend para la UI (Fase 6)
- frontend/app.py: 6 nav_panel (Resumen, Creación de Parcelas con ipyleaflet+DrawControl, Teledetección con Plotly NDVI 5 años/clima + heatmap, Conteo EN DESARROLLO, Asistente RAG, Credenciales efímeras). Consume el gateway con cabeceras X-User-* efímeras. - backend: repositories.get_field(+centroide)/get_field_geojson; /api/fields devuelve lon/lat; /api/ndvi/raster acepta field_id. - Deps UI: shinywidgets, ipyleaflet, plotly. - Verificado: backend y UI levantan en local (HTTP 200); ruff limpio; suite sin regresión.820f460 -
feat(agent): asistente RAG con function calling + memoria (Fase 5)
- backend/services/tools.py: 3 herramientas tipadas (tendencia NDVI, contexto climático, densidad [en desarrollo]) + TOOLS_SCHEMA + dispatch. - backend/services/agent.py: orquestación Groq/Llama 3 (OpenAI-compatible vía httpx), bucle de tool-calling y memoria en chat_messages. - backend/api/chat.py: POST /api/chat (no-streaming; SSE diferido). - repositories.get_field_by_name (con centroide para el clima). - Tests: unit (schema, _describe_trend) + integración en vivo (Groq llama la herramienta NDVI end-to-end). 58 passed, ruff limpio.9837673 -
feat(api): gateway + parcelas + teledetección NDVI/clima (Fase 3)
- backend/api/deps.py: proxy efímero BYOK (X-User-* con fallback DEV_*) + get_db. - backend/services/remote_sensing.py: NDVI vía Sentinel Hub en CDSE (Statistical API serie mensual 5 años + Process API heatmap PNG); OAuth client_credentials. - backend/services/weather.py: Open-Meteo (sin llave) + agregación mensual. - backend/services/parcels.py: CRUD + backfill NDVI de 5 años en background. - backend/api/{fields,ndvi,weather}.py: /api/fields (CRUD), /api/ndvi (+/raster), /api/weather. - main.py monta los routers nuevos; repositories.delete_field por id. - Tests: unitarios (parse stats, agregación clima, deps) + integración en vivo (NDVI real + cadena parcela->NDVI->persistencia). 52 passed, ruff limpio. - Desviación: se usa Sentinel Hub (CDSE) en vez de pystac-client+rioxarray.c9bb7d3 -
feat(db): persistencia Supabase BYOK - migraciones PostGIS/RLS + repos async (Fase 2)
- supabase/migrations/0001_init.sql (PostGIS+pgmq, 4 tablas, índices GIST/GIN) y 0002_rls.sql (RLS por usuario, efectiva con Supabase Auth). - backend/db: session.py (engine async, Session pooler), migrate.py (aplicador), repositories.py (CRUD parcelas, upsert/lectura NDVI idempotente, memoria chat; SQLAlchemy Core text() + PostGIS por robustez con asyncpg). - Deps: sqlalchemy, asyncpg, geoalchemy2, shapely, python-dateutil. - Tests integración contra Supabase real (tests/integration/test_db.py): 4 verdes. - BYOK monousuario: user_id sin FK a auth.users; conteo/PGMQ creados pero inactivos.8d80da2 -
feat(core): esquemas de dominio y motores puros NDVI/GSD/densidad (Fase 1)
- backend/core/schemas.py: FieldIn (valida polígono cerrado 4326), FieldOut, NDVIPoint, WeatherPoint, ChatMessage. - backend/core/ndvi.py: ndvi(), zonal_stats(), aggregate_monthly() (1 punto/mes). - backend/core/geometry.py: gsd_cm_per_px(), density_per_ha(), geodesic_area_m2(). - Tests unitarios (TDD): test_domain_schemas, test_ndvi, test_geometry (verde, ruff limpio).603f109 -
feat: ortomosaico de arándano simulado y mock por detección de blobs
Añade scripts/make_sample_orthomosaic.py que genera un ortomosaico de arándano de prueba (hileras de arbustos verdes con huecos de siembra y malezas amarillas, determinista por semilla). Mejora MockInferenceAdapter para detectar los arbustos por color (blobs HSV) cuando la imagen los contiene, de modo que las cajas caen sobre ellos y el conteo coincide con el real; en otras imágenes mantiene el fallback aleatorio. Incluye pruebas del generador y de la coherencia con el mock. Verificado en vivo: sobre la imagen generada (112 arbustos, 5 malezas) el conteo es exacto. La imagen PNG no se versiona (se regenera).1cec427 -
feat: modo mock para validar el flujo de conteo sin modelo real
Añade MockInferenceAdapter y la fábrica create_adapter seleccionable con MODEL_BACKEND=mock|onnx. Con COUNTING_ENABLED=true y MODEL_BACKEND=mock, /api/count devuelve detecciones falsas plausibles (deterministas por imagen) para validar el flujo completo (carga → conteo → métricas → overlay → UI) sin el modelo real; la UI muestra el aviso '(datos de prueba / mock)'. Incluye pruebas unitarias e integración del modo mock y documenta MODEL_BACKEND en .env.example.c136a98 -
chore(infra): contenedores, despliegue y scripts de arranque local
Añade Dockerfiles de backend y UI, docker-compose, render.yaml para el despliegue gratuito y los scripts PowerShell de arranque local sin Docker (run_backend, run_ui, dev) que usan 'python -m uvicorn' para evitar los shims .exe bloqueados por OneDrive. Incluye placeholders de models/ y sample_data/.c0f31a8 -
feat(backend): API FastAPI de conteo con modo standby
Implementa el backend del MVP: configuración por entorno, esquemas Pydantic, dominio de detección, métricas, adaptador de inferencia agnóstico (YOLO26/RF-DETR vía ONNX) y endpoints /api/status y /api/count. El conteo arranca en standby (COUNTING_ENABLED=false) y responde 503 hasta publicar el modelo.53371fd