""" Grid Editor API — unified grid endpoints. """ import logging from fastapi import APIRouter, HTTPException from ocr_pipeline_session_store import ( get_session_db, update_session_db, ) logger = logging.getLogger(__name__) router = APIRouter(prefix="/api/v1/ocr-pipeline", tags=["grid-editor"]) @router.post("/sessions/{session_id}/build-unified-grid") async def build_unified_grid_endpoint(session_id: str): """Build a single-zone unified grid merging content + box zones. Takes the existing multi-zone grid_editor_result and produces a unified grid where boxes are integrated into the main row sequence. Persists as unified_grid_result (preserves original multi-zone data). """ session = await get_session_db(session_id) if not session: raise HTTPException(status_code=404, detail=f"Session {session_id} not found") grid_data = session.get("grid_editor_result") if not grid_data: raise HTTPException(status_code=400, detail="No grid data. Run build-grid first.") from unified_grid import build_unified_grid result = build_unified_grid( zones=grid_data.get("zones", []), image_width=grid_data.get("image_width", 0), image_height=grid_data.get("image_height", 0), layout_metrics=grid_data.get("layout_metrics", {}), ) # Persist as separate field (don't overwrite original multi-zone grid) await update_session_db(session_id, unified_grid_result=result) logger.info( "build-unified-grid session %s: %d rows, %d cells", session_id, result.get("summary", {}).get("total_rows", 0), result.get("summary", {}).get("total_cells", 0), ) return result @router.get("/sessions/{session_id}/unified-grid") async def get_unified_grid(session_id: str): """Retrieve the unified grid for a session.""" session = await get_session_db(session_id) if not session: raise HTTPException(status_code=404, detail=f"Session {session_id} not found") result = session.get("unified_grid_result") if not result: raise HTTPException( status_code=404, detail="No unified grid. Run build-unified-grid first.", ) return result