Spaces:
Sleeping
Sleeping
Commit
·
c4a01de
1
Parent(s):
28f9d0d
feat: Add V3 API endpoints with file metadata - sessions list, history, and pipeline executions
Browse files- api_routes_v2.py +114 -0
- services/session_manager.py +42 -0
api_routes_v2.py
CHANGED
|
@@ -2470,6 +2470,120 @@ async def regenerate_file_url(file_id: str):
|
|
| 2470 |
raise HTTPException(status_code=404, detail=f"File not found: {str(e)}")
|
| 2471 |
|
| 2472 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2473 |
# ========================
|
| 2474 |
# HEALTH
|
| 2475 |
# ========================
|
|
|
|
| 2470 |
raise HTTPException(status_code=404, detail=f"File not found: {str(e)}")
|
| 2471 |
|
| 2472 |
|
| 2473 |
+
# V3 API Endpoints - Add to api_routes_v2.py before # HEALTH section
|
| 2474 |
+
|
| 2475 |
+
# ========================
|
| 2476 |
+
# V3 SESSIONS API
|
| 2477 |
+
# ========================
|
| 2478 |
+
|
| 2479 |
+
@router.get("/sessions")
|
| 2480 |
+
def get_all_sessions(limit: int = 100):
|
| 2481 |
+
"""Get all sessions sorted by last_activity with current_file metadata"""
|
| 2482 |
+
try:
|
| 2483 |
+
sessions = session_manager.get_all_sessions(limit=limit)
|
| 2484 |
+
return {"sessions": sessions}
|
| 2485 |
+
except Exception as e:
|
| 2486 |
+
raise HTTPException(status_code=500, detail=f"Failed to get sessions: {str(e)}")
|
| 2487 |
+
|
| 2488 |
+
|
| 2489 |
+
@router.get("/sessions/{session_id}/history")
|
| 2490 |
+
def get_session_complete_history(session_id: str, limit: int = 50):
|
| 2491 |
+
"""Get complete session history with file metadata (file, fileName, fileUrl)"""
|
| 2492 |
+
try:
|
| 2493 |
+
session = session_manager.get_session(session_id)
|
| 2494 |
+
if not session:
|
| 2495 |
+
raise HTTPException(status_code=404, detail="Session not found")
|
| 2496 |
+
|
| 2497 |
+
messages = session_manager.get_messages(session_id, limit=limit, include_content=True)
|
| 2498 |
+
|
| 2499 |
+
return {
|
| 2500 |
+
"session_id": session_id,
|
| 2501 |
+
"chat_name": session.get("chat_name"),
|
| 2502 |
+
"created_at": session.get("created_at"),
|
| 2503 |
+
"last_activity": session.get("last_activity"),
|
| 2504 |
+
"state": session.get("state"),
|
| 2505 |
+
"messages": messages
|
| 2506 |
+
}
|
| 2507 |
+
except HTTPException:
|
| 2508 |
+
raise
|
| 2509 |
+
except Exception as e:
|
| 2510 |
+
raise HTTPException(status_code=500, detail=f"Failed to get session history: {str(e)}")
|
| 2511 |
+
|
| 2512 |
+
|
| 2513 |
+
@router.get("/sessions/{session_id}/pipelines")
|
| 2514 |
+
def get_session_pipeline_executions(session_id: str, limit: int = 50):
|
| 2515 |
+
"""Get all pipeline executions for session with final_output_url"""
|
| 2516 |
+
try:
|
| 2517 |
+
from services.pipeline_manager import get_pipeline_manager
|
| 2518 |
+
|
| 2519 |
+
pipeline_mgr = get_pipeline_manager()
|
| 2520 |
+
pipelines = pipeline_mgr.get_session_pipelines(session_id, limit=limit)
|
| 2521 |
+
|
| 2522 |
+
return {
|
| 2523 |
+
"session_id": session_id,
|
| 2524 |
+
"pipelines": pipelines
|
| 2525 |
+
}
|
| 2526 |
+
except Exception as e:
|
| 2527 |
+
raise HTTPException(status_code=500, detail=f"Failed to get pipeline executions: {str(e)}")
|
| 2528 |
+
|
| 2529 |
+
|
| 2530 |
+
# V3 API Endpoints - Add to api_routes_v2.py before # HEALTH section
|
| 2531 |
+
|
| 2532 |
+
# ========================
|
| 2533 |
+
# V3 SESSIONS API
|
| 2534 |
+
# ========================
|
| 2535 |
+
|
| 2536 |
+
@router.get("/sessions")
|
| 2537 |
+
def get_all_sessions(limit: int = 100):
|
| 2538 |
+
"""Get all sessions sorted by last_activity with current_file metadata"""
|
| 2539 |
+
try:
|
| 2540 |
+
sessions = session_manager.get_all_sessions(limit=limit)
|
| 2541 |
+
return {"sessions": sessions}
|
| 2542 |
+
except Exception as e:
|
| 2543 |
+
raise HTTPException(status_code=500, detail=f"Failed to get sessions: {str(e)}")
|
| 2544 |
+
|
| 2545 |
+
|
| 2546 |
+
@router.get("/sessions/{session_id}/history")
|
| 2547 |
+
def get_session_complete_history(session_id: str, limit: int = 50):
|
| 2548 |
+
"""Get complete session history with file metadata (file, fileName, fileUrl)"""
|
| 2549 |
+
try:
|
| 2550 |
+
session = session_manager.get_session(session_id)
|
| 2551 |
+
if not session:
|
| 2552 |
+
raise HTTPException(status_code=404, detail="Session not found")
|
| 2553 |
+
|
| 2554 |
+
messages = session_manager.get_messages(session_id, limit=limit, include_content=True)
|
| 2555 |
+
|
| 2556 |
+
return {
|
| 2557 |
+
"session_id": session_id,
|
| 2558 |
+
"chat_name": session.get("chat_name"),
|
| 2559 |
+
"created_at": session.get("created_at"),
|
| 2560 |
+
"last_activity": session.get("last_activity"),
|
| 2561 |
+
"state": session.get("state"),
|
| 2562 |
+
"messages": messages
|
| 2563 |
+
}
|
| 2564 |
+
except HTTPException:
|
| 2565 |
+
raise
|
| 2566 |
+
except Exception as e:
|
| 2567 |
+
raise HTTPException(status_code=500, detail=f"Failed to get session history: {str(e)}")
|
| 2568 |
+
|
| 2569 |
+
|
| 2570 |
+
@router.get("/sessions/{session_id}/pipelines")
|
| 2571 |
+
def get_session_pipeline_executions(session_id: str, limit: int = 50):
|
| 2572 |
+
"""Get all pipeline executions for session with final_output_url"""
|
| 2573 |
+
try:
|
| 2574 |
+
from services.pipeline_manager import get_pipeline_manager
|
| 2575 |
+
|
| 2576 |
+
pipeline_mgr = get_pipeline_manager()
|
| 2577 |
+
pipelines = pipeline_mgr.get_session_pipelines(session_id, limit=limit)
|
| 2578 |
+
|
| 2579 |
+
return {
|
| 2580 |
+
"session_id": session_id,
|
| 2581 |
+
"pipelines": pipelines
|
| 2582 |
+
}
|
| 2583 |
+
except Exception as e:
|
| 2584 |
+
raise HTTPException(status_code=500, detail=f"Failed to get pipeline executions: {str(e)}")
|
| 2585 |
+
|
| 2586 |
+
|
| 2587 |
# ========================
|
| 2588 |
# HEALTH
|
| 2589 |
# ========================
|
services/session_manager.py
CHANGED
|
@@ -204,6 +204,18 @@ class SessionManager:
|
|
| 204 |
# If S3 fetch fails, use preview
|
| 205 |
msg["content"] = msg["content_preview"]
|
| 206 |
msg["file_data"] = {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 207 |
|
| 208 |
return messages
|
| 209 |
|
|
@@ -427,6 +439,36 @@ class SessionManager:
|
|
| 427 |
print("⚠️ save_pipeline_execution is deprecated. Use pipeline_manager instead.")
|
| 428 |
return True
|
| 429 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 430 |
def close(self):
|
| 431 |
"""Close MongoDB connection"""
|
| 432 |
if self.client:
|
|
|
|
| 204 |
# If S3 fetch fails, use preview
|
| 205 |
msg["content"] = msg["content_preview"]
|
| 206 |
msg["file_data"] = {}
|
| 207 |
+
|
| 208 |
+
# V3 API: Add file metadata fields
|
| 209 |
+
msg["file"] = False
|
| 210 |
+
if msg.get("file_id"):
|
| 211 |
+
try:
|
| 212 |
+
file_record = self.db["files"].find_one({"file_id": msg["file_id"]})
|
| 213 |
+
if file_record:
|
| 214 |
+
msg["file"] = True
|
| 215 |
+
msg["fileName"] = file_record["file_name"]
|
| 216 |
+
msg["fileUrl"] = file_record["presigned_url"]
|
| 217 |
+
except Exception as e:
|
| 218 |
+
print(f"⚠️ Failed to get file metadata: {e}")
|
| 219 |
|
| 220 |
return messages
|
| 221 |
|
|
|
|
| 439 |
print("⚠️ save_pipeline_execution is deprecated. Use pipeline_manager instead.")
|
| 440 |
return True
|
| 441 |
|
| 442 |
+
def get_all_sessions(self, limit: int = 100) -> List[Dict[str, Any]]:
|
| 443 |
+
"""
|
| 444 |
+
Get all sessions sorted by last_activity
|
| 445 |
+
Includes current_file metadata
|
| 446 |
+
"""
|
| 447 |
+
sessions = list(self.sessions_collection.find(
|
| 448 |
+
{},
|
| 449 |
+
{"_id": 0}
|
| 450 |
+
).sort("last_activity", -1).limit(limit))
|
| 451 |
+
|
| 452 |
+
# Add current file info to each session
|
| 453 |
+
for session in sessions:
|
| 454 |
+
session["file"] = False
|
| 455 |
+
|
| 456 |
+
if session.get("current_file_id"):
|
| 457 |
+
try:
|
| 458 |
+
file_record = self.db["files"].find_one({"file_id": session["current_file_id"]})
|
| 459 |
+
if file_record:
|
| 460 |
+
session["current_file"] = {
|
| 461 |
+
"file_id": file_record["file_id"],
|
| 462 |
+
"file_name": file_record["file_name"],
|
| 463 |
+
"file_url": file_record["presigned_url"],
|
| 464 |
+
"uploaded_at": file_record["uploaded_at"]
|
| 465 |
+
}
|
| 466 |
+
session["file"] = True
|
| 467 |
+
except Exception as e:
|
| 468 |
+
print(f"⚠️ Failed to get file info: {e}")
|
| 469 |
+
|
| 470 |
+
return sessions
|
| 471 |
+
|
| 472 |
def close(self):
|
| 473 |
"""Close MongoDB connection"""
|
| 474 |
if self.client:
|