Update app.py
Browse files
app.py
CHANGED
|
@@ -93,6 +93,28 @@ except Exception:
|
|
| 93 |
def get_category_for_mood(m): return "neutral"
|
| 94 |
def get_emoji(cat, intensity=0.5): return "🤖"
|
| 95 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 96 |
# Optional langdetect
|
| 97 |
try:
|
| 98 |
from langdetect import detect as detect_lang
|
|
@@ -162,6 +184,10 @@ engine_knowledge = create_engine(
|
|
| 162 |
|
| 163 |
app = FastAPI(title="Justice Brain — Backend")
|
| 164 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 165 |
# -------------------------
|
| 166 |
# Database schema creation
|
| 167 |
# -------------------------
|
|
@@ -1305,7 +1331,10 @@ async def model_status():
|
|
| 1305 |
"language_module": LANGUAGE_MODULE_AVAILABLE,
|
| 1306 |
"tts_available": TTS_AVAILABLE,
|
| 1307 |
"multipart_available": HAVE_MULTIPART,
|
| 1308 |
-
"pillow_available": PIL_AVAILABLE
|
|
|
|
|
|
|
|
|
|
| 1309 |
}
|
| 1310 |
|
| 1311 |
@app.get("/health")
|
|
@@ -1556,6 +1585,199 @@ async def clear_database(data: dict = Body(...), x_admin_key: str = Header(None,
|
|
| 1556 |
logger.exception("clear failed")
|
| 1557 |
return JSONResponse(status_code=500, content={"error": "failed to clear database", "details": str(e)})
|
| 1558 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1559 |
@app.get("/", response_class=HTMLResponse)
|
| 1560 |
async def frontend_dashboard():
|
| 1561 |
try:
|
|
|
|
| 93 |
def get_category_for_mood(m): return "neutral"
|
| 94 |
def get_emoji(cat, intensity=0.5): return "🤖"
|
| 95 |
|
| 96 |
+
# Import custom modules
|
| 97 |
+
try:
|
| 98 |
+
from voicecloner import synthesize_speech, is_available as tts_is_available, cache_speaker_sample
|
| 99 |
+
VOICECLONER_AVAILABLE = True
|
| 100 |
+
except Exception:
|
| 101 |
+
VOICECLONER_AVAILABLE = False
|
| 102 |
+
logger.warning("voicecloner module not available")
|
| 103 |
+
|
| 104 |
+
try:
|
| 105 |
+
from coder import Coder
|
| 106 |
+
CODER_AVAILABLE = True
|
| 107 |
+
except Exception:
|
| 108 |
+
CODER_AVAILABLE = False
|
| 109 |
+
logger.warning("coder module not available")
|
| 110 |
+
|
| 111 |
+
try:
|
| 112 |
+
from videogenerator import VideoGenerator
|
| 113 |
+
VIDEOGEN_AVAILABLE = True
|
| 114 |
+
except Exception:
|
| 115 |
+
VIDEOGEN_AVAILABLE = False
|
| 116 |
+
logger.warning("videogenerator module not available")
|
| 117 |
+
|
| 118 |
# Optional langdetect
|
| 119 |
try:
|
| 120 |
from langdetect import detect as detect_lang
|
|
|
|
| 184 |
|
| 185 |
app = FastAPI(title="Justice Brain — Backend")
|
| 186 |
|
| 187 |
+
# Initialize custom modules
|
| 188 |
+
coder_instance = Coder() if CODER_AVAILABLE else None
|
| 189 |
+
video_generator = VideoGenerator() if VIDEOGEN_AVAILABLE else None
|
| 190 |
+
|
| 191 |
# -------------------------
|
| 192 |
# Database schema creation
|
| 193 |
# -------------------------
|
|
|
|
| 1331 |
"language_module": LANGUAGE_MODULE_AVAILABLE,
|
| 1332 |
"tts_available": TTS_AVAILABLE,
|
| 1333 |
"multipart_available": HAVE_MULTIPART,
|
| 1334 |
+
"pillow_available": PIL_AVAILABLE,
|
| 1335 |
+
"voicecloner_available": VOICECLONER_AVAILABLE,
|
| 1336 |
+
"coder_available": CODER_AVAILABLE,
|
| 1337 |
+
"videogen_available": VIDEOGEN_AVAILABLE
|
| 1338 |
}
|
| 1339 |
|
| 1340 |
@app.get("/health")
|
|
|
|
| 1585 |
logger.exception("clear failed")
|
| 1586 |
return JSONResponse(status_code=500, content={"error": "failed to clear database", "details": str(e)})
|
| 1587 |
|
| 1588 |
+
# -------------------------
|
| 1589 |
+
# Coder endpoints
|
| 1590 |
+
# -------------------------
|
| 1591 |
+
@app.post("/coder/run")
|
| 1592 |
+
async def coder_run_code(data: dict = Body(...)):
|
| 1593 |
+
"""Execute code in sandbox"""
|
| 1594 |
+
if not CODER_AVAILABLE or coder_instance is None:
|
| 1595 |
+
raise HTTPException(status_code=503, detail="Coder module not available")
|
| 1596 |
+
|
| 1597 |
+
code = data.get("code", "")
|
| 1598 |
+
lang = data.get("language", "python")
|
| 1599 |
+
timeout = int(data.get("timeout", 15))
|
| 1600 |
+
|
| 1601 |
+
if not code:
|
| 1602 |
+
raise HTTPException(status_code=400, detail="Code is required")
|
| 1603 |
+
|
| 1604 |
+
try:
|
| 1605 |
+
result = coder_instance.run_code(code, lang, timeout)
|
| 1606 |
+
return result
|
| 1607 |
+
except Exception as e:
|
| 1608 |
+
logger.exception("Coder run failed")
|
| 1609 |
+
return JSONResponse(status_code=500, content={"error": str(e)})
|
| 1610 |
+
|
| 1611 |
+
@app.post("/coder/debug")
|
| 1612 |
+
async def coder_debug_code(data: dict = Body(...)):
|
| 1613 |
+
"""Debug code in sandbox"""
|
| 1614 |
+
if not CODER_AVAILABLE or coder_instance is None:
|
| 1615 |
+
raise HTTPException(status_code=503, detail="Coder module not available")
|
| 1616 |
+
|
| 1617 |
+
code = data.get("code", "")
|
| 1618 |
+
lang = data.get("language", "python")
|
| 1619 |
+
|
| 1620 |
+
if not code:
|
| 1621 |
+
raise HTTPException(status_code=400, detail="Code is required")
|
| 1622 |
+
|
| 1623 |
+
try:
|
| 1624 |
+
result = coder_instance.debug_code(code, lang)
|
| 1625 |
+
return result
|
| 1626 |
+
except Exception as e:
|
| 1627 |
+
logger.exception("Coder debug failed")
|
| 1628 |
+
return JSONResponse(status_code=500, content={"error": str(e)})
|
| 1629 |
+
|
| 1630 |
+
@app.post("/coder/preview/start")
|
| 1631 |
+
async def coder_start_preview(data: dict = Body(...)):
|
| 1632 |
+
"""Start preview server"""
|
| 1633 |
+
if not CODER_AVAILABLE or coder_instance is None:
|
| 1634 |
+
raise HTTPException(status_code=503, detail="Coder module not available")
|
| 1635 |
+
|
| 1636 |
+
lang = data.get("language", "html")
|
| 1637 |
+
port = int(data.get("port", 8000))
|
| 1638 |
+
|
| 1639 |
+
try:
|
| 1640 |
+
result = coder_instance.start_preview(lang, port)
|
| 1641 |
+
return result
|
| 1642 |
+
except Exception as e:
|
| 1643 |
+
logger.exception("Preview start failed")
|
| 1644 |
+
return JSONResponse(status_code=500, content={"error": str(e)})
|
| 1645 |
+
|
| 1646 |
+
@app.post("/coder/preview/stop")
|
| 1647 |
+
async def coder_stop_preview():
|
| 1648 |
+
"""Stop preview server"""
|
| 1649 |
+
if not CODER_AVAILABLE or coder_instance is None:
|
| 1650 |
+
raise HTTPException(status_code=503, detail="Coder module not available")
|
| 1651 |
+
|
| 1652 |
+
try:
|
| 1653 |
+
result = coder_instance.stop_preview()
|
| 1654 |
+
return result
|
| 1655 |
+
except Exception as e:
|
| 1656 |
+
logger.exception("Preview stop failed")
|
| 1657 |
+
return JSONResponse(status_code=500, content={"error": str(e)})
|
| 1658 |
+
|
| 1659 |
+
@app.get("/coder/preview/info")
|
| 1660 |
+
async def coder_preview_info():
|
| 1661 |
+
"""Get preview server info"""
|
| 1662 |
+
if not CODER_AVAILABLE or coder_instance is None:
|
| 1663 |
+
raise HTTPException(status_code=503, detail="Coder module not available")
|
| 1664 |
+
|
| 1665 |
+
try:
|
| 1666 |
+
result = coder_instance.get_preview_info()
|
| 1667 |
+
return result
|
| 1668 |
+
except Exception as e:
|
| 1669 |
+
logger.exception("Preview info failed")
|
| 1670 |
+
return JSONResponse(status_code=500, content={"error": str(e)})
|
| 1671 |
+
|
| 1672 |
+
@app.post("/coder/file/write")
|
| 1673 |
+
async def coder_write_file(data: dict = Body(...)):
|
| 1674 |
+
"""Write file to sandbox"""
|
| 1675 |
+
if not CODER_AVAILABLE or coder_instance is None:
|
| 1676 |
+
raise HTTPException(status_code=503, detail="Coder module not available")
|
| 1677 |
+
|
| 1678 |
+
filename = data.get("filename", "")
|
| 1679 |
+
content = data.get("content", "")
|
| 1680 |
+
|
| 1681 |
+
if not filename:
|
| 1682 |
+
raise HTTPException(status_code=400, detail="Filename is required")
|
| 1683 |
+
|
| 1684 |
+
try:
|
| 1685 |
+
result = coder_instance.write_file(filename, content)
|
| 1686 |
+
return result
|
| 1687 |
+
except Exception as e:
|
| 1688 |
+
logger.exception("File write failed")
|
| 1689 |
+
return JSONResponse(status_code=500, content={"error": str(e)})
|
| 1690 |
+
|
| 1691 |
+
@app.post("/coder/file/read")
|
| 1692 |
+
async def coder_read_file(data: dict = Body(...)):
|
| 1693 |
+
"""Read file from sandbox"""
|
| 1694 |
+
if not CODER_AVAILABLE or coder_instance is None:
|
| 1695 |
+
raise HTTPException(status_code=503, detail="Coder module not available")
|
| 1696 |
+
|
| 1697 |
+
filename = data.get("filename", "")
|
| 1698 |
+
|
| 1699 |
+
if not filename:
|
| 1700 |
+
raise HTTPException(status_code=400, detail="Filename is required")
|
| 1701 |
+
|
| 1702 |
+
try:
|
| 1703 |
+
result = coder_instance.read_file(filename)
|
| 1704 |
+
return result
|
| 1705 |
+
except Exception as e:
|
| 1706 |
+
logger.exception("File read failed")
|
| 1707 |
+
return JSONResponse(status_code=500, content={"error": str(e)})
|
| 1708 |
+
|
| 1709 |
+
@app.get("/coder/files")
|
| 1710 |
+
async def coder_list_files():
|
| 1711 |
+
"""List files in sandbox"""
|
| 1712 |
+
if not CODER_AVAILABLE or coder_instance is None:
|
| 1713 |
+
raise HTTPException(status_code=503, detail="Coder module not available")
|
| 1714 |
+
|
| 1715 |
+
try:
|
| 1716 |
+
result = coder_instance.list_files()
|
| 1717 |
+
return result
|
| 1718 |
+
except Exception as e:
|
| 1719 |
+
logger.exception("File list failed")
|
| 1720 |
+
return JSONResponse(status_code=500, content={"error": str(e)})
|
| 1721 |
+
|
| 1722 |
+
# -------------------------
|
| 1723 |
+
# Video Generator endpoints
|
| 1724 |
+
# -------------------------
|
| 1725 |
+
@app.post("/video/generate")
|
| 1726 |
+
async def video_generate(background_tasks: BackgroundTasks, data: dict = Body(...)):
|
| 1727 |
+
"""Generate video from prompt"""
|
| 1728 |
+
if not VIDEOGEN_AVAILABLE or video_generator is None:
|
| 1729 |
+
raise HTTPException(status_code=503, detail="Video generator not available")
|
| 1730 |
+
|
| 1731 |
+
prompt = data.get("prompt", "")
|
| 1732 |
+
num_frames = int(data.get("num_frames", 16))
|
| 1733 |
+
fps = int(data.get("fps", 8))
|
| 1734 |
+
enhance = bool(data.get("enhance", False))
|
| 1735 |
+
|
| 1736 |
+
if not prompt:
|
| 1737 |
+
raise HTTPException(status_code=400, detail="Prompt is required")
|
| 1738 |
+
|
| 1739 |
+
try:
|
| 1740 |
+
loop = asyncio.get_running_loop()
|
| 1741 |
+
result = await loop.run_in_executor(
|
| 1742 |
+
None,
|
| 1743 |
+
lambda: video_generator.generate(
|
| 1744 |
+
prompt=prompt,
|
| 1745 |
+
num_frames=num_frames,
|
| 1746 |
+
fps=fps,
|
| 1747 |
+
enhance=enhance
|
| 1748 |
+
)
|
| 1749 |
+
)
|
| 1750 |
+
return result
|
| 1751 |
+
except Exception as e:
|
| 1752 |
+
logger.exception("Video generation failed")
|
| 1753 |
+
return JSONResponse(status_code=500, content={"error": str(e)})
|
| 1754 |
+
|
| 1755 |
+
@app.get("/video/history")
|
| 1756 |
+
async def video_history(limit: int = Query(20)):
|
| 1757 |
+
"""Get video generation history"""
|
| 1758 |
+
if not VIDEOGEN_AVAILABLE or video_generator is None:
|
| 1759 |
+
raise HTTPException(status_code=503, detail="Video generator not available")
|
| 1760 |
+
|
| 1761 |
+
try:
|
| 1762 |
+
history = video_generator.get_history(limit)
|
| 1763 |
+
return {"history": history}
|
| 1764 |
+
except Exception as e:
|
| 1765 |
+
logger.exception("Video history failed")
|
| 1766 |
+
return JSONResponse(status_code=500, content={"error": str(e)})
|
| 1767 |
+
|
| 1768 |
+
@app.get("/video/status")
|
| 1769 |
+
async def video_status():
|
| 1770 |
+
"""Get video generator status"""
|
| 1771 |
+
if not VIDEOGEN_AVAILABLE or video_generator is None:
|
| 1772 |
+
raise HTTPException(status_code=503, detail="Video generator not available")
|
| 1773 |
+
|
| 1774 |
+
try:
|
| 1775 |
+
status = video_generator.get_status()
|
| 1776 |
+
return status
|
| 1777 |
+
except Exception as e:
|
| 1778 |
+
logger.exception("Video status failed")
|
| 1779 |
+
return JSONResponse(status_code=500, content={"error": str(e)})
|
| 1780 |
+
|
| 1781 |
@app.get("/", response_class=HTMLResponse)
|
| 1782 |
async def frontend_dashboard():
|
| 1783 |
try:
|